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