torque-postgresql 2.4.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.rdoc +0 -17
- data/lib/torque/postgresql/adapter/database_statements.rb +32 -74
- data/lib/torque/postgresql/adapter/oid/enum_set.rb +1 -1
- data/lib/torque/postgresql/adapter/oid.rb +0 -3
- data/lib/torque/postgresql/adapter/quoting.rb +12 -20
- data/lib/torque/postgresql/adapter/schema_creation.rb +1 -2
- data/lib/torque/postgresql/adapter/schema_definitions.rb +0 -37
- data/lib/torque/postgresql/adapter/schema_dumper.rb +2 -60
- data/lib/torque/postgresql/adapter/schema_statements.rb +2 -74
- data/lib/torque/postgresql/adapter.rb +2 -11
- data/lib/torque/postgresql/associations/belongs_to_many_association.rb +5 -4
- data/lib/torque/postgresql/associations/{association.rb → foreign_association.rb} +1 -4
- data/lib/torque/postgresql/associations/preloader/association.rb +53 -26
- data/lib/torque/postgresql/associations/preloader/loader_query.rb +36 -0
- data/lib/torque/postgresql/associations/preloader.rb +1 -0
- data/lib/torque/postgresql/associations.rb +6 -1
- data/lib/torque/postgresql/attributes/builder/period.rb +6 -2
- data/lib/torque/postgresql/auxiliary_statement/settings.rb +22 -75
- data/lib/torque/postgresql/auxiliary_statement.rb +40 -39
- data/lib/torque/postgresql/base.rb +13 -33
- data/lib/torque/postgresql/config.rb +3 -30
- data/lib/torque/postgresql/inheritance.rb +1 -3
- data/lib/torque/postgresql/migration/command_recorder.rb +2 -12
- data/lib/torque/postgresql/railtie.rb +1 -5
- data/lib/torque/postgresql/reflection/abstract_reflection.rb +44 -20
- data/lib/torque/postgresql/relation/auxiliary_statement.rb +15 -28
- data/lib/torque/postgresql/relation.rb +10 -12
- data/lib/torque/postgresql/schema_cache.rb +2 -7
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/postgresql.rb +1 -2
- data/lib/torque-postgresql.rb +0 -1
- data/spec/schema.rb +5 -21
- data/spec/spec_helper.rb +1 -2
- data/spec/tests/arel_spec.rb +2 -4
- data/spec/tests/auxiliary_statement_spec.rb +35 -374
- data/spec/tests/belongs_to_many_spec.rb +2 -50
- data/spec/tests/enum_set_spec.rb +10 -10
- data/spec/tests/enum_spec.rb +0 -90
- data/spec/tests/has_many_spec.rb +0 -46
- data/spec/tests/table_inheritance_spec.rb +15 -11
- metadata +8 -28
- data/lib/torque/postgresql/auxiliary_statement/recursive.rb +0 -149
- data/lib/torque/postgresql/table_name.rb +0 -41
- data/lib/torque/range.rb +0 -22
- data/spec/models/category.rb +0 -2
- data/spec/models/internal/user.rb +0 -5
- data/spec/tests/range_spec.rb +0 -36
- data/spec/tests/schema_spec.rb +0 -134
@@ -344,7 +344,8 @@ RSpec.describe 'BelongsToMany' do
|
|
344
344
|
subject.tags.concat(records)
|
345
345
|
|
346
346
|
entries = Video.all
|
347
|
-
|
347
|
+
arguments = { records: entries, associations: :tags, available_records: Tag.all.to_a }
|
348
|
+
ActiveRecord::Associations::Preloader.new(**arguments).call
|
348
349
|
entries = entries.load
|
349
350
|
|
350
351
|
expect(entries.size).to be_eql(1)
|
@@ -392,53 +393,4 @@ RSpec.describe 'BelongsToMany' do
|
|
392
393
|
end
|
393
394
|
end
|
394
395
|
end
|
395
|
-
|
396
|
-
context 'using uuid' do
|
397
|
-
let(:connection) { ActiveRecord::Base.connection }
|
398
|
-
let(:game) { Class.new(ActiveRecord::Base) }
|
399
|
-
let(:player) { Class.new(ActiveRecord::Base) }
|
400
|
-
let(:other) { player.create }
|
401
|
-
|
402
|
-
# TODO: Set as a shred example
|
403
|
-
before do
|
404
|
-
connection.create_table(:players, id: :uuid) { |t| t.string :name }
|
405
|
-
connection.create_table(:games, id: :uuid) { |t| t.uuid :player_ids, array: true }
|
406
|
-
|
407
|
-
options = { anonymous_class: player, foreign_key: :player_ids }
|
408
|
-
options[:inverse_of] = false if Torque::PostgreSQL::AR610
|
409
|
-
|
410
|
-
game.table_name = 'games'
|
411
|
-
player.table_name = 'players'
|
412
|
-
game.belongs_to_many :players, **options
|
413
|
-
end
|
414
|
-
|
415
|
-
subject { game.create }
|
416
|
-
|
417
|
-
it 'loads associated records' do
|
418
|
-
subject.update(player_ids: [other.id])
|
419
|
-
expect(subject.players.to_sql).to be_eql(<<-SQL.squish)
|
420
|
-
SELECT "players".* FROM "players" WHERE "players"."id" IN ('#{other.id}')
|
421
|
-
SQL
|
422
|
-
|
423
|
-
expect(subject.players.load).to be_a(ActiveRecord::Associations::CollectionProxy)
|
424
|
-
expect(subject.players.to_a).to be_eql([other])
|
425
|
-
end
|
426
|
-
|
427
|
-
it 'can preload records' do
|
428
|
-
records = 5.times.map { player.create }
|
429
|
-
subject.players.concat(records)
|
430
|
-
|
431
|
-
entries = game.all.includes(:players).load
|
432
|
-
|
433
|
-
expect(entries.size).to be_eql(1)
|
434
|
-
expect(entries.first.players).to be_loaded
|
435
|
-
expect(entries.first.players.size).to be_eql(5)
|
436
|
-
end
|
437
|
-
|
438
|
-
it 'can joins records' do
|
439
|
-
query = game.all.joins(:players)
|
440
|
-
expect(query.to_sql).to match(/INNER JOIN "players"/)
|
441
|
-
expect { query.load }.not_to raise_error
|
442
|
-
end
|
443
|
-
end
|
444
396
|
end
|
data/spec/tests/enum_set_spec.rb
CHANGED
@@ -31,7 +31,8 @@ RSpec.describe 'Enum' do
|
|
31
31
|
it 'can be defined as an array' do
|
32
32
|
subject.enum(:content_status, array: true, enum_type: :content_status)
|
33
33
|
expect(subject['content_status'].name).to be_eql('content_status')
|
34
|
-
expect(subject['content_status'].type).to be_eql(:
|
34
|
+
expect(subject['content_status'].type).to be_eql(:enum)
|
35
|
+
expect(subject['content_status'].options[:enum_type]).to be_eql(:content_status)
|
35
36
|
|
36
37
|
array = subject['content_status'].respond_to?(:options) \
|
37
38
|
? subject['content_status'].options[:array] \
|
@@ -42,19 +43,18 @@ RSpec.describe 'Enum' do
|
|
42
43
|
end
|
43
44
|
|
44
45
|
context 'on schema' do
|
45
|
-
let(:dump_result) do
|
46
|
-
ActiveRecord::SchemaDumper.dump(connection, (dump_result = StringIO.new))
|
47
|
-
dump_result.string
|
48
|
-
end
|
49
|
-
|
50
46
|
it 'can be used on tables' do
|
51
|
-
|
52
|
-
|
47
|
+
dump_io = StringIO.new
|
48
|
+
checker = /t\.enum +"conflicts", +array: true, +enum_type: "conflicts"/
|
49
|
+
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
50
|
+
expect(dump_io.string).to match checker
|
53
51
|
end
|
54
52
|
|
55
53
|
xit 'can have a default value as an array of symbols' do
|
56
|
-
|
57
|
-
|
54
|
+
dump_io = StringIO.new
|
55
|
+
checker = /t\.enum +"types", +default: \[:A, :B\], +array: true, +enum_type: "types"/
|
56
|
+
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
57
|
+
expect(dump_io.string).to match checker
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
data/spec/tests/enum_spec.rb
CHANGED
@@ -26,12 +26,6 @@ RSpec.describe 'Enum' do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'on migration' do
|
29
|
-
it 'can be created' do
|
30
|
-
connection.create_enum(:status, %i(foo bar))
|
31
|
-
expect(connection.type_exists?(:status)).to be_truthy
|
32
|
-
expect(connection.enum_values(:status)).to be_eql(['foo', 'bar'])
|
33
|
-
end
|
34
|
-
|
35
29
|
it 'can be deleted' do
|
36
30
|
connection.create_enum(:status, %i(foo bar))
|
37
31
|
expect(connection.type_exists?(:status)).to be_truthy
|
@@ -46,16 +40,6 @@ RSpec.describe 'Enum' do
|
|
46
40
|
expect(connection.type_exists?(:status)).to be_truthy
|
47
41
|
end
|
48
42
|
|
49
|
-
it 'can have prefix' do
|
50
|
-
connection.create_enum(:status, %i(foo bar), prefix: true)
|
51
|
-
expect(connection.enum_values(:status)).to be_eql(['status_foo', 'status_bar'])
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'can have suffix' do
|
55
|
-
connection.create_enum(:status, %i(foo bar), suffix: 'tst')
|
56
|
-
expect(connection.enum_values(:status)).to be_eql(['foo_tst', 'bar_tst'])
|
57
|
-
end
|
58
|
-
|
59
43
|
it 'inserts values at the end' do
|
60
44
|
connection.create_enum(:status, %i(foo bar))
|
61
45
|
connection.add_enum_values(:status, %i(baz qux))
|
@@ -85,80 +69,6 @@ RSpec.describe 'Enum' do
|
|
85
69
|
end
|
86
70
|
end
|
87
71
|
|
88
|
-
context 'on table definition' do
|
89
|
-
subject { table_definition.new(connection, 'articles') }
|
90
|
-
|
91
|
-
it 'has the enum method' do
|
92
|
-
expect(subject).to respond_to(:enum)
|
93
|
-
end
|
94
|
-
|
95
|
-
it 'can be used in a single form' do
|
96
|
-
subject.enum('content_status')
|
97
|
-
expect(subject['content_status'].name).to be_eql('content_status')
|
98
|
-
expect(subject['content_status'].type).to be_eql(:content_status)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'can be used in a multiple form' do
|
102
|
-
subject.enum('foo', 'bar', 'baz', enum_type: :content_status)
|
103
|
-
expect(subject['foo'].type).to be_eql(:content_status)
|
104
|
-
expect(subject['bar'].type).to be_eql(:content_status)
|
105
|
-
expect(subject['baz'].type).to be_eql(:content_status)
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'can have custom type' do
|
109
|
-
subject.enum('foo', enum_type: :content_status)
|
110
|
-
expect(subject['foo'].name).to be_eql('foo')
|
111
|
-
expect(subject['foo'].type).to be_eql(:content_status)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'can use the deprecated subtype option' do
|
115
|
-
subject.enum('foo', subtype: :content_status)
|
116
|
-
expect(subject['foo'].name).to be_eql('foo')
|
117
|
-
expect(subject['foo'].type).to be_eql(:content_status)
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'raises StatementInvalid when type isn\'t defined' do
|
121
|
-
subject.enum('foo')
|
122
|
-
creation = connection.send(:schema_creation).accept subject
|
123
|
-
expect{ connection.execute creation }.to raise_error(ActiveRecord::StatementInvalid)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
context 'on schema' do
|
128
|
-
it 'dumps when has it' do
|
129
|
-
dump_io = StringIO.new
|
130
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
131
|
-
expect(dump_io.string).to match /create_enum \"content_status\", \[/
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'sorts the enum entries to better consistency' do
|
135
|
-
dump_io = StringIO.new
|
136
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
137
|
-
items = dump_io.string.scan(/create_enum "(\w+)"/).flatten
|
138
|
-
expect(items).to be_eql(items.sort)
|
139
|
-
end
|
140
|
-
|
141
|
-
it 'do not dump when has none' do
|
142
|
-
connection.drop_type(:content_status, force: :cascade)
|
143
|
-
|
144
|
-
dump_io = StringIO.new
|
145
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
146
|
-
expect(dump_io.string).not_to match /create_enum \"content_status\", \[/
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'can be used on tables too' do
|
150
|
-
dump_io = StringIO.new
|
151
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
152
|
-
expect(dump_io.string).to match /t\.enum +"status", +enum_type: :content_status/
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'can have a default value as symbol' do
|
156
|
-
dump_io = StringIO.new
|
157
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
158
|
-
expect(dump_io.string).to match /t\.enum +"role", +default: :visitor, +enum_type: :roles/
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
72
|
context 'on value' do
|
163
73
|
subject { Enum::ContentStatus }
|
164
74
|
let(:values) { %w(created draft published archived) }
|
data/spec/tests/has_many_spec.rb
CHANGED
@@ -411,50 +411,4 @@ RSpec.describe 'HasMany' do
|
|
411
411
|
expect { query.load }.not_to raise_error
|
412
412
|
end
|
413
413
|
end
|
414
|
-
|
415
|
-
context 'using uuid' do
|
416
|
-
let(:connection) { ActiveRecord::Base.connection }
|
417
|
-
let(:game) { Class.new(ActiveRecord::Base) }
|
418
|
-
let(:player) { Class.new(ActiveRecord::Base) }
|
419
|
-
|
420
|
-
# TODO: Set as a shred example
|
421
|
-
before do
|
422
|
-
connection.create_table(:players, id: :uuid) { |t| t.string :name }
|
423
|
-
connection.create_table(:games, id: :uuid) { |t| t.uuid :player_ids, array: true }
|
424
|
-
|
425
|
-
options = { anonymous_class: game, foreign_key: :player_ids }
|
426
|
-
options[:inverse_of] = false if Torque::PostgreSQL::AR610
|
427
|
-
|
428
|
-
game.table_name = 'games'
|
429
|
-
player.table_name = 'players'
|
430
|
-
player.has_many :games, array: true, **options
|
431
|
-
end
|
432
|
-
|
433
|
-
subject { player.create }
|
434
|
-
|
435
|
-
it 'loads associated records' do
|
436
|
-
expect(subject.games.to_sql).to match(Regexp.new(<<-SQL.squish))
|
437
|
-
SELECT "games"\\.\\* FROM "games"
|
438
|
-
WHERE \\(?"games"\\."player_ids" && ARRAY\\['#{subject.id}'\\]::uuid\\[\\]\\)?
|
439
|
-
SQL
|
440
|
-
|
441
|
-
expect(subject.games.load).to be_a(ActiveRecord::Associations::CollectionProxy)
|
442
|
-
expect(subject.games.to_a).to be_eql([])
|
443
|
-
end
|
444
|
-
|
445
|
-
it 'can preload records' do
|
446
|
-
5.times { game.create(player_ids: [subject.id]) }
|
447
|
-
entries = player.all.includes(:games).load
|
448
|
-
|
449
|
-
expect(entries.size).to be_eql(1)
|
450
|
-
expect(entries.first.games).to be_loaded
|
451
|
-
expect(entries.first.games.size).to be_eql(5)
|
452
|
-
end
|
453
|
-
|
454
|
-
it 'can joins records' do
|
455
|
-
query = player.all.joins(:games)
|
456
|
-
expect(query.to_sql).to match(/INNER JOIN "games"/)
|
457
|
-
expect { query.load }.not_to raise_error
|
458
|
-
end
|
459
|
-
end
|
460
414
|
end
|
@@ -73,33 +73,37 @@ RSpec.describe 'TableInheritance' do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
context 'on schema' do
|
76
|
-
let(:dump_result) do
|
77
|
-
ActiveRecord::SchemaDumper.dump(connection, (dump_result = StringIO.new))
|
78
|
-
dump_result.string
|
79
|
-
end
|
80
|
-
|
81
76
|
it 'dumps single inheritance with body' do
|
77
|
+
dump_io = StringIO.new
|
78
|
+
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
79
|
+
|
82
80
|
parts = '"activity_books"'
|
83
81
|
parts << ', id: false'
|
84
82
|
parts << ', force: :cascade'
|
85
|
-
parts << ', inherits:
|
86
|
-
expect(
|
83
|
+
parts << ', inherits: :activities'
|
84
|
+
expect(dump_io.string).to match(/create_table #{parts} do /)
|
87
85
|
end
|
88
86
|
|
89
87
|
it 'dumps single inheritance without body' do
|
88
|
+
dump_io = StringIO.new
|
89
|
+
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
90
|
+
|
90
91
|
parts = '"activity_post_samples"'
|
91
92
|
parts << ', id: false'
|
92
93
|
parts << ', force: :cascade'
|
93
|
-
parts << ', inherits:
|
94
|
-
expect(
|
94
|
+
parts << ', inherits: :activity_posts'
|
95
|
+
expect(dump_io.string).to match(/create_table #{parts}(?! do \|t\|)/)
|
95
96
|
end
|
96
97
|
|
97
98
|
it 'dumps multiple inheritance' do
|
99
|
+
dump_io = StringIO.new
|
100
|
+
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
101
|
+
|
98
102
|
parts = '"activity_posts"'
|
99
103
|
parts << ', id: false'
|
100
104
|
parts << ', force: :cascade'
|
101
|
-
parts << ', inherits: (\[
|
102
|
-
expect(
|
105
|
+
parts << ', inherits: (\[:images, :activities\]|\[:activities, :images\])'
|
106
|
+
expect(dump_io.string).to match(/create_table #{parts}/)
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
metadata
CHANGED
@@ -1,23 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: torque-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '6.0'
|
20
|
-
- - "<"
|
21
18
|
- !ruby/object:Gem::Version
|
22
19
|
version: '7.0'
|
23
20
|
type: :runtime
|
@@ -25,9 +22,6 @@ dependencies:
|
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '6.0'
|
30
|
-
- - "<"
|
31
25
|
- !ruby/object:Gem::Version
|
32
26
|
version: '7.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
@@ -161,7 +155,7 @@ dependencies:
|
|
161
155
|
description: Add support to complex resources of PostgreSQL, like data types, array
|
162
156
|
associations, and auxiliary statements (CTE)
|
163
157
|
email:
|
164
|
-
-
|
158
|
+
- carlinhus.fsilva@gmail.com
|
165
159
|
executables: []
|
166
160
|
extensions: []
|
167
161
|
extra_rdoc_files: []
|
@@ -195,14 +189,15 @@ files:
|
|
195
189
|
- lib/torque/postgresql/arel/select_manager.rb
|
196
190
|
- lib/torque/postgresql/arel/visitors.rb
|
197
191
|
- lib/torque/postgresql/associations.rb
|
198
|
-
- lib/torque/postgresql/associations/association.rb
|
199
192
|
- lib/torque/postgresql/associations/association_scope.rb
|
200
193
|
- lib/torque/postgresql/associations/belongs_to_many_association.rb
|
201
194
|
- lib/torque/postgresql/associations/builder.rb
|
202
195
|
- lib/torque/postgresql/associations/builder/belongs_to_many.rb
|
203
196
|
- lib/torque/postgresql/associations/builder/has_many.rb
|
197
|
+
- lib/torque/postgresql/associations/foreign_association.rb
|
204
198
|
- lib/torque/postgresql/associations/preloader.rb
|
205
199
|
- lib/torque/postgresql/associations/preloader/association.rb
|
200
|
+
- lib/torque/postgresql/associations/preloader/loader_query.rb
|
206
201
|
- lib/torque/postgresql/attributes.rb
|
207
202
|
- lib/torque/postgresql/attributes/builder.rb
|
208
203
|
- lib/torque/postgresql/attributes/builder/enum.rb
|
@@ -213,7 +208,6 @@ files:
|
|
213
208
|
- lib/torque/postgresql/attributes/period.rb
|
214
209
|
- lib/torque/postgresql/autosave_association.rb
|
215
210
|
- lib/torque/postgresql/auxiliary_statement.rb
|
216
|
-
- lib/torque/postgresql/auxiliary_statement/recursive.rb
|
217
211
|
- lib/torque/postgresql/auxiliary_statement/settings.rb
|
218
212
|
- lib/torque/postgresql/base.rb
|
219
213
|
- lib/torque/postgresql/collector.rb
|
@@ -238,9 +232,7 @@ files:
|
|
238
232
|
- lib/torque/postgresql/relation/inheritance.rb
|
239
233
|
- lib/torque/postgresql/relation/merger.rb
|
240
234
|
- lib/torque/postgresql/schema_cache.rb
|
241
|
-
- lib/torque/postgresql/table_name.rb
|
242
235
|
- lib/torque/postgresql/version.rb
|
243
|
-
- lib/torque/range.rb
|
244
236
|
- spec/en.yml
|
245
237
|
- spec/factories/authors.rb
|
246
238
|
- spec/factories/comments.rb
|
@@ -258,12 +250,10 @@ files:
|
|
258
250
|
- spec/models/activity_post/sample.rb
|
259
251
|
- spec/models/author.rb
|
260
252
|
- spec/models/author_journalist.rb
|
261
|
-
- spec/models/category.rb
|
262
253
|
- spec/models/comment.rb
|
263
254
|
- spec/models/course.rb
|
264
255
|
- spec/models/geometry.rb
|
265
256
|
- spec/models/guest_comment.rb
|
266
|
-
- spec/models/internal/user.rb
|
267
257
|
- spec/models/item.rb
|
268
258
|
- spec/models/post.rb
|
269
259
|
- spec/models/question.rb
|
@@ -289,27 +279,21 @@ files:
|
|
289
279
|
- spec/tests/lazy_spec.rb
|
290
280
|
- spec/tests/period_spec.rb
|
291
281
|
- spec/tests/quoting_spec.rb
|
292
|
-
- spec/tests/range_spec.rb
|
293
282
|
- spec/tests/relation_spec.rb
|
294
|
-
- spec/tests/schema_spec.rb
|
295
283
|
- spec/tests/table_inheritance_spec.rb
|
296
284
|
homepage: https://github.com/crashtech/torque-postgresql
|
297
285
|
licenses:
|
298
286
|
- MIT
|
299
|
-
metadata:
|
300
|
-
source_code_uri: https://github.com/crashtech/torque-postgresql
|
301
|
-
bug_tracker_uri: https://github.com/crashtech/torque-postgresql/issues
|
287
|
+
metadata: {}
|
302
288
|
post_install_message:
|
303
|
-
rdoc_options:
|
304
|
-
- "--title"
|
305
|
-
- Torque PostgreSQL
|
289
|
+
rdoc_options: []
|
306
290
|
require_paths:
|
307
291
|
- lib
|
308
292
|
required_ruby_version: !ruby/object:Gem::Requirement
|
309
293
|
requirements:
|
310
294
|
- - ">="
|
311
295
|
- !ruby/object:Gem::Version
|
312
|
-
version:
|
296
|
+
version: 2.7.2
|
313
297
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
314
298
|
requirements:
|
315
299
|
- - ">="
|
@@ -338,12 +322,10 @@ test_files:
|
|
338
322
|
- spec/models/activity_post.rb
|
339
323
|
- spec/models/author.rb
|
340
324
|
- spec/models/author_journalist.rb
|
341
|
-
- spec/models/category.rb
|
342
325
|
- spec/models/comment.rb
|
343
326
|
- spec/models/course.rb
|
344
327
|
- spec/models/geometry.rb
|
345
328
|
- spec/models/guest_comment.rb
|
346
|
-
- spec/models/internal/user.rb
|
347
329
|
- spec/models/item.rb
|
348
330
|
- spec/models/post.rb
|
349
331
|
- spec/models/question.rb
|
@@ -369,7 +351,5 @@ test_files:
|
|
369
351
|
- spec/tests/lazy_spec.rb
|
370
352
|
- spec/tests/period_spec.rb
|
371
353
|
- spec/tests/quoting_spec.rb
|
372
|
-
- spec/tests/range_spec.rb
|
373
354
|
- spec/tests/relation_spec.rb
|
374
|
-
- spec/tests/schema_spec.rb
|
375
355
|
- spec/tests/table_inheritance_spec.rb
|
@@ -1,149 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Torque
|
4
|
-
module PostgreSQL
|
5
|
-
class AuxiliaryStatement
|
6
|
-
class Recursive < AuxiliaryStatement
|
7
|
-
# Setup any additional option in the recursive mode
|
8
|
-
def initialize(*, **options)
|
9
|
-
super
|
10
|
-
|
11
|
-
@connect = options[:connect]&.to_a&.first
|
12
|
-
@union_all = options[:union_all]
|
13
|
-
@sub_query = options[:sub_query]
|
14
|
-
|
15
|
-
if options.key?(:with_depth)
|
16
|
-
@depth = options[:with_depth].values_at(:name, :start, :as)
|
17
|
-
@depth[0] ||= 'depth'
|
18
|
-
end
|
19
|
-
|
20
|
-
if options.key?(:with_path)
|
21
|
-
@path = options[:with_path].values_at(:name, :source, :as)
|
22
|
-
@path[0] ||= 'path'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
# Build the string or arel query
|
29
|
-
def build_query(base)
|
30
|
-
# Expose columns and get the list of the ones for select
|
31
|
-
columns = expose_columns(base, @query.try(:arel_table))
|
32
|
-
sub_columns = columns.dup
|
33
|
-
type = @union_all.present? ? 'all' : ''
|
34
|
-
|
35
|
-
# Build any extra columns that are dynamic and from the recursion
|
36
|
-
extra_columns(base, columns, sub_columns)
|
37
|
-
|
38
|
-
# Prepare the query depending on its type
|
39
|
-
if @query.is_a?(String) && @sub_query.is_a?(String)
|
40
|
-
args = @args.each_with_object({}) { |h, (k, v)| h[k] = base.connection.quote(v) }
|
41
|
-
::Arel.sql("(#{@query} UNION #{type.upcase} #{@sub_query})" % args)
|
42
|
-
elsif relation_query?(@query)
|
43
|
-
@query = @query.where(@where) if @where.present?
|
44
|
-
@bound_attributes.concat(@query.send(:bound_attributes))
|
45
|
-
|
46
|
-
if relation_query?(@sub_query)
|
47
|
-
@bound_attributes.concat(@sub_query.send(:bound_attributes))
|
48
|
-
|
49
|
-
sub_query = @sub_query.select(*sub_columns).arel
|
50
|
-
sub_query.from([@sub_query.arel_table, table])
|
51
|
-
else
|
52
|
-
sub_query = ::Arel.sql(@sub_query)
|
53
|
-
end
|
54
|
-
|
55
|
-
@query.select(*columns).arel.union(type, sub_query)
|
56
|
-
else
|
57
|
-
raise ArgumentError, <<-MSG.squish
|
58
|
-
Only String and ActiveRecord::Base objects are accepted as query and sub query
|
59
|
-
objects, #{@query.class.name} given for #{self.class.name}.
|
60
|
-
MSG
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Setup the statement using the class configuration
|
65
|
-
def prepare(base, settings)
|
66
|
-
super
|
67
|
-
|
68
|
-
prepare_sub_query(base, settings)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Make sure that both parts of the union are ready
|
72
|
-
def prepare_sub_query(base, settings)
|
73
|
-
@union_all = settings.union_all if @union_all.nil?
|
74
|
-
@sub_query ||= settings.sub_query
|
75
|
-
@depth ||= settings.depth
|
76
|
-
@path ||= settings.path
|
77
|
-
|
78
|
-
# Collect the connection
|
79
|
-
@connect ||= settings.connect || begin
|
80
|
-
key = base.primary_key
|
81
|
-
[key.to_sym, :"parent_#{key}"] unless key.nil?
|
82
|
-
end
|
83
|
-
|
84
|
-
raise ArgumentError, <<-MSG.squish if @sub_query.nil? && @query.is_a?(String)
|
85
|
-
Unable to generate sub query from a string query. Please provide a `sub_query`
|
86
|
-
property on the "#{table_name}" settings.
|
87
|
-
MSG
|
88
|
-
|
89
|
-
if @sub_query.nil?
|
90
|
-
raise ArgumentError, <<-MSG.squish if @connect.blank?
|
91
|
-
Unable to generate sub query without setting up a proper way to connect it
|
92
|
-
with the main query. Please provide a `connect` property on the "#{table_name}"
|
93
|
-
settings.
|
94
|
-
MSG
|
95
|
-
|
96
|
-
left, right = @connect.map(&:to_s)
|
97
|
-
condition = @query.arel_table[right].eq(table[left])
|
98
|
-
|
99
|
-
if @query.where_values_hash.key?(right)
|
100
|
-
@sub_query = @query.unscope(where: right.to_sym).where(condition)
|
101
|
-
else
|
102
|
-
@sub_query = @query.where(condition)
|
103
|
-
@query = @query.where(right => nil)
|
104
|
-
end
|
105
|
-
elsif @sub_query.respond_to?(:call)
|
106
|
-
# Call a proc to get the real sub query
|
107
|
-
call_args = @sub_query.try(:arity) === 0 ? [] : [OpenStruct.new(@args)]
|
108
|
-
@sub_query = @sub_query.call(*call_args)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Add depth and path if they were defined in settings
|
113
|
-
def extra_columns(base, columns, sub_columns)
|
114
|
-
return if @query.is_a?(String) || @sub_query.is_a?(String)
|
115
|
-
|
116
|
-
# Add the connect attribute to the query
|
117
|
-
if defined?(@connect)
|
118
|
-
columns.unshift(@query.arel_table[@connect[0]])
|
119
|
-
sub_columns.unshift(@sub_query.arel_table[@connect[0]])
|
120
|
-
end
|
121
|
-
|
122
|
-
# Build a column to represent the depth of the recursion
|
123
|
-
if @depth.present?
|
124
|
-
name, start, as = @depth
|
125
|
-
col = table[name]
|
126
|
-
base.select_extra_values += [col.as(as)] unless as.nil?
|
127
|
-
|
128
|
-
columns << ::Arel.sql(start.to_s).as(name)
|
129
|
-
sub_columns << (col + ::Arel.sql('1')).as(name)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Build a column to represent the path of the record access
|
133
|
-
if @path.present?
|
134
|
-
name, source, as = @path
|
135
|
-
source = @query.arel_table[source || @connect[0]]
|
136
|
-
|
137
|
-
col = table[name]
|
138
|
-
base.select_extra_values += [col.as(as)] unless as.nil?
|
139
|
-
parts = [col, source.cast(:varchar)]
|
140
|
-
|
141
|
-
columns << ::Arel.array([source]).cast(:varchar, true).as(name)
|
142
|
-
sub_columns << ::Arel::Nodes::NamedFunction.new('array_append', parts).as(name)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Torque
|
4
|
-
module PostgreSQL
|
5
|
-
class TableName < Delegator
|
6
|
-
def initialize(klass, table_name)
|
7
|
-
@klass = klass
|
8
|
-
@table_name = table_name
|
9
|
-
end
|
10
|
-
|
11
|
-
def schema
|
12
|
-
return @schema if defined?(@schema)
|
13
|
-
|
14
|
-
@schema = ([@klass] + @klass.module_parents[0..-2]).find do |klass|
|
15
|
-
next unless klass.respond_to?(:schema) && !(value = klass.schema).nil?
|
16
|
-
break value
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_s
|
21
|
-
schema.nil? ? @table_name : "#{schema}.#{@table_name}"
|
22
|
-
end
|
23
|
-
|
24
|
-
alias __getobj__ to_s
|
25
|
-
|
26
|
-
def ==(other)
|
27
|
-
other.to_s =~ /("?#{schema | search_path_schemes.join('|')}"?\.)?"?#{@table_name}"?/
|
28
|
-
end
|
29
|
-
|
30
|
-
def __setobj__(value)
|
31
|
-
@table_name = value
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def search_path_schemes
|
37
|
-
klass.connection.schemas_search_path_sanitized
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/torque/range.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Torque
|
2
|
-
module Range
|
3
|
-
def intersection(other)
|
4
|
-
ActiveSupport::Deprecation.warn('Range extensions will be removed in future versions')
|
5
|
-
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
6
|
-
|
7
|
-
new_min = self.cover?(other.min) ? other.min : other.cover?(min) ? min : nil
|
8
|
-
new_max = self.cover?(other.max) ? other.max : other.cover?(max) ? max : nil
|
9
|
-
|
10
|
-
new_min && new_max ? new_min..new_max : nil
|
11
|
-
end
|
12
|
-
alias_method :&, :intersection
|
13
|
-
|
14
|
-
def union(other)
|
15
|
-
ActiveSupport::Deprecation.warn('Range extensions will be removed in future versions')
|
16
|
-
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
17
|
-
|
18
|
-
([min, other.min].min)..([max, other.max].max)
|
19
|
-
end
|
20
|
-
alias_method :|, :union
|
21
|
-
end
|
22
|
-
end
|
data/spec/models/category.rb
DELETED