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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +0 -17
  3. data/lib/torque/postgresql/adapter/database_statements.rb +32 -74
  4. data/lib/torque/postgresql/adapter/oid/enum_set.rb +1 -1
  5. data/lib/torque/postgresql/adapter/oid.rb +0 -3
  6. data/lib/torque/postgresql/adapter/quoting.rb +12 -20
  7. data/lib/torque/postgresql/adapter/schema_creation.rb +1 -2
  8. data/lib/torque/postgresql/adapter/schema_definitions.rb +0 -37
  9. data/lib/torque/postgresql/adapter/schema_dumper.rb +2 -60
  10. data/lib/torque/postgresql/adapter/schema_statements.rb +2 -74
  11. data/lib/torque/postgresql/adapter.rb +2 -11
  12. data/lib/torque/postgresql/associations/belongs_to_many_association.rb +5 -4
  13. data/lib/torque/postgresql/associations/{association.rb → foreign_association.rb} +1 -4
  14. data/lib/torque/postgresql/associations/preloader/association.rb +53 -26
  15. data/lib/torque/postgresql/associations/preloader/loader_query.rb +36 -0
  16. data/lib/torque/postgresql/associations/preloader.rb +1 -0
  17. data/lib/torque/postgresql/associations.rb +6 -1
  18. data/lib/torque/postgresql/attributes/builder/period.rb +6 -2
  19. data/lib/torque/postgresql/auxiliary_statement/settings.rb +22 -75
  20. data/lib/torque/postgresql/auxiliary_statement.rb +40 -39
  21. data/lib/torque/postgresql/base.rb +13 -33
  22. data/lib/torque/postgresql/config.rb +3 -30
  23. data/lib/torque/postgresql/inheritance.rb +1 -3
  24. data/lib/torque/postgresql/migration/command_recorder.rb +2 -12
  25. data/lib/torque/postgresql/railtie.rb +1 -5
  26. data/lib/torque/postgresql/reflection/abstract_reflection.rb +44 -20
  27. data/lib/torque/postgresql/relation/auxiliary_statement.rb +15 -28
  28. data/lib/torque/postgresql/relation.rb +10 -12
  29. data/lib/torque/postgresql/schema_cache.rb +2 -7
  30. data/lib/torque/postgresql/version.rb +1 -1
  31. data/lib/torque/postgresql.rb +1 -2
  32. data/lib/torque-postgresql.rb +0 -1
  33. data/spec/schema.rb +5 -21
  34. data/spec/spec_helper.rb +1 -2
  35. data/spec/tests/arel_spec.rb +2 -4
  36. data/spec/tests/auxiliary_statement_spec.rb +35 -374
  37. data/spec/tests/belongs_to_many_spec.rb +2 -50
  38. data/spec/tests/enum_set_spec.rb +10 -10
  39. data/spec/tests/enum_spec.rb +0 -90
  40. data/spec/tests/has_many_spec.rb +0 -46
  41. data/spec/tests/table_inheritance_spec.rb +15 -11
  42. metadata +8 -28
  43. data/lib/torque/postgresql/auxiliary_statement/recursive.rb +0 -149
  44. data/lib/torque/postgresql/table_name.rb +0 -41
  45. data/lib/torque/range.rb +0 -22
  46. data/spec/models/category.rb +0 -2
  47. data/spec/models/internal/user.rb +0 -5
  48. data/spec/tests/range_spec.rb +0 -36
  49. 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
- ActiveRecord::Associations::Preloader.new.preload(entries, :tags, Tag.all)
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
@@ -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(:content_status)
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
- checker = /t\.enum +"conflicts", +array: true, +enum_type: :conflicts/
52
- expect(dump_result).to match checker
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
- checker = /t\.enum +"types", +default: \[:A, :B\], +array: true, +enum_type: :types/
57
- expect(dump_result).to match checker
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
 
@@ -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) }
@@ -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: "activities"'
86
- expect(dump_result).to match(/create_table #{parts} do /)
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: "activity_posts"'
94
- expect(dump_result).to match(/create_table #{parts}(?! do \|t\|)/)
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: (\["images", "activities"\]|\["activities", "images"\])'
102
- expect(dump_result).to match(/create_table #{parts}/)
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: 2.4.2
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: 2023-01-20 00:00:00.000000000 Z
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
- - me@carlosfsilva.com
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: '2.6'
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
@@ -1,2 +0,0 @@
1
- class Category < ActiveRecord::Base
2
- end
@@ -1,5 +0,0 @@
1
- module Internal
2
- class User < ActiveRecord::Base
3
- self.schema = 'internal'
4
- end
5
- end