torque-postgresql 2.4.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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