Skip to content

Commit 8919f05

Browse files
authored
v4.0 preview1 (#107)
* v4.0 preview1 * Final adjustments to version 4.0 * Allow exposing FN helper and change version * Change where to setup the FN helper
1 parent 920f750 commit 8919f05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+1996
-759
lines changed

.circleci/config.yml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,8 @@ references:
3939
test:
4040
matrix:
4141
parameters:
42-
ruby-version: ['2.7', '3.0', '3.1', '3.2']
43-
bundle-version: ['Gemfile.rails-7.0', 'Gemfile.rails-7.1', 'Gemfile.rails-7.2']
44-
exclude:
45-
- ruby-version: '2.7'
46-
bundle-version: 'Gemfile.rails-7.2'
47-
- ruby-version: '3.0'
48-
bundle-version: 'Gemfile.rails-7.2'
42+
ruby-version: ['3.2', '3.3']
43+
bundle-version: ['Gemfile.rails-8.0']
4944

5045
workflows:
5146
commit:

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<img src="./docs/assets/images/github.png" alt="Torque PostgreSQL - Advanced PG features in a seamlessly RoR interface" />
33
</a>
44

5-
[![CircleCI](https://circleci.com/gh/crashtech/torque-postgresql/tree/master_v2.svg?style=svg)](https://circleci.com/gh/crashtech/torque-postgresql/tree/master_v2)
5+
[![CircleCI](https://circleci.com/gh/crashtech/torque-postgresql/tree/master.svg?style=svg)](https://circleci.com/gh/crashtech/torque-postgresql/tree/master)
66
[![Code Climate](https://codeclimate.com/github/crashtech/torque-postgresql/badges/gpa.svg)](https://codeclimate.com/github/crashtech/torque-postgresql)
77
[![Gem Version](https://badge.fury.io/rb/torque-postgresql.svg)](https://badge.fury.io/rb/torque-postgresql)
88
<!--([![Test Coverage](https://codeclimate.com/github/crashtech/torque-postgresql/badges/coverage.svg)](https://codeclimate.com/github/crashtech/torque-postgresql/coverage))-->
@@ -25,7 +25,8 @@ gem 'torque-postgresql', '~> 2.0' # For Rails >= 6.0 < 6.1
2525
gem 'torque-postgresql', '~> 2.0.4' # For Rails >= 6.1
2626
gem 'torque-postgresql', '~> 3.0' # For Rails >= 7.0 < 7.1
2727
gem 'torque-postgresql', '~> 3.3' # For Rails >= 7.1 < 7.2
28-
gem 'torque-postgresql', '~> 3.4' # For Rails >= 7.2
28+
gem 'torque-postgresql', '~> 3.4' # For Rails >= 7.2 < 8.0
29+
gem 'torque-postgresql', '~> 4.0' # For Rails >= 8.0
2930
```
3031

3132
Also, run:
@@ -67,6 +68,8 @@ These are the currently available features:
6768
* [Inherited Tables](https://github.com/crashtech/torque-postgresql/wiki/Inherited-Tables)
6869
* [Insert All](https://github.com/crashtech/torque-postgresql/wiki/Insert-All)
6970
* [Multiple Schemas](https://github.com/crashtech/torque-postgresql/wiki/Multiple-Schemas)
71+
* Predicate Builder (DOCS Pending)
72+
* Full-Text Search (DOCS Pending)
7073

7174
# How to Contribute
7275

gemfiles/Gemfile.rails-7.1

Lines changed: 0 additions & 7 deletions
This file was deleted.

gemfiles/Gemfile.rails-7.2

Lines changed: 0 additions & 7 deletions
This file was deleted.

gemfiles/Gemfile.rails-7.0 renamed to gemfiles/Gemfile.rails-8.0

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
source 'https://rubygems.org'
22

3-
gem 'rails', '~> 7.0', '< 7.1'
3+
gem 'rails', '~> 8.0', '< 8.1'
44
gem 'pg', '~> 1.4.0'
55
gem "byebug"
66

lib/torque/postgresql.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@
1212
require 'torque/postgresql/version'
1313
require 'torque/postgresql/collector'
1414
require 'torque/postgresql/geometry_builder'
15+
require 'torque/postgresql/predicate_builder'
1516

1617
require 'torque/postgresql/i18n'
1718
require 'torque/postgresql/arel'
1819
require 'torque/postgresql/adapter'
1920
require 'torque/postgresql/associations'
2021
require 'torque/postgresql/attributes'
2122
require 'torque/postgresql/autosave_association'
22-
require 'torque/postgresql/auxiliary_statement'
2323
require 'torque/postgresql/inheritance'
2424
require 'torque/postgresql/base' # Needs to be after inheritance
2525
require 'torque/postgresql/insert_all'
@@ -28,5 +28,6 @@
2828
require 'torque/postgresql/reflection'
2929
require 'torque/postgresql/schema_cache'
3030
require 'torque/postgresql/table_name'
31+
require 'torque/postgresql/function'
3132

3233
require 'torque/postgresql/railtie' if defined?(Rails)

lib/torque/postgresql/adapter/database_statements.rb

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module PostgreSQL
55
module Adapter
66
module DatabaseStatements
77

8-
EXTENDED_DATABASE_TYPES = %i(enum enum_set interval)
8+
EXTENDED_DATABASE_TYPES = %i[enum enum_set interval]
99

1010
# Switch between dump mode or not
1111
def dump_mode!
@@ -48,8 +48,8 @@ def extended_types
4848
def schema_exists?(name, filtered: true)
4949
return user_defined_schemas.include?(name.to_s) if filtered
5050

51-
query_value(<<-SQL) == 1
52-
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = '#{name}'
51+
query_value(<<-SQL, "SCHEMA") == 1
52+
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = #{quote(name)}
5353
SQL
5454
end
5555

@@ -59,96 +59,75 @@ def type_exists?(name)
5959
end
6060
alias data_type_exists? type_exists?
6161

62-
# Configure the interval format
63-
def configure_connection
64-
super
65-
execute("SET SESSION IntervalStyle TO 'iso_8601'", 'SCHEMA')
66-
end
67-
68-
# Since enums create new types, type map needs to be rebooted to include
69-
# the new ones, both normal and array one
70-
def create_enum(name, *)
71-
super
72-
73-
oid = query_value("SELECT #{quote(name)}::regtype::oid", "SCHEMA").to_i
74-
load_additional_types([oid])
75-
end
76-
7762
# Change some of the types being mapped
7863
def initialize_type_map(m = type_map)
7964
super
80-
m.register_type 'box', OID::Box.new
81-
m.register_type 'circle', OID::Circle.new
82-
m.register_type 'interval', OID::Interval.new
83-
m.register_type 'line', OID::Line.new
84-
m.register_type 'segment', OID::Segment.new
8565

86-
m.alias_type 'regclass', 'varchar'
66+
if PostgreSQL.config.geometry.enabled
67+
m.register_type 'box', OID::Box.new
68+
m.register_type 'circle', OID::Circle.new
69+
m.register_type 'line', OID::Line.new
70+
m.register_type 'segment', OID::Segment.new
71+
end
72+
73+
if PostgreSQL.config.interval.enabled
74+
m.register_type 'interval', OID::Interval.new
75+
end
8776
end
8877

8978
# :nodoc:
9079
def load_additional_types(oids = nil)
80+
type_map.alias_type 'regclass', 'varchar'
81+
type_map.alias_type 'regconfig', 'varchar'
9182
super
9283
torque_load_additional_types(oids)
9384
end
9485

9586
# Add the composite types to be loaded too.
9687
def torque_load_additional_types(oids = nil)
97-
filter = ("AND a.typelem::integer IN (%s)" % oids.join(', ')) if oids
98-
99-
query = <<-SQL
100-
SELECT a.typelem AS oid, t.typname, t.typelem,
101-
t.typdelim, t.typbasetype, t.typtype,
102-
t.typarray
103-
FROM pg_type t
104-
INNER JOIN pg_type a ON (a.oid = t.typarray)
105-
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
106-
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
107-
AND t.typtype IN ( 'e' )
108-
#{filter}
109-
AND NOT EXISTS(
110-
SELECT 1 FROM pg_catalog.pg_type el
111-
WHERE el.oid = t.typelem AND el.typarray = t.oid
112-
)
113-
AND (t.typrelid = 0 OR (
114-
SELECT c.relkind = 'c' FROM pg_catalog.pg_class c
115-
WHERE c.oid = t.typrelid
116-
))
88+
return unless torque_load_additional_types?
89+
90+
# Types: (b)ase, (c)omposite, (d)omain, (e)num, (p)seudotype, (r)ange
91+
# (m)ultirange
92+
93+
query = <<~SQL
94+
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput,
95+
r.rngsubtype, t.typtype, t.typbasetype, t.typarray
96+
FROM pg_type as t
97+
LEFT JOIN pg_range as r ON oid = rngtypid
98+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
99+
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
117100
SQL
118101

119-
execute_and_clear(query, 'SCHEMA', []) do |records|
120-
records.each { |row| OID::Enum.create(row, type_map) }
102+
if oids
103+
query += " AND t.oid IN (%s)" % oids.join(", ")
104+
else
105+
query += " AND t.typtype IN ('e')"
121106
end
107+
108+
options = { allow_retry: true, materialize_transactions: false }
109+
internal_execute(query, 'SCHEMA', **options).each do |row|
110+
if row['typtype'] == 'e' && PostgreSQL.config.enum.enabled
111+
OID::Enum.create(row, type_map)
112+
end
113+
end
114+
end
115+
116+
def torque_load_additional_types?
117+
PostgreSQL.config.enum.enabled
122118
end
123119

124120
# Gets a list of user defined types.
125121
# You can even choose the +category+ filter
126122
def user_defined_types(*categories)
127-
category_condition = categories.present? \
128-
? "AND t.typtype IN ('#{categories.join("', '")}')" \
129-
: "AND t.typtype NOT IN ('b', 'd')"
130-
131-
select_all(<<-SQL, 'SCHEMA').rows.to_h
132-
SELECT t.typname AS name,
133-
CASE t.typtype
134-
WHEN 'e' THEN 'enum'
135-
END AS type
136-
FROM pg_type t
137-
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
123+
categories = categories.compact.presence || %w[c e p r m]
124+
125+
query(<<-SQL, 'SCHEMA').to_h
126+
SELECT t.typname, t.typtype
127+
FROM pg_type as t
128+
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
138129
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
139-
#{category_condition}
140-
AND NOT EXISTS(
141-
SELECT 1
142-
FROM pg_catalog.pg_type el
143-
WHERE el.oid = t.typelem
144-
AND el.typarray = t.oid
145-
)
146-
AND (t.typrelid = 0 OR (
147-
SELECT c.relkind = 'c'
148-
FROM pg_catalog.pg_class c
149-
WHERE c.oid = t.typrelid
150-
))
151-
ORDER BY t.typtype DESC
130+
AND t.typtype IN ('#{categories.join("', '")}')
152131
SQL
153132
end
154133

@@ -195,20 +174,20 @@ def user_defined_schemas_sql
195174
# Get the list of columns, and their definition, but only from the
196175
# actual table, does not include columns that comes from inherited table
197176
def column_definitions(table_name)
198-
local = 'AND a.attislocal' if @_dump_mode
199-
200-
query(<<-SQL, 'SCHEMA')
201-
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
202-
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
203-
c.collname, col_description(a.attrelid, a.attnum) AS comment,
204-
#{supports_virtual_columns? ? 'attgenerated' : quote('')} as attgenerated
205-
FROM pg_attribute a
206-
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
207-
LEFT JOIN pg_type t ON a.atttypid = t.oid
208-
LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
209-
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
210-
AND a.attnum > 0 AND NOT a.attisdropped #{local}
211-
ORDER BY a.attnum
177+
query(<<~SQL, "SCHEMA")
178+
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
179+
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
180+
c.collname, col_description(a.attrelid, a.attnum) AS comment,
181+
#{supports_identity_columns? ? 'attidentity' : quote('')} AS identity,
182+
#{supports_virtual_columns? ? 'attgenerated' : quote('')} as attgenerated
183+
FROM pg_attribute a
184+
LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
185+
LEFT JOIN pg_type t ON a.atttypid = t.oid
186+
LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
187+
WHERE a.attrelid = #{quote(quote_table_name(table_name))}::regclass
188+
AND a.attnum > 0 AND NOT a.attisdropped
189+
#{'AND a.attislocal' if @_dump_mode}
190+
ORDER BY a.attnum
212191
SQL
213192
end
214193

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,2 @@
1-
require_relative 'oid/box'
2-
require_relative 'oid/circle'
3-
require_relative 'oid/enum'
4-
require_relative 'oid/enum_set'
5-
require_relative 'oid/interval'
6-
require_relative 'oid/line'
1+
require_relative 'oid/array'
72
require_relative 'oid/range'
8-
require_relative 'oid/segment'
9-
10-
module Torque
11-
module PostgreSQL
12-
module Adapter
13-
module OID
14-
end
15-
16-
ActiveRecord::Type.register(:box, OID::Box, adapter: :postgresql)
17-
ActiveRecord::Type.register(:circle, OID::Circle, adapter: :postgresql)
18-
ActiveRecord::Type.register(:enum, OID::Enum, adapter: :postgresql)
19-
ActiveRecord::Type.register(:enum_set, OID::EnumSet, adapter: :postgresql)
20-
ActiveRecord::Type.register(:line, OID::Line, adapter: :postgresql)
21-
ActiveRecord::Type.register(:segment, OID::Segment, adapter: :postgresql)
22-
end
23-
end
24-
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module Torque
4+
module PostgreSQL
5+
module Adapter
6+
module OID
7+
module Array
8+
def force_equality?(value)
9+
PostgreSQL.config.predicate_builder.handle_array_attributes ? false : super
10+
end
11+
end
12+
13+
::ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Array.prepend(Array)
14+
end
15+
end
16+
end
17+
end

lib/torque/postgresql/adapter/oid/line.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,15 @@ class Line < Struct.new(:slope, :intercept)
77
alias c= intercept=
88

99
def a=(value)
10-
self.slope = vertical? \
11-
? Float::INFINITY \
12-
: Rational(value, b)
10+
self.slope = vertical? ? Float::INFINITY : Rational(value, b)
1311
end
1412

1513
def a
1614
slope.numerator
1715
end
1816

1917
def b=(value)
20-
self.slope = value.zero? \
21-
? Float::INFINITY \
22-
: Rational(a, value)
18+
self.slope = value.zero? ? Float::INFINITY : Rational(a, value)
2319
end
2420

2521
def b

0 commit comments

Comments
 (0)