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.
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