veritas-sql-generator 0.0.3 → 0.0.4
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.
- data/.gemtest +0 -0
- data/.rvmrc +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +20 -10
- data/Guardfile +22 -0
- data/README.rdoc +2 -0
- data/Rakefile +4 -2
- data/TODO +16 -2
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/roodi.yml +5 -5
- data/config/site.reek +21 -19
- data/lib/veritas/sql/generator.rb +25 -2
- data/lib/veritas/sql/generator/core_ext/date.rb +20 -0
- data/lib/veritas/sql/generator/core_ext/date_time.rb +45 -0
- data/lib/veritas/sql/generator/direction.rb +3 -1
- data/lib/veritas/sql/generator/function.rb +54 -0
- data/lib/veritas/sql/generator/function/aggregate.rb +134 -0
- data/lib/veritas/sql/generator/function/connective.rb +53 -0
- data/lib/veritas/sql/generator/function/numeric.rb +135 -0
- data/lib/veritas/sql/generator/function/predicate.rb +266 -0
- data/lib/veritas/sql/generator/function/proposition.rb +38 -0
- data/lib/veritas/sql/generator/function/string.rb +29 -0
- data/lib/veritas/sql/generator/identifier.rb +2 -1
- data/lib/veritas/sql/generator/literal.rb +15 -18
- data/lib/veritas/sql/generator/relation.rb +144 -17
- data/lib/veritas/sql/generator/relation/binary.rb +16 -64
- data/lib/veritas/sql/generator/relation/set.rb +30 -22
- data/lib/veritas/sql/generator/relation/unary.rb +131 -78
- data/lib/veritas/sql/generator/version.rb +1 -1
- data/spec/unit/date/iso8601_spec.rb +23 -0
- data/spec/unit/date_time/iso_8601_spec.rb +115 -0
- data/spec/unit/veritas/sql/generator/class_methods/parenthesize_spec.rb +18 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_count_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_maximum_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_mean_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_minimum_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_standard_deviation_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_sum_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/aggregate/visit_veritas_aggregate_variance_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/function/connective/visit_veritas_function_connective_conjunction_spec.rb +20 -0
- data/spec/unit/veritas/sql/generator/function/connective/visit_veritas_function_connective_disjunction_spec.rb +20 -0
- data/spec/unit/veritas/sql/generator/function/connective/visit_veritas_function_connective_negation_spec.rb +20 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_absolute_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_addition_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_division_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_exponentiation_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_modulo_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_multiplication_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_square_root_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_subtraction_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_unary_minus_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/numeric/visit_veritas_function_numeric_unary_plus_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_equality_spec.rb → function/predicate/visit_veritas_function_predicate_equality_spec.rb} +5 -5
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_exclusion_spec.rb → function/predicate/visit_veritas_function_predicate_exclusion_spec.rb} +10 -6
- data/spec/unit/veritas/sql/generator/function/predicate/visit_veritas_function_predicate_greater_than_or_equal_to_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_greater_than_spec.rb → function/predicate/visit_veritas_function_predicate_greater_than_spec.rb} +5 -5
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_inclusion_spec.rb → function/predicate/visit_veritas_function_predicate_inclusion_spec.rb} +10 -6
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_inequality_spec.rb → function/predicate/visit_veritas_function_predicate_inequality_spec.rb} +8 -8
- data/spec/unit/veritas/sql/generator/function/predicate/visit_veritas_function_predicate_less_than_or_equal_to_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/{logic/visit_veritas_logic_predicate_less_than_spec.rb → function/predicate/visit_veritas_function_predicate_less_than_spec.rb} +5 -5
- data/spec/unit/veritas/sql/generator/function/proposition/visit_veritas_function_proposition_contradiction_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/proposition/visit_veritas_function_proposition_tautology_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/function/string/visit_veritas_function_string_length_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/literal/class_methods/dup_frozen_spec.rb +2 -2
- data/spec/unit/veritas/sql/generator/relation/binary/base/to_subquery_spec.rb +1 -1
- data/spec/unit/veritas/sql/generator/relation/binary/base/{visit_veritas_base_relation_spec.rb → visit_veritas_relation_base_spec.rb} +3 -3
- data/spec/unit/veritas/sql/generator/relation/binary/to_s_spec.rb +2 -2
- data/spec/unit/veritas/sql/generator/relation/binary/to_subquery_spec.rb +2 -2
- data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_join_spec.rb +74 -33
- data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_product_spec.rb +63 -19
- data/spec/unit/veritas/sql/generator/relation/class_methods/visit_spec.rb +1 -1
- data/spec/unit/veritas/sql/generator/relation/set/class_methods/normalize_operand_headers_spec.rb +35 -0
- data/spec/unit/veritas/sql/generator/relation/set/to_s_spec.rb +1 -1
- data/spec/unit/veritas/sql/generator/relation/set/to_subquery_spec.rb +4 -4
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_difference_spec.rb +83 -30
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_intersection_spec.rb +80 -30
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_union_spec.rb +80 -30
- data/spec/unit/veritas/sql/generator/relation/to_s_spec.rb +50 -0
- data/spec/unit/veritas/sql/generator/relation/to_subquery_spec.rb +49 -0
- data/spec/unit/veritas/sql/generator/relation/unary/to_s_spec.rb +1 -1
- data/spec/unit/veritas/sql/generator/relation/unary/to_subquery_spec.rb +6 -6
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_extension_spec.rb +165 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_projection_spec.rb +84 -29
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_rename_spec.rb +69 -27
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_restriction_spec.rb +64 -22
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_summarization_spec.rb +652 -0
- data/spec/unit/veritas/sql/generator/relation/unary/{visit_veritas_base_relation_spec.rb → visit_veritas_relation_base_spec.rb} +4 -4
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_limit_spec.rb +60 -20
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_offset_spec.rb +60 -20
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_order_spec.rb +63 -23
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_reverse_spec.rb +60 -20
- data/spec/unit/veritas/sql/generator/relation/visited_spec.rb +1 -1
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/{quality → metrics}/flay.rake +0 -0
- data/tasks/{quality → metrics}/flog.rake +0 -0
- data/tasks/{quality → metrics}/heckle.rake +1 -0
- data/tasks/{quality → metrics}/metric_fu.rake +3 -0
- data/tasks/{quality → metrics}/reek.rake +0 -0
- data/tasks/{quality → metrics}/roodi.rake +0 -0
- data/tasks/{quality → metrics}/yardstick.rake +0 -0
- data/tasks/spec.rake +1 -0
- data/veritas-sql-generator.gemspec +82 -114
- metadata +137 -125
- data/lib/veritas/base_relation.rb +0 -36
- data/lib/veritas/sql/generator/logic.rb +0 -349
- data/spec/unit/veritas/base_relation/name_spec.rb +0 -45
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_conjunction_spec.rb +0 -16
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_disjunction_spec.rb +0 -16
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_negation_spec.rb +0 -16
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_greater_than_or_equal_to_spec.rb +0 -15
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_less_than_or_equal_to_spec.rb +0 -15
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_contradiction_spec.rb +0 -15
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_tautology_spec.rb +0 -15
- data/spec/unit/veritas/sql/generator/relation/binary/class_methods/subquery_spec.rb +0 -42
- data/spec/unit/veritas/sql/generator/relation/class_methods/subquery_spec.rb +0 -33
- data/tasks/quality/ci.rake +0 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe SQL::Generator::Relation, '#to_subquery' do
|
|
6
|
+
subject { object.to_subquery }
|
|
7
|
+
|
|
8
|
+
let(:described_class) { Class.new(SQL::Generator::Relation) }
|
|
9
|
+
let(:id) { Attribute::Integer.new(:id) }
|
|
10
|
+
let(:name) { Attribute::String.new(:name) }
|
|
11
|
+
let(:age) { Attribute::Integer.new(:age, :required => false) }
|
|
12
|
+
let(:header) { [ id, name, age ] }
|
|
13
|
+
let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
|
|
14
|
+
let(:base_relation) { Relation::Base.new('users', header, body) }
|
|
15
|
+
let(:object) { described_class.new }
|
|
16
|
+
|
|
17
|
+
context 'when no object visited' do
|
|
18
|
+
it_should_behave_like 'an idempotent method'
|
|
19
|
+
|
|
20
|
+
it { should respond_to(:to_s) }
|
|
21
|
+
|
|
22
|
+
it { should be_frozen }
|
|
23
|
+
|
|
24
|
+
its(:to_s) { should == '' }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'when an object is visited' do
|
|
28
|
+
let(:visitable) { mock('Visitable') }
|
|
29
|
+
|
|
30
|
+
before do
|
|
31
|
+
described_class.class_eval do
|
|
32
|
+
def visit_spec_mocks_mock(mock)
|
|
33
|
+
@name = mock.instance_variable_get(:@name)
|
|
34
|
+
@scope = Set.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def generate_sql(columns)
|
|
38
|
+
"SELECT #{columns} FROM #{@name}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
object.visit(visitable)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it_should_behave_like 'a generated SQL expression'
|
|
46
|
+
|
|
47
|
+
its(:to_s) { should eql('(SELECT * FROM Visitable)') }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -10,7 +10,7 @@ describe SQL::Generator::Relation::Unary, '#to_s' do
|
|
|
10
10
|
let(:age) { Attribute::Integer.new(:age, :required => false) }
|
|
11
11
|
let(:header) { [ id, name, age ] }
|
|
12
12
|
let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
|
|
13
|
-
let(:base_relation) {
|
|
13
|
+
let(:base_relation) { Relation::Base.new('users', header, body) }
|
|
14
14
|
let(:object) { described_class.new }
|
|
15
15
|
|
|
16
16
|
context 'when no object visited' do
|
|
@@ -10,7 +10,7 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
10
10
|
let(:age) { Attribute::Integer.new(:age, :required => false) }
|
|
11
11
|
let(:header) { [ id, name, age ] }
|
|
12
12
|
let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
|
|
13
|
-
let(:base_relation) {
|
|
13
|
+
let(:base_relation) { Relation::Base.new('users', header, body) }
|
|
14
14
|
let(:object) { described_class.new }
|
|
15
15
|
|
|
16
16
|
context 'when no object visited' do
|
|
@@ -30,7 +30,7 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
30
30
|
|
|
31
31
|
it_should_behave_like 'a generated SQL expression'
|
|
32
32
|
|
|
33
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users"') }
|
|
33
|
+
its(:to_s) { should eql('(SELECT DISTINCT "id", "name" FROM "users")') }
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
context 'when a rename is visited' do
|
|
@@ -40,7 +40,7 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
40
40
|
|
|
41
41
|
it_should_behave_like 'a generated SQL expression'
|
|
42
42
|
|
|
43
|
-
its(:to_s) { should eql('SELECT "id" AS "user_id", "name", "age" FROM "users"') }
|
|
43
|
+
its(:to_s) { should eql('(SELECT "id" AS "user_id", "name", "age" FROM "users")') }
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
context 'when a restriction is visited' do
|
|
@@ -50,7 +50,7 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
50
50
|
|
|
51
51
|
it_should_behave_like 'a generated SQL expression'
|
|
52
52
|
|
|
53
|
-
its(:to_s) { should eql('SELECT * FROM "users" WHERE "id" = 1') }
|
|
53
|
+
its(:to_s) { should eql('(SELECT * FROM "users" WHERE "id" = 1)') }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
context 'when a limit is visited' do
|
|
@@ -60,7 +60,7 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
60
60
|
|
|
61
61
|
it_should_behave_like 'a generated SQL expression'
|
|
62
62
|
|
|
63
|
-
its(:to_s) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1') }
|
|
63
|
+
its(:to_s) { should eql('(SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1)') }
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
context 'when an offset is visited' do
|
|
@@ -70,6 +70,6 @@ describe SQL::Generator::Relation::Unary, '#to_subquery' do
|
|
|
70
70
|
|
|
71
71
|
it_should_behave_like 'a generated SQL expression'
|
|
72
72
|
|
|
73
|
-
its(:to_s) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1') }
|
|
73
|
+
its(:to_s) { should eql('(SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1)') }
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_extension' do
|
|
6
|
+
subject { object.visit_veritas_algebra_extension(extension) }
|
|
7
|
+
|
|
8
|
+
let(:relation_name) { 'users' }
|
|
9
|
+
let(:id) { Attribute::Integer.new(:id) }
|
|
10
|
+
let(:name) { Attribute::String.new(:name) }
|
|
11
|
+
let(:age) { Attribute::Integer.new(:age, :required => false) }
|
|
12
|
+
let(:header) { [ id, name, age ] }
|
|
13
|
+
let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
|
|
14
|
+
let(:base_relation) { Relation::Base.new(relation_name, header, body) }
|
|
15
|
+
let(:extension) { operand.extend { |r| r.add(:one, 1) } }
|
|
16
|
+
let(:object) { described_class.new }
|
|
17
|
+
|
|
18
|
+
context 'when the operand is a base relation' do
|
|
19
|
+
let(:operand) { base_relation }
|
|
20
|
+
|
|
21
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
22
|
+
|
|
23
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users"') }
|
|
24
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users")') }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'when the operand is a projection' do
|
|
28
|
+
let(:operand) { base_relation.project([ :id, :name ]) }
|
|
29
|
+
|
|
30
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
31
|
+
|
|
32
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name", 1 AS "one" FROM "users"') }
|
|
33
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name", 1 AS "one" FROM "users")') }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when the operand is an extension' do
|
|
37
|
+
let(:operand) { base_relation.extend { |r| r.add(:two, 2) } }
|
|
38
|
+
|
|
39
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
40
|
+
|
|
41
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", "two", 1 AS "one" FROM (SELECT *, 2 AS "two" FROM "users") AS "users"') }
|
|
42
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT *, 2 AS "two" FROM "users") AS "users")') }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'when the operand is a rename' do
|
|
46
|
+
let(:operand) { base_relation.rename(:id => :user_id) }
|
|
47
|
+
|
|
48
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
49
|
+
|
|
50
|
+
its(:to_s) { should eql('SELECT "user_id", "name", "age", 1 AS "one" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users"') }
|
|
51
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users")') }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'when the operand is a restriction' do
|
|
55
|
+
let(:operand) { base_relation.restrict { |r| r[:id].eq(1) } }
|
|
56
|
+
|
|
57
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
58
|
+
|
|
59
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users" WHERE "id" = 1') }
|
|
60
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users" WHERE "id" = 1)') }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'when the operand is a summarization' do
|
|
64
|
+
context 'summarize per table dee' do
|
|
65
|
+
let(:summarize_per) { TABLE_DEE }
|
|
66
|
+
let(:operand) { base_relation.summarize(summarize_per) { |r| r.add(:count, r[:id].count) } }
|
|
67
|
+
|
|
68
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
69
|
+
|
|
70
|
+
its(:to_s) { should eql('SELECT "count", 1 AS "one" FROM (SELECT COUNT ("id") AS "count" FROM "users") AS "users"') }
|
|
71
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT COUNT ("id") AS "count" FROM "users") AS "users")') }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'summarize per table dum' do
|
|
75
|
+
let(:summarize_per) { TABLE_DUM }
|
|
76
|
+
let(:operand) { base_relation.summarize(summarize_per) { |r| r.add(:count, r[:id].count) } }
|
|
77
|
+
|
|
78
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
79
|
+
|
|
80
|
+
its(:to_s) { should eql('SELECT "count", 1 AS "one" FROM (SELECT COUNT ("id") AS "count" FROM "users" HAVING FALSE) AS "users"') }
|
|
81
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT COUNT ("id") AS "count" FROM "users" HAVING FALSE) AS "users")') }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context 'summarize by a subset of the operand header' do
|
|
85
|
+
let(:operand) { base_relation.summarize([ :id, :name ]) { |r| r.add(:count, r[:age].count) } }
|
|
86
|
+
|
|
87
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
88
|
+
|
|
89
|
+
its(:to_s) { should eql('SELECT "id", "name", "count", 1 AS "one" FROM (SELECT "id", "name", COUNT ("age") AS "count" FROM "users" GROUP BY "id", "name" HAVING COUNT (*) > 0) AS "users"') }
|
|
90
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT "id", "name", COUNT ("age") AS "count" FROM "users" GROUP BY "id", "name" HAVING COUNT (*) > 0) AS "users")') }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
context 'when the operand is ordered' do
|
|
95
|
+
let(:operand) { base_relation.order }
|
|
96
|
+
|
|
97
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
98
|
+
|
|
99
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users" ORDER BY "id", "name", "age"') }
|
|
100
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users" ORDER BY "id", "name", "age")') }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'when the operand is reversed' do
|
|
104
|
+
let(:operand) { base_relation.order.reverse }
|
|
105
|
+
|
|
106
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
107
|
+
|
|
108
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
|
|
109
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC)') }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'when the operand is limited' do
|
|
113
|
+
let(:operand) { base_relation.order.take(1) }
|
|
114
|
+
|
|
115
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
116
|
+
|
|
117
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users" ORDER BY "id", "name", "age" LIMIT 1') }
|
|
118
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users" ORDER BY "id", "name", "age" LIMIT 1)') }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
context 'when the operand is an offset' do
|
|
122
|
+
let(:operand) { base_relation.order.drop(1) }
|
|
123
|
+
|
|
124
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
125
|
+
|
|
126
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM "users" ORDER BY "id", "name", "age" OFFSET 1') }
|
|
127
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM "users" ORDER BY "id", "name", "age" OFFSET 1)') }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'when the operand is a difference' do
|
|
131
|
+
let(:operand) { base_relation.difference(base_relation) }
|
|
132
|
+
|
|
133
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
134
|
+
|
|
135
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") EXCEPT (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
136
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") EXCEPT (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
context 'when the operand is an intersection' do
|
|
140
|
+
let(:operand) { base_relation.intersect(base_relation) }
|
|
141
|
+
|
|
142
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
143
|
+
|
|
144
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") INTERSECT (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
145
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") INTERSECT (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context 'when the operand is a union' do
|
|
149
|
+
let(:operand) { base_relation.union(base_relation) }
|
|
150
|
+
|
|
151
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
152
|
+
|
|
153
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") UNION (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
154
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM ((SELECT "id", "name", "age" FROM "users") UNION (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context 'when the operand is a join' do
|
|
158
|
+
let(:operand) { base_relation.join(base_relation) }
|
|
159
|
+
|
|
160
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
161
|
+
|
|
162
|
+
its(:to_s) { should eql('SELECT "id", "name", "age", 1 AS "one" FROM (SELECT * FROM "users" AS "left" NATURAL JOIN "users" AS "right") AS "users"') }
|
|
163
|
+
its(:to_subquery) { should eql('(SELECT *, 1 AS "one" FROM (SELECT * FROM "users" AS "left" NATURAL JOIN "users" AS "right") AS "users")') }
|
|
164
|
+
end
|
|
165
|
+
end
|
data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_projection_spec.rb
CHANGED
|
@@ -11,7 +11,7 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
11
11
|
let(:age) { Attribute::Integer.new(:age, :required => false) }
|
|
12
12
|
let(:header) { [ id, name, age ] }
|
|
13
13
|
let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
|
|
14
|
-
let(:base_relation) {
|
|
14
|
+
let(:base_relation) { Relation::Base.new(relation_name, header, body) }
|
|
15
15
|
let(:projection) { operand.project([ :id, :name ]) }
|
|
16
16
|
let(:object) { described_class.new }
|
|
17
17
|
|
|
@@ -20,8 +20,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
20
20
|
|
|
21
21
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
22
22
|
|
|
23
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users"')
|
|
24
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM "users"') }
|
|
23
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users"') }
|
|
24
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM "users")') }
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
context 'when the operand is a projection' do
|
|
@@ -29,14 +29,37 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
29
29
|
|
|
30
30
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
31
31
|
|
|
32
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users"')
|
|
33
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM "users"') }
|
|
32
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users"') }
|
|
33
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM "users")') }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when the operand is an extension' do
|
|
37
|
+
let(:operand) { base_relation.extend { |r| r.add(:one, 1) } }
|
|
38
|
+
|
|
39
|
+
context 'when the projection includes the extended column' do
|
|
40
|
+
let(:projection) { operand.project([ :id, :name, :one ]) }
|
|
41
|
+
|
|
42
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
43
|
+
|
|
44
|
+
its(:to_s) { pending { should eql('SELECT DISTINCT "id", "name", 1 AS "one" FROM "users"') } }
|
|
45
|
+
its(:to_subquery) { pending { should eql('SELECT DISTINCT "id", "name", 1 AS "one" FROM "users"') } }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'when the projection does not include the extended column' do
|
|
49
|
+
let(:projection) { operand.project([ :id, :name ]) }
|
|
50
|
+
|
|
51
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
52
|
+
|
|
53
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT *, 1 AS "one" FROM "users") AS "users"') }
|
|
54
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT *, 1 AS "one" FROM "users") AS "users")') }
|
|
55
|
+
end
|
|
34
56
|
end
|
|
35
57
|
|
|
36
58
|
context 'when the operand is a rename' do
|
|
59
|
+
let(:operand) { base_relation.rename(:id => :user_id) }
|
|
60
|
+
|
|
37
61
|
context 'when the projection includes the renamed column' do
|
|
38
|
-
let(:
|
|
39
|
-
let(:projection) { operand.project([ :user_id, :name ]) }
|
|
62
|
+
let(:projection) { operand.project([ :user_id, :name ]) }
|
|
40
63
|
|
|
41
64
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
42
65
|
|
|
@@ -45,13 +68,12 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
45
68
|
end
|
|
46
69
|
|
|
47
70
|
context 'when the projection does not include the renamed column' do
|
|
48
|
-
let(:
|
|
49
|
-
let(:projection) { operand.project([ :name, :age ]) }
|
|
71
|
+
let(:projection) { operand.project([ :name, :age ]) }
|
|
50
72
|
|
|
51
73
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
52
74
|
|
|
53
|
-
its(:to_s) { should eql('SELECT DISTINCT "name", "age" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users"')
|
|
54
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "name", "age" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users"') }
|
|
75
|
+
its(:to_s) { should eql('SELECT DISTINCT "name", "age" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users"') }
|
|
76
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "name", "age" FROM (SELECT "id" AS "user_id", "name", "age" FROM "users") AS "users")') }
|
|
55
77
|
end
|
|
56
78
|
end
|
|
57
79
|
|
|
@@ -60,8 +82,41 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
60
82
|
|
|
61
83
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
62
84
|
|
|
63
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users" WHERE "id" = 1')
|
|
64
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM "users" WHERE "id" = 1') }
|
|
85
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users" WHERE "id" = 1') }
|
|
86
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM "users" WHERE "id" = 1)') }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'when the operand is a summarization' do
|
|
90
|
+
context 'summarize per table dee' do
|
|
91
|
+
let(:summarize_per) { TABLE_DEE }
|
|
92
|
+
let(:operand) { base_relation.summarize(summarize_per) { |r| r.add(:count, r[:id].count) } }
|
|
93
|
+
let(:projection) { operand.project([ :count ]) }
|
|
94
|
+
|
|
95
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
96
|
+
|
|
97
|
+
its(:to_s) { should eql('SELECT DISTINCT "count" FROM (SELECT COUNT ("id") AS "count" FROM "users") AS "users"') }
|
|
98
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "count" FROM (SELECT COUNT ("id") AS "count" FROM "users") AS "users")') }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context 'summarize per table dum' do
|
|
102
|
+
let(:summarize_per) { TABLE_DUM }
|
|
103
|
+
let(:operand) { base_relation.summarize(summarize_per) { |r| r.add(:count, r[:id].count) } }
|
|
104
|
+
let(:projection) { operand.project([ :count ]) }
|
|
105
|
+
|
|
106
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
107
|
+
|
|
108
|
+
its(:to_s) { should eql('SELECT DISTINCT "count" FROM (SELECT COUNT ("id") AS "count" FROM "users" HAVING FALSE) AS "users"') }
|
|
109
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "count" FROM (SELECT COUNT ("id") AS "count" FROM "users" HAVING FALSE) AS "users")') }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context 'summarize by a subset of the operand header' do
|
|
113
|
+
let(:operand) { base_relation.summarize([ :id, :name ]) { |r| r.add(:count, r[:age].count) } }
|
|
114
|
+
|
|
115
|
+
it_should_behave_like 'a generated SQL SELECT query'
|
|
116
|
+
|
|
117
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT "id", "name", COUNT ("age") AS "count" FROM "users" GROUP BY "id", "name" HAVING COUNT (*) > 0) AS "users"') }
|
|
118
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT "id", "name", COUNT ("age") AS "count" FROM "users" GROUP BY "id", "name" HAVING COUNT (*) > 0) AS "users")') }
|
|
119
|
+
end
|
|
65
120
|
end
|
|
66
121
|
|
|
67
122
|
context 'when the operand is ordered' do
|
|
@@ -69,8 +124,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
69
124
|
|
|
70
125
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
71
126
|
|
|
72
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users"')
|
|
73
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users"') }
|
|
127
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users"') }
|
|
128
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users")') }
|
|
74
129
|
end
|
|
75
130
|
|
|
76
131
|
context 'when the operand is reversed' do
|
|
@@ -78,8 +133,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
78
133
|
|
|
79
134
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
80
135
|
|
|
81
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC) AS "users"')
|
|
82
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC) AS "users"') }
|
|
136
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC) AS "users"') }
|
|
137
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC) AS "users")') }
|
|
83
138
|
end
|
|
84
139
|
|
|
85
140
|
context 'when the operand is limited' do
|
|
@@ -87,8 +142,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
87
142
|
|
|
88
143
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
89
144
|
|
|
90
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users"')
|
|
91
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users"') }
|
|
145
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users"') }
|
|
146
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users")') }
|
|
92
147
|
end
|
|
93
148
|
|
|
94
149
|
context 'when the operand is an offset' do
|
|
@@ -96,8 +151,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
96
151
|
|
|
97
152
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
98
153
|
|
|
99
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users"')
|
|
100
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users"') }
|
|
154
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users"') }
|
|
155
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users")') }
|
|
101
156
|
end
|
|
102
157
|
|
|
103
158
|
context 'when the operand is a difference' do
|
|
@@ -105,8 +160,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
105
160
|
|
|
106
161
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
107
162
|
|
|
108
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
109
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
163
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") EXCEPT (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
164
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") EXCEPT (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
110
165
|
end
|
|
111
166
|
|
|
112
167
|
context 'when the operand is an intersection' do
|
|
@@ -114,8 +169,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
114
169
|
|
|
115
170
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
116
171
|
|
|
117
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
118
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
172
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") INTERSECT (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
173
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") INTERSECT (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
119
174
|
end
|
|
120
175
|
|
|
121
176
|
context 'when the operand is a union' do
|
|
@@ -123,8 +178,8 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
123
178
|
|
|
124
179
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
125
180
|
|
|
126
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
127
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT
|
|
181
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") UNION (SELECT "id", "name", "age" FROM "users")) AS "users"') }
|
|
182
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM ((SELECT "id", "name", "age" FROM "users") UNION (SELECT "id", "name", "age" FROM "users")) AS "users")') }
|
|
128
183
|
end
|
|
129
184
|
|
|
130
185
|
context 'when the operand is a join' do
|
|
@@ -132,7 +187,7 @@ describe SQL::Generator::Relation::Unary, '#visit_veritas_algebra_projection' do
|
|
|
132
187
|
|
|
133
188
|
it_should_behave_like 'a generated SQL SELECT query'
|
|
134
189
|
|
|
135
|
-
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users"')
|
|
136
|
-
its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users"') }
|
|
190
|
+
its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" AS "left" NATURAL JOIN "users" AS "right") AS "users"') }
|
|
191
|
+
its(:to_subquery) { should eql('(SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" AS "left" NATURAL JOIN "users" AS "right") AS "users")') }
|
|
137
192
|
end
|
|
138
193
|
end
|