torque-postgresql 2.4.4 → 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 +7 -6
- 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/reflection/belongs_to_many_reflection.rb +2 -2
- 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 +14 -30
- 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 -99
- data/spec/tests/distinct_on_spec.rb +1 -1
- 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/relation_spec.rb +1 -1
- data/spec/tests/table_inheritance_spec.rb +15 -11
- metadata +11 -37
- 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
@@ -21,7 +21,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
result = 'WITH "comments" AS'
|
24
|
-
result << ' (SELECT "comments"."
|
24
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments")'
|
25
25
|
result << ' SELECT "users".*, "comments"."comment_content" FROM "users"'
|
26
26
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
27
27
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -34,7 +34,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
result = 'WITH "comments" AS (SELECT DISTINCT ON ( "comments"."user_id" )'
|
37
|
-
result << ' "comments"."
|
37
|
+
result << ' "comments"."user_id", "comments"."content" AS last_comment'
|
38
38
|
result << ' FROM "comments" ORDER BY "comments"."user_id" ASC,'
|
39
39
|
result << ' "comments"."id" DESC) SELECT "users".*,'
|
40
40
|
result << ' "comments"."last_comment" FROM "users" INNER JOIN "comments"'
|
@@ -49,7 +49,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
result = 'WITH "comments" AS'
|
52
|
-
result << ' (SELECT "comments"."
|
52
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content, "comments"."slug" AS comment_slug FROM "comments")'
|
53
53
|
result << ' SELECT "users".*, "comments"."comment_content", "comments"."comment_slug" FROM "users"'
|
54
54
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
55
55
|
expect(subject.with(:comments, select: {slug: :comment_slug}).arel.to_sql).to eql(result)
|
@@ -62,7 +62,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
62
62
|
end
|
63
63
|
|
64
64
|
result = 'WITH "comments" AS'
|
65
|
-
result << ' (SELECT "comments"."
|
65
|
+
result << ' (SELECT "comments"."user_id", "comments"."active", "comments"."content" AS comment_content FROM "comments")'
|
66
66
|
result << ' SELECT "users".*, "comments"."comment_content" FROM "users"'
|
67
67
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id" AND "comments"."active" = "users"."active"'
|
68
68
|
expect(subject.with(:comments, join: {active: :active}).arel.to_sql).to eql(result)
|
@@ -75,7 +75,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
75
75
|
end
|
76
76
|
|
77
77
|
result = 'WITH "comments" AS'
|
78
|
-
result << ' (SELECT "comments"."
|
78
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content'
|
79
79
|
result << ' FROM "comments" WHERE "comments"."active" = $1)'
|
80
80
|
result << ' SELECT "users".*, "comments"."comment_content" FROM "users"'
|
81
81
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
@@ -91,7 +91,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
91
91
|
query = subject.where(id: 2).with(:comments)
|
92
92
|
|
93
93
|
result = 'WITH "comments" AS'
|
94
|
-
result << ' (SELECT "comments"."
|
94
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments"'
|
95
95
|
result << ' WHERE "comments"."id" = $1)'
|
96
96
|
result << ' SELECT "users".*, "comments"."comment_content" FROM "users"'
|
97
97
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
@@ -108,7 +108,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
108
108
|
end
|
109
109
|
|
110
110
|
result = 'WITH "comments" AS'
|
111
|
-
result << ' (SELECT MAX(id) AS comment_id
|
111
|
+
result << ' (SELECT "comments"."user_id", MAX(id) AS comment_id FROM "comments")'
|
112
112
|
result << ' SELECT "users".*, "comments"."comment_id" FROM "users"'
|
113
113
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
114
114
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -121,7 +121,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
121
121
|
end
|
122
122
|
|
123
123
|
result = 'WITH "comments" AS'
|
124
|
-
result << ' (SELECT ROW_NUMBER() OVER (PARTITION BY ORDER BY "comments"."id") AS comment_id
|
124
|
+
result << ' (SELECT "comments"."user_id", ROW_NUMBER() OVER (PARTITION BY ORDER BY "comments"."id") AS comment_id FROM "comments")'
|
125
125
|
result << ' SELECT "users".*, "comments"."comment_id" FROM "users"'
|
126
126
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
127
127
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -134,7 +134,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
result = 'WITH "comments" AS'
|
137
|
-
result << ' (SELECT MIN("comments"."id") AS comment_id
|
137
|
+
result << ' (SELECT "comments"."user_id", MIN("comments"."id") AS comment_id FROM "comments")'
|
138
138
|
result << ' SELECT "users".*, "comments"."comment_id" FROM "users"'
|
139
139
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
140
140
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -147,8 +147,8 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
147
147
|
cte.join name: :id, 'a.col' => :col
|
148
148
|
end
|
149
149
|
|
150
|
-
result = 'WITH "comments" AS (SELECT "comments"."
|
151
|
-
result << ' "comments"."
|
150
|
+
result = 'WITH "comments" AS (SELECT "comments"."id", "comments"."col",'
|
151
|
+
result << ' "comments"."content" AS comment_content FROM "comments") SELECT "users".*,'
|
152
152
|
result << ' "comments"."comment_content" FROM "users" INNER JOIN "comments"'
|
153
153
|
result << ' ON "comments"."id" = "users"."name" AND "comments"."col" = "a"."col"'
|
154
154
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -161,8 +161,8 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
161
161
|
cte.join_type :left
|
162
162
|
end
|
163
163
|
|
164
|
-
result = 'WITH "comments" AS (SELECT "comments"."
|
165
|
-
result << ' "comments"."
|
164
|
+
result = 'WITH "comments" AS (SELECT "comments"."user_id",'
|
165
|
+
result << ' "comments"."content" AS comment_content FROM "comments") SELECT "users".*,'
|
166
166
|
result << ' "comments"."comment_content" FROM "users" LEFT OUTER JOIN "comments"'
|
167
167
|
result << ' ON "comments"."user_id" = "users"."id"'
|
168
168
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -177,7 +177,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
177
177
|
end
|
178
178
|
|
179
179
|
result = 'WITH "comments" AS'
|
180
|
-
result << ' (SELECT "comments"."
|
180
|
+
result << ' (SELECT "comments"."a_user_id", "comments"."content" AS sample_content FROM "comments")'
|
181
181
|
result << ' SELECT "users".*, "comments"."sample_content" FROM "users"'
|
182
182
|
result << ' INNER JOIN "comments" ON "comments"."a_user_id" = "users"."id"'
|
183
183
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -198,8 +198,8 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
198
198
|
query = subject.where(id: 3).with(:comments2)
|
199
199
|
|
200
200
|
result = 'WITH '
|
201
|
-
result << '"comments1" AS (SELECT "comments"."
|
202
|
-
result << '"comments2" AS (SELECT "comments"."
|
201
|
+
result << '"comments1" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content1 FROM "comments" WHERE "comments"."id" = $1), '
|
202
|
+
result << '"comments2" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content2 FROM "comments" WHERE "comments"."id" = $2)'
|
203
203
|
result << ' SELECT "users".*, "comments1"."comment_content1", "comments2"."comment_content2" FROM "users"'
|
204
204
|
result << ' INNER JOIN "comments1" ON "comments1"."user_id" = "users"."id"'
|
205
205
|
result << ' INNER JOIN "comments2" ON "comments2"."user_id" = "users"."id"'
|
@@ -225,8 +225,8 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
225
225
|
|
226
226
|
it 'can requires another statement as dependency' do
|
227
227
|
result = 'WITH '
|
228
|
-
result << '"comments1" AS (SELECT "comments"."
|
229
|
-
result << '"comments2" AS (SELECT "comments"."
|
228
|
+
result << '"comments1" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content1 FROM "comments"), '
|
229
|
+
result << '"comments2" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content2 FROM "comments")'
|
230
230
|
result << ' SELECT "users".*, "comments1"."comment_content1", "comments2"."comment_content2" FROM "users"'
|
231
231
|
result << ' INNER JOIN "comments1" ON "comments1"."user_id" = "users"."id"'
|
232
232
|
result << ' INNER JOIN "comments2" ON "comments2"."user_id" = "users"."id"'
|
@@ -235,8 +235,8 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
235
235
|
|
236
236
|
it 'can uses already already set dependent' do
|
237
237
|
result = 'WITH '
|
238
|
-
result << '"comments1" AS (SELECT "comments"."
|
239
|
-
result << '"comments2" AS (SELECT "comments"."
|
238
|
+
result << '"comments1" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content1 FROM "comments"), '
|
239
|
+
result << '"comments2" AS (SELECT "comments"."user_id", "comments"."content" AS comment_content2 FROM "comments")'
|
240
240
|
result << ' SELECT "users".*, "comments1"."comment_content1", "comments2"."comment_content2" FROM "users"'
|
241
241
|
result << ' INNER JOIN "comments1" ON "comments1"."user_id" = "users"."id"'
|
242
242
|
result << ' INNER JOIN "comments2" ON "comments2"."user_id" = "users"."id"'
|
@@ -289,14 +289,14 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
289
289
|
expect{ subject.with(:comments).arel.to_sql }.to raise_error(ArgumentError, /join columns/)
|
290
290
|
end
|
291
291
|
|
292
|
-
it '
|
292
|
+
it 'raises an error when not given the table name as first argument' do
|
293
293
|
klass.send(:auxiliary_statement, :comments) do |cte|
|
294
294
|
cte.query 'SELECT * FROM comments'
|
295
295
|
cte.attributes content: :comment
|
296
296
|
cte.join id: :user_id
|
297
297
|
end
|
298
298
|
|
299
|
-
expect{ subject.with(:comments).arel.to_sql }.
|
299
|
+
expect{ subject.with(:comments).arel.to_sql }.to raise_error(ArgumentError, /table name/)
|
300
300
|
end
|
301
301
|
end
|
302
302
|
|
@@ -309,7 +309,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
309
309
|
end
|
310
310
|
|
311
311
|
result = 'WITH "comments" AS'
|
312
|
-
result << ' (SELECT "comments"."
|
312
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment FROM "comments")'
|
313
313
|
result << ' SELECT "users".*, "comments"."comment" FROM "users"'
|
314
314
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
315
315
|
expect(subject.with(:comments).arel.to_sql).to eql(result)
|
@@ -352,7 +352,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
352
352
|
query = subject.with(:comments, args: {id: 1})
|
353
353
|
|
354
354
|
result = 'WITH "comments" AS'
|
355
|
-
result << ' (SELECT "comments"."
|
355
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment'
|
356
356
|
result << ' FROM "comments" WHERE "comments"."id" = $1)'
|
357
357
|
result << ' SELECT "users".*, "comments"."comment" FROM "users"'
|
358
358
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
@@ -370,14 +370,14 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
370
370
|
expect{ subject.with(:comments).arel.to_sql }.to raise_error(ArgumentError, /join columns/)
|
371
371
|
end
|
372
372
|
|
373
|
-
it '
|
373
|
+
it 'raises an error when not given the table name as first argument' do
|
374
374
|
klass.send(:auxiliary_statement, :comments) do |cte|
|
375
375
|
cte.query -> { Comment.all }
|
376
376
|
cte.attributes content: :comment
|
377
377
|
cte.join id: :user_id
|
378
378
|
end
|
379
379
|
|
380
|
-
expect{ subject.with(:comments).arel.to_sql }.
|
380
|
+
expect{ subject.with(:comments).arel.to_sql }.to raise_error(ArgumentError, /table name/)
|
381
381
|
end
|
382
382
|
|
383
383
|
it 'raises an error when the result of the proc is an invalid type' do
|
@@ -403,7 +403,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
403
403
|
end
|
404
404
|
|
405
405
|
result = 'WITH "authors" AS'
|
406
|
-
result << ' (SELECT "authors"."
|
406
|
+
result << ' (SELECT "authors"."id", "authors"."name" AS author_name FROM "authors")'
|
407
407
|
result << ' SELECT "activity_books".*, "authors"."author_name" FROM "activity_books"'
|
408
408
|
result << ' INNER JOIN "authors" ON "authors"."id" = "activity_books"."author_id"'
|
409
409
|
expect(subject.with(:authors).arel.to_sql).to eql(result)
|
@@ -423,7 +423,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
423
423
|
end
|
424
424
|
|
425
425
|
result = 'WITH "authors" AS'
|
426
|
-
result << ' (SELECT "authors"."
|
426
|
+
result << ' (SELECT "authors"."id", "authors"."type" AS author_type FROM "authors")'
|
427
427
|
result << ' SELECT "activity_books".*, "authors"."author_type" FROM "activity_books"'
|
428
428
|
result << ' INNER JOIN "authors" ON "authors"."id" = "activity_books"."author_id"'
|
429
429
|
expect(subject.with(:authors).arel.to_sql).to eql(result)
|
@@ -434,233 +434,6 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
434
434
|
end
|
435
435
|
end
|
436
436
|
|
437
|
-
context 'recursive' do
|
438
|
-
let(:klass) { Course }
|
439
|
-
|
440
|
-
it 'correctly build a recursive cte' do
|
441
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
442
|
-
cte.query Category.all
|
443
|
-
cte.join id: :parent_id
|
444
|
-
end
|
445
|
-
|
446
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
447
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
448
|
-
result << ' FROM "categories"'
|
449
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
450
|
-
result << ' UNION'
|
451
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
452
|
-
result << ' FROM "categories", "all_categories"'
|
453
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
454
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
455
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
456
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
457
|
-
end
|
458
|
-
|
459
|
-
it 'allows connect to be set to something different using a single value' do
|
460
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
461
|
-
cte.query Category.all
|
462
|
-
cte.join id: :parent_id
|
463
|
-
cte.connect :name
|
464
|
-
end
|
465
|
-
|
466
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
467
|
-
result << ' SELECT "categories"."name", "categories"."parent_id"'
|
468
|
-
result << ' FROM "categories"'
|
469
|
-
result << ' WHERE "categories"."parent_name" IS NULL'
|
470
|
-
result << ' UNION'
|
471
|
-
result << ' SELECT "categories"."name", "categories"."parent_id"'
|
472
|
-
result << ' FROM "categories", "all_categories"'
|
473
|
-
result << ' WHERE "categories"."parent_name" = "all_categories"."name"'
|
474
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
475
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
476
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
477
|
-
end
|
478
|
-
|
479
|
-
it 'allows a complete different set of connect' do
|
480
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
481
|
-
cte.query Category.all
|
482
|
-
cte.join id: :parent_id
|
483
|
-
cte.connect left: :right
|
484
|
-
end
|
485
|
-
|
486
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
487
|
-
result << ' SELECT "categories"."left", "categories"."parent_id"'
|
488
|
-
result << ' FROM "categories"'
|
489
|
-
result << ' WHERE "categories"."right" IS NULL'
|
490
|
-
result << ' UNION'
|
491
|
-
result << ' SELECT "categories"."left", "categories"."parent_id"'
|
492
|
-
result << ' FROM "categories", "all_categories"'
|
493
|
-
result << ' WHERE "categories"."right" = "all_categories"."left"'
|
494
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
495
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
496
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
497
|
-
end
|
498
|
-
|
499
|
-
it 'allows using an union all' do
|
500
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
501
|
-
cte.query Category.all
|
502
|
-
cte.join id: :parent_id
|
503
|
-
cte.union_all!
|
504
|
-
end
|
505
|
-
|
506
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
507
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
508
|
-
result << ' FROM "categories"'
|
509
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
510
|
-
result << ' UNION ALL'
|
511
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
512
|
-
result << ' FROM "categories", "all_categories"'
|
513
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
514
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
515
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
516
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
517
|
-
end
|
518
|
-
|
519
|
-
it 'allows having a complete different initiator' do
|
520
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
521
|
-
cte.query Category.where(parent_id: 5)
|
522
|
-
cte.join id: :parent_id
|
523
|
-
end
|
524
|
-
|
525
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
526
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
527
|
-
result << ' FROM "categories"'
|
528
|
-
result << ' WHERE "categories"."parent_id" = $1'
|
529
|
-
result << ' UNION'
|
530
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
531
|
-
result << ' FROM "categories", "all_categories"'
|
532
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
533
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
534
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
535
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
536
|
-
end
|
537
|
-
|
538
|
-
it 'can process the depth of the query' do
|
539
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
540
|
-
cte.query Category.all
|
541
|
-
cte.join id: :parent_id
|
542
|
-
cte.with_depth
|
543
|
-
end
|
544
|
-
|
545
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
546
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", 0 AS depth'
|
547
|
-
result << ' FROM "categories"'
|
548
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
549
|
-
result << ' UNION'
|
550
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ("all_categories"."depth" + 1) AS depth'
|
551
|
-
result << ' FROM "categories", "all_categories"'
|
552
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
553
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
554
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
555
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
556
|
-
end
|
557
|
-
|
558
|
-
it 'can process and expose the depth of the query' do
|
559
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
560
|
-
cte.query Category.all
|
561
|
-
cte.join id: :parent_id
|
562
|
-
cte.with_depth 'd', start: 10, as: :category_depth
|
563
|
-
end
|
564
|
-
|
565
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
566
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", 10 AS d'
|
567
|
-
result << ' FROM "categories"'
|
568
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
569
|
-
result << ' UNION'
|
570
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ("all_categories"."d" + 1) AS d'
|
571
|
-
result << ' FROM "categories", "all_categories"'
|
572
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
573
|
-
result << ' ) SELECT "courses".*, "all_categories"."d" AS category_depth FROM "courses" INNER JOIN "all_categories"'
|
574
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
575
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
576
|
-
end
|
577
|
-
|
578
|
-
it 'can process the path of the query' do
|
579
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
580
|
-
cte.query Category.all
|
581
|
-
cte.join id: :parent_id
|
582
|
-
cte.with_path
|
583
|
-
end
|
584
|
-
|
585
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
586
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ARRAY["categories"."id"]::varchar[] AS path'
|
587
|
-
result << ' FROM "categories"'
|
588
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
589
|
-
result << ' UNION'
|
590
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", array_append("all_categories"."path", "categories"."id"::varchar) AS path'
|
591
|
-
result << ' FROM "categories", "all_categories"'
|
592
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
593
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
594
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
595
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
596
|
-
end
|
597
|
-
|
598
|
-
it 'can process and expose the path of the query' do
|
599
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
600
|
-
cte.query Category.all
|
601
|
-
cte.join id: :parent_id
|
602
|
-
cte.with_path 'p', source: :name, as: :category_path
|
603
|
-
end
|
604
|
-
|
605
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
606
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ARRAY["categories"."name"]::varchar[] AS p'
|
607
|
-
result << ' FROM "categories"'
|
608
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
609
|
-
result << ' UNION'
|
610
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", array_append("all_categories"."p", "categories"."name"::varchar) AS p'
|
611
|
-
result << ' FROM "categories", "all_categories"'
|
612
|
-
result << ' WHERE "categories"."parent_id" = "all_categories"."id"'
|
613
|
-
result << ' ) SELECT "courses".*, "all_categories"."p" AS category_path FROM "courses" INNER JOIN "all_categories"'
|
614
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
615
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
616
|
-
end
|
617
|
-
|
618
|
-
it 'works with string queries' do
|
619
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
620
|
-
cte.query 'SELECT * FROM categories WHERE a IS NULL'
|
621
|
-
cte.sub_query 'SELECT * FROM categories, all_categories WHERE all_categories.a = b'
|
622
|
-
cte.join id: :parent_id
|
623
|
-
end
|
624
|
-
|
625
|
-
result = 'WITH RECURSIVE "all_categories" AS ('
|
626
|
-
result << 'SELECT * FROM categories WHERE a IS NULL'
|
627
|
-
result << ' UNION '
|
628
|
-
result << ' SELECT * FROM categories, all_categories WHERE all_categories.a = b'
|
629
|
-
result << ') SELECT "courses".* FROM "courses" INNER JOIN "all_categories"'
|
630
|
-
result << ' ON "all_categories"."parent_id" = "courses"."id"'
|
631
|
-
expect(subject.with(:all_categories).arel.to_sql).to eql(result)
|
632
|
-
end
|
633
|
-
|
634
|
-
it 'raises an error when query is a string and there is no sub query' do
|
635
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
636
|
-
cte.query 'SELECT * FROM categories WHERE a IS NULL'
|
637
|
-
cte.join id: :parent_id
|
638
|
-
end
|
639
|
-
|
640
|
-
expect{ subject.with(:all_categories).arel.to_sql }.to raise_error(ArgumentError, /generate sub query/)
|
641
|
-
end
|
642
|
-
|
643
|
-
it 'raises an error when sub query has an invalid type' do
|
644
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
645
|
-
cte.query 'SELECT * FROM categories WHERE a IS NULL'
|
646
|
-
cte.sub_query -> { 1 }
|
647
|
-
cte.join id: :parent_id
|
648
|
-
end
|
649
|
-
|
650
|
-
expect{ subject.with(:all_categories).arel.to_sql }.to raise_error(ArgumentError, /query and sub query objects/)
|
651
|
-
end
|
652
|
-
|
653
|
-
it 'raises an error when connect can be resolved automatically' do
|
654
|
-
allow(klass).to receive(:primary_key).and_return(nil)
|
655
|
-
klass.send(:recursive_auxiliary_statement, :all_categories) do |cte|
|
656
|
-
cte.query Category.all
|
657
|
-
cte.join id: :parent_id
|
658
|
-
end
|
659
|
-
|
660
|
-
expect{ subject.with(:all_categories).arel.to_sql }.to raise_error(ArgumentError, /setting up a proper way to connect/)
|
661
|
-
end
|
662
|
-
end
|
663
|
-
|
664
437
|
it 'works with count and does not add extra columns' do
|
665
438
|
klass.send(:auxiliary_statement, :comments) do |cte|
|
666
439
|
cte.query Comment.all
|
@@ -668,7 +441,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
668
441
|
end
|
669
442
|
|
670
443
|
result = 'WITH "comments" AS'
|
671
|
-
result << ' (SELECT "comments"."
|
444
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments")'
|
672
445
|
result << ' SELECT COUNT(*) FROM "users"'
|
673
446
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
674
447
|
|
@@ -683,7 +456,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
683
456
|
end
|
684
457
|
|
685
458
|
result = 'WITH "comments" AS'
|
686
|
-
result << ' (SELECT "comments"."
|
459
|
+
result << ' (SELECT "comments"."user_id", "comments"."id" AS value FROM "comments")'
|
687
460
|
result << ' SELECT SUM("comments"."value") FROM "users"'
|
688
461
|
result << ' INNER JOIN "comments" ON "comments"."user_id" = "users"."id"'
|
689
462
|
|
@@ -699,7 +472,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
699
472
|
expect{ subject.with(:comments).arel.to_sql }.to raise_error(ArgumentError, /object types/)
|
700
473
|
end
|
701
474
|
|
702
|
-
it 'raises an error when
|
475
|
+
it 'raises an error when traying to use a statement that is not defined' do
|
703
476
|
expect{ subject.with(:does_not_exist).arel.to_sql }.to raise_error(ArgumentError)
|
704
477
|
end
|
705
478
|
|
@@ -722,12 +495,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
722
495
|
expect(subject.protected_methods).to include(:auxiliary_statement)
|
723
496
|
end
|
724
497
|
|
725
|
-
it '
|
726
|
-
expect(subject.protected_methods).to include(:recursive_cte)
|
727
|
-
expect(subject.protected_methods).to include(:recursive_auxiliary_statement)
|
728
|
-
end
|
729
|
-
|
730
|
-
it 'allows configure new auxiliary statements' do
|
498
|
+
it 'allows configurate new auxiliary statements' do
|
731
499
|
subject.send(:auxiliary_statement, :cte1)
|
732
500
|
expect(subject.auxiliary_statements_list).to include(:cte1)
|
733
501
|
expect(subject.const_defined?('Cte1_AuxiliaryStatement')).to be_truthy
|
@@ -759,7 +527,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
759
527
|
query = subject.with(sample, select: {content: :comment_content}).arel.to_sql
|
760
528
|
|
761
529
|
result = 'WITH "comment" AS'
|
762
|
-
result << ' (SELECT "comments"."
|
530
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments")'
|
763
531
|
result << ' SELECT "users".*, "comment"."comment_content" FROM "users"'
|
764
532
|
result << ' INNER JOIN "comment" ON "comment"."user_id" = "users"."id"'
|
765
533
|
expect(query).to eql(result)
|
@@ -770,7 +538,7 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
770
538
|
query = subject.with(sample).arel.to_sql
|
771
539
|
|
772
540
|
result = 'WITH "comment" AS'
|
773
|
-
result << ' (SELECT "comments"."
|
541
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments")'
|
774
542
|
result << ' SELECT "users".*, "comment"."comment_content" FROM "users"'
|
775
543
|
result << ' INNER JOIN "comment" ON "comment"."user_id" = "users"."id"'
|
776
544
|
expect(query).to eql(result)
|
@@ -783,120 +551,13 @@ RSpec.describe 'AuxiliaryStatement' do
|
|
783
551
|
end
|
784
552
|
|
785
553
|
result = 'WITH "all_comments" AS'
|
786
|
-
result << ' (SELECT "comments"."
|
554
|
+
result << ' (SELECT "comments"."user_id", "comments"."content" AS comment_content FROM "comments")'
|
787
555
|
result << ' SELECT "users".*, "all_comments"."comment_content" FROM "users"'
|
788
556
|
result << ' INNER JOIN "all_comments" ON "all_comments"."user_id" = "users"."id"'
|
789
557
|
|
790
558
|
query = subject.with(sample).arel.to_sql
|
791
559
|
expect(query).to eql(result)
|
792
560
|
end
|
793
|
-
|
794
|
-
context 'recursive' do
|
795
|
-
let(:klass) { Torque::PostgreSQL::AuxiliaryStatement::Recursive }
|
796
|
-
subject { Course }
|
797
|
-
|
798
|
-
it 'has the external method available' do
|
799
|
-
expect(klass).to respond_to(:create)
|
800
|
-
end
|
801
|
-
|
802
|
-
it 'accepts simple recursive auxiliary statement definition' do
|
803
|
-
settings = { join: { id: :parent_id } }
|
804
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
805
|
-
|
806
|
-
result = 'WITH RECURSIVE "category" AS ('
|
807
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
808
|
-
result << ' FROM "categories"'
|
809
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
810
|
-
result << ' UNION'
|
811
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
812
|
-
result << ' FROM "categories", "category"'
|
813
|
-
result << ' WHERE "categories"."parent_id" = "category"."id"'
|
814
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "category"'
|
815
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
816
|
-
expect(query).to eql(result)
|
817
|
-
end
|
818
|
-
|
819
|
-
it 'accepts a connect option' do
|
820
|
-
settings = { join: { id: :parent_id }, connect: { a: :b } }
|
821
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
822
|
-
|
823
|
-
result = 'WITH RECURSIVE "category" AS ('
|
824
|
-
result << ' SELECT "categories"."a", "categories"."parent_id"'
|
825
|
-
result << ' FROM "categories"'
|
826
|
-
result << ' WHERE "categories"."b" IS NULL'
|
827
|
-
result << ' UNION'
|
828
|
-
result << ' SELECT "categories"."a", "categories"."parent_id"'
|
829
|
-
result << ' FROM "categories", "category"'
|
830
|
-
result << ' WHERE "categories"."b" = "category"."a"'
|
831
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "category"'
|
832
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
833
|
-
expect(query).to eql(result)
|
834
|
-
end
|
835
|
-
|
836
|
-
it 'accepts an union all option' do
|
837
|
-
settings = { join: { id: :parent_id }, union_all: true }
|
838
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
839
|
-
|
840
|
-
result = 'WITH RECURSIVE "category" AS ('
|
841
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
842
|
-
result << ' FROM "categories"'
|
843
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
844
|
-
result << ' UNION ALL'
|
845
|
-
result << ' SELECT "categories"."id", "categories"."parent_id"'
|
846
|
-
result << ' FROM "categories", "category"'
|
847
|
-
result << ' WHERE "categories"."parent_id" = "category"."id"'
|
848
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "category"'
|
849
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
850
|
-
expect(query).to eql(result)
|
851
|
-
end
|
852
|
-
|
853
|
-
it 'accepts a sub query option' do
|
854
|
-
settings = { join: { id: :parent_id }, sub_query: Category.where(active: true) }
|
855
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
856
|
-
|
857
|
-
result = 'WITH RECURSIVE "category" AS ('
|
858
|
-
result << ' SELECT "categories"."id", "categories"."parent_id" FROM "categories"'
|
859
|
-
result << ' UNION'
|
860
|
-
result << ' SELECT "categories"."id", "categories"."parent_id" FROM "categories", "category" WHERE "categories"."active" = $1'
|
861
|
-
result << ' ) SELECT "courses".* FROM "courses" INNER JOIN "category"'
|
862
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
863
|
-
expect(query).to eql(result)
|
864
|
-
end
|
865
|
-
|
866
|
-
it 'accepts a depth option' do
|
867
|
-
settings = { join: { id: :parent_id }, with_depth: { name: 'a', start: 5, as: 'b' } }
|
868
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
869
|
-
|
870
|
-
result = 'WITH RECURSIVE "category" AS ('
|
871
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", 5 AS a'
|
872
|
-
result << ' FROM "categories"'
|
873
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
874
|
-
result << ' UNION'
|
875
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ("category"."a" + 1) AS a'
|
876
|
-
result << ' FROM "categories", "category"'
|
877
|
-
result << ' WHERE "categories"."parent_id" = "category"."id"'
|
878
|
-
result << ' ) SELECT "courses".*, "category"."a" AS b FROM "courses" INNER JOIN "category"'
|
879
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
880
|
-
expect(query).to eql(result)
|
881
|
-
end
|
882
|
-
|
883
|
-
it 'accepts a path option' do
|
884
|
-
settings = { join: { id: :parent_id }, with_path: { name: 'a', source: 'b', as: 'c' } }
|
885
|
-
query = subject.with(klass.create(Category.all), **settings).arel.to_sql
|
886
|
-
|
887
|
-
result = 'WITH RECURSIVE "category" AS ('
|
888
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", ARRAY["categories"."b"]::varchar[] AS a'
|
889
|
-
result << ' FROM "categories"'
|
890
|
-
result << ' WHERE "categories"."parent_id" IS NULL'
|
891
|
-
result << ' UNION'
|
892
|
-
result << ' SELECT "categories"."id", "categories"."parent_id", array_append("category"."a", "categories"."b"::varchar) AS a'
|
893
|
-
result << ' FROM "categories", "category"'
|
894
|
-
result << ' WHERE "categories"."parent_id" = "category"."id"'
|
895
|
-
result << ' ) SELECT "courses".*, "category"."a" AS c FROM "courses" INNER JOIN "category"'
|
896
|
-
result << ' ON "category"."parent_id" = "courses"."id"'
|
897
|
-
expect(query).to eql(result)
|
898
|
-
end
|
899
|
-
end
|
900
561
|
end
|
901
562
|
|
902
563
|
context 'on settings' do
|