veritas-sql-generator 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. data/Gemfile +33 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +27 -0
  4. data/Rakefile +25 -0
  5. data/TODO +17 -0
  6. data/config/flay.yml +3 -0
  7. data/config/flog.yml +2 -0
  8. data/config/roodi.yml +16 -0
  9. data/config/site.reek +124 -0
  10. data/config/yardstick.yml +2 -0
  11. data/lib/veritas-sql-generator.rb +3 -0
  12. data/lib/veritas/base_relation.rb +36 -0
  13. data/lib/veritas/sql/generator.rb +35 -0
  14. data/lib/veritas/sql/generator/attribute.rb +25 -0
  15. data/lib/veritas/sql/generator/direction.rb +36 -0
  16. data/lib/veritas/sql/generator/identifier.rb +27 -0
  17. data/lib/veritas/sql/generator/literal.rb +160 -0
  18. data/lib/veritas/sql/generator/logic.rb +349 -0
  19. data/lib/veritas/sql/generator/relation.rb +111 -0
  20. data/lib/veritas/sql/generator/relation/base.rb +14 -0
  21. data/lib/veritas/sql/generator/relation/binary.rb +184 -0
  22. data/lib/veritas/sql/generator/relation/set.rb +99 -0
  23. data/lib/veritas/sql/generator/relation/unary.rb +326 -0
  24. data/lib/veritas/sql/generator/version.rb +9 -0
  25. data/lib/veritas/sql/generator/visitor.rb +121 -0
  26. data/spec/rcov.opts +6 -0
  27. data/spec/shared/command_method_behavior.rb +7 -0
  28. data/spec/shared/generated_sql_behavior.rb +15 -0
  29. data/spec/shared/idempotent_method_behavior.rb +7 -0
  30. data/spec/spec.opts +3 -0
  31. data/spec/spec_helper.rb +15 -0
  32. data/spec/unit/veritas/base_relation/name_spec.rb +45 -0
  33. data/spec/unit/veritas/sql/generator/attribute/visit_veritas_attribute_spec.rb +15 -0
  34. data/spec/unit/veritas/sql/generator/direction/visit_veritas_relation_operation_order_ascending_spec.rb +15 -0
  35. data/spec/unit/veritas/sql/generator/direction/visit_veritas_relation_operation_order_descending_spec.rb +15 -0
  36. data/spec/unit/veritas/sql/generator/identifier/visit_identifier_spec.rb +26 -0
  37. data/spec/unit/veritas/sql/generator/literal/class_methods/dup_frozen_spec.rb +23 -0
  38. data/spec/unit/veritas/sql/generator/literal/visit_class_spec.rb +31 -0
  39. data/spec/unit/veritas/sql/generator/literal/visit_date_spec.rb +15 -0
  40. data/spec/unit/veritas/sql/generator/literal/visit_date_time_spec.rb +61 -0
  41. data/spec/unit/veritas/sql/generator/literal/visit_enumerable_spec.rb +15 -0
  42. data/spec/unit/veritas/sql/generator/literal/visit_false_class_spec.rb +14 -0
  43. data/spec/unit/veritas/sql/generator/literal/visit_nil_class_spec.rb +14 -0
  44. data/spec/unit/veritas/sql/generator/literal/visit_numeric_spec.rb +34 -0
  45. data/spec/unit/veritas/sql/generator/literal/visit_string_spec.rb +26 -0
  46. data/spec/unit/veritas/sql/generator/literal/visit_time_spec.rb +97 -0
  47. data/spec/unit/veritas/sql/generator/literal/visit_true_class_spec.rb +14 -0
  48. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_conjunction_spec.rb +16 -0
  49. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_disjunction_spec.rb +16 -0
  50. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_negation_spec.rb +16 -0
  51. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_equality_spec.rb +27 -0
  52. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_exclusion_spec.rb +43 -0
  53. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_greater_than_or_equal_to_spec.rb +15 -0
  54. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_greater_than_spec.rb +15 -0
  55. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_inclusion_spec.rb +43 -0
  56. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_inequality_spec.rb +55 -0
  57. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_less_than_or_equal_to_spec.rb +15 -0
  58. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_less_than_spec.rb +15 -0
  59. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_contradiction_spec.rb +15 -0
  60. data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_tautology_spec.rb +15 -0
  61. data/spec/unit/veritas/sql/generator/relation/binary/base/to_subquery_spec.rb +35 -0
  62. data/spec/unit/veritas/sql/generator/relation/binary/base/visit_veritas_base_relation_spec.rb +22 -0
  63. data/spec/unit/veritas/sql/generator/relation/binary/class_methods/subquery_spec.rb +42 -0
  64. data/spec/unit/veritas/sql/generator/relation/binary/to_s_spec.rb +35 -0
  65. data/spec/unit/veritas/sql/generator/relation/binary/to_subquery_spec.rb +35 -0
  66. data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_join_spec.rb +138 -0
  67. data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_product_spec.rb +139 -0
  68. data/spec/unit/veritas/sql/generator/relation/class_methods/subquery_spec.rb +33 -0
  69. data/spec/unit/veritas/sql/generator/relation/class_methods/visit_spec.rb +61 -0
  70. data/spec/unit/veritas/sql/generator/relation/name_spec.rb +30 -0
  71. data/spec/unit/veritas/sql/generator/relation/set/to_s_spec.rb +55 -0
  72. data/spec/unit/veritas/sql/generator/relation/set/to_subquery_spec.rb +55 -0
  73. data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_difference_spec.rb +138 -0
  74. data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_intersection_spec.rb +138 -0
  75. data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_union_spec.rb +138 -0
  76. data/spec/unit/veritas/sql/generator/relation/to_sql_spec.rb +52 -0
  77. data/spec/unit/veritas/sql/generator/relation/unary/to_s_spec.rb +55 -0
  78. data/spec/unit/veritas/sql/generator/relation/unary/to_subquery_spec.rb +75 -0
  79. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_projection_spec.rb +138 -0
  80. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_rename_spec.rb +136 -0
  81. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_restriction_spec.rb +157 -0
  82. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_base_relation_spec.rb +21 -0
  83. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_limit_spec.rb +125 -0
  84. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_offset_spec.rb +125 -0
  85. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_order_spec.rb +136 -0
  86. data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_reverse_spec.rb +125 -0
  87. data/spec/unit/veritas/sql/generator/relation/visit_spec.rb +54 -0
  88. data/spec/unit/veritas/sql/generator/relation/visited_spec.rb +35 -0
  89. data/spec/unit/veritas/sql/generator/visitor/class_methods/handler_for_spec.rb +71 -0
  90. data/spec/unit/veritas/sql/generator/visitor/visit_spec.rb +12 -0
  91. data/spec/unit/veritas/sql/generator/visitor/visited_spec.rb +11 -0
  92. data/tasks/quality/ci.rake +2 -0
  93. data/tasks/quality/flay.rake +41 -0
  94. data/tasks/quality/flog.rake +45 -0
  95. data/tasks/quality/heckle.rake +203 -0
  96. data/tasks/quality/metric_fu.rake +26 -0
  97. data/tasks/quality/reek.rake +9 -0
  98. data/tasks/quality/roodi.rake +15 -0
  99. data/tasks/quality/yardstick.rake +23 -0
  100. data/tasks/spec.rake +38 -0
  101. data/tasks/yard.rake +9 -0
  102. data/veritas-sql-generator.gemspec +222 -0
  103. metadata +285 -0
@@ -0,0 +1,136 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Relation::Unary, '#visit_veritas_relation_operation_order' do
6
+ subject { object.visit_veritas_relation_operation_order(order) }
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) { BaseRelation.new(relation_name, header, body) }
15
+ let(:order) { operand.order }
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" FROM "users" ORDER BY "id", "name", "age"') }
24
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age"') }
25
+ end
26
+
27
+ context 'when the operand is a projection' do
28
+ context 'when the projection contains the base_relation' do
29
+ let(:operand) { base_relation.project([ :id, :name ]) }
30
+
31
+ it_should_behave_like 'a generated SQL SELECT query'
32
+
33
+ its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users" ORDER BY "id", "name"') }
34
+ its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM "users" ORDER BY "id", "name"') }
35
+ end
36
+
37
+ context 'when the projection contains an order' do
38
+ let(:operand) { base_relation.order.project([ :id, :name ]) }
39
+
40
+ it_should_behave_like 'a generated SQL SELECT query'
41
+
42
+ its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users" ORDER BY "id", "name"') }
43
+ its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age") AS "users" ORDER BY "id", "name"') }
44
+ end
45
+ end
46
+
47
+ context 'when the operand is a rename' do
48
+ let(:operand) { base_relation.rename(:id => :user_id) }
49
+
50
+ it_should_behave_like 'a generated SQL SELECT query'
51
+
52
+ its(:to_s) { should eql('SELECT "id" AS "user_id", "name", "age" FROM "users" ORDER BY "user_id", "name", "age"') }
53
+ its(:to_subquery) { should eql('SELECT "id" AS "user_id", "name", "age" FROM "users" ORDER BY "user_id", "name", "age"') }
54
+ end
55
+
56
+ context 'when the operand is a restriction' do
57
+ let(:operand) { base_relation.restrict { |r| r[:id].eq(1) } }
58
+
59
+ it_should_behave_like 'a generated SQL SELECT query'
60
+
61
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" WHERE "id" = 1 ORDER BY "id", "name", "age"') }
62
+ its(:to_subquery) { should eql('SELECT * FROM "users" WHERE "id" = 1 ORDER BY "id", "name", "age"') }
63
+ end
64
+
65
+ context 'when the operand is ordered' do
66
+ let(:operand) { base_relation.order }
67
+
68
+ it_should_behave_like 'a generated SQL SELECT query'
69
+
70
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" ORDER BY "id", "name", "age"') }
71
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age"') }
72
+ end
73
+
74
+ context 'when the operand is reversed' do
75
+ let(:operand) { base_relation.order.reverse }
76
+
77
+ it_should_behave_like 'a generated SQL SELECT query'
78
+
79
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" ORDER BY "id", "name", "age"') }
80
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age"') }
81
+ end
82
+
83
+ context 'when the operand is limited' do
84
+ let(:operand) { base_relation.order([ id.desc, name.desc, age.desc ]).take(1) }
85
+
86
+ it_should_behave_like 'a generated SQL SELECT query'
87
+
88
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC LIMIT 1) AS "users" ORDER BY "id", "name", "age"') }
89
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC LIMIT 1) AS "users" ORDER BY "id", "name", "age"') }
90
+ end
91
+
92
+ context 'when the operand is an offset' do
93
+ let(:operand) { base_relation.order([ id.desc, name.desc, age.desc ]).drop(1) }
94
+
95
+ it_should_behave_like 'a generated SQL SELECT query'
96
+
97
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC OFFSET 1) AS "users" ORDER BY "id", "name", "age"') }
98
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC OFFSET 1) AS "users" ORDER BY "id", "name", "age"') }
99
+ end
100
+
101
+ context 'when the operand is a difference' do
102
+ let(:operand) { base_relation.difference(base_relation) }
103
+
104
+ it_should_behave_like 'a generated SQL SELECT query'
105
+
106
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") EXCEPT (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
107
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") EXCEPT (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
108
+ end
109
+
110
+ context 'when the operand is an intersection' do
111
+ let(:operand) { base_relation.intersect(base_relation) }
112
+
113
+ it_should_behave_like 'a generated SQL SELECT query'
114
+
115
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") INTERSECT (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
116
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") INTERSECT (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
117
+ end
118
+
119
+ context 'when the operand is a union' do
120
+ let(:operand) { base_relation.union(base_relation) }
121
+
122
+ it_should_behave_like 'a generated SQL SELECT query'
123
+
124
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") UNION (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
125
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") UNION (SELECT * FROM "users")) AS "users" ORDER BY "id", "name", "age"') }
126
+ end
127
+
128
+ context 'when the operand is a join' do
129
+ let(:operand) { base_relation.join(base_relation) }
130
+
131
+ it_should_behave_like 'a generated SQL SELECT query'
132
+
133
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users" ORDER BY "id", "name", "age"') }
134
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users" ORDER BY "id", "name", "age"') }
135
+ end
136
+ end
@@ -0,0 +1,125 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Relation::Unary, '#visit_veritas_relation_operation_reverse' do
6
+ subject { object.visit_veritas_relation_operation_reverse(order) }
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) { BaseRelation.new(relation_name, header, body) }
15
+ let(:order) { operand.reverse }
16
+ let(:object) { described_class.new }
17
+
18
+ context 'when the operand is a base relation' do
19
+ let(:operand) { base_relation.order }
20
+
21
+ it_should_behave_like 'a generated SQL SELECT query'
22
+
23
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
24
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
25
+ end
26
+
27
+ context 'when the operand is a projection' do
28
+ let(:operand) { base_relation.project([ :id, :name ]).order }
29
+
30
+ it_should_behave_like 'a generated SQL SELECT query'
31
+
32
+ its(:to_s) { should eql('SELECT DISTINCT "id", "name" FROM "users" ORDER BY "id" DESC, "name" DESC') }
33
+ its(:to_subquery) { should eql('SELECT DISTINCT "id", "name" FROM "users" ORDER BY "id" DESC, "name" DESC') }
34
+ end
35
+
36
+ context 'when the operand is a rename' do
37
+ let(:operand) { base_relation.order.rename(:id => :user_id) }
38
+
39
+ it_should_behave_like 'a generated SQL SELECT query'
40
+
41
+ its(:to_s) { should eql('SELECT "id" AS "user_id", "name", "age" FROM "users" ORDER BY "user_id" DESC, "name" DESC, "age" DESC') }
42
+ its(:to_subquery) { should eql('SELECT "id" AS "user_id", "name", "age" FROM "users" ORDER BY "user_id" DESC, "name" DESC, "age" DESC') }
43
+ end
44
+
45
+ context 'when the operand is a restriction' do
46
+ let(:operand) { base_relation.order.restrict { |r| r[:id].eq(1) } }
47
+
48
+ it_should_behave_like 'a generated SQL SELECT query'
49
+
50
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" WHERE "id" = 1 ORDER BY "id" DESC, "name" DESC, "age" DESC') }
51
+ its(:to_subquery) { should eql('SELECT * FROM "users" WHERE "id" = 1 ORDER BY "id" DESC, "name" DESC, "age" DESC') }
52
+ end
53
+
54
+ context 'when the operand is ordered' do
55
+ let(:operand) { base_relation.order }
56
+
57
+ it_should_behave_like 'a generated SQL SELECT query'
58
+
59
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
60
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
61
+ end
62
+
63
+ context 'when the operand is reversed' do
64
+ let(:operand) { base_relation.order.reverse }
65
+
66
+ it_should_behave_like 'a generated SQL SELECT query'
67
+
68
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM "users" ORDER BY "id", "name", "age"') }
69
+ its(:to_subquery) { should eql('SELECT * FROM "users" ORDER BY "id", "name", "age"') }
70
+ end
71
+
72
+ context 'when the operand is limited' do
73
+ let(:operand) { base_relation.order.take(1) }
74
+
75
+ it_should_behave_like 'a generated SQL SELECT query'
76
+
77
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
78
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" LIMIT 1) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
79
+ end
80
+
81
+ context 'when the operand is an offset' do
82
+ let(:operand) { base_relation.order.drop(1) }
83
+
84
+ it_should_behave_like 'a generated SQL SELECT query'
85
+
86
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
87
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" ORDER BY "id", "name", "age" OFFSET 1) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
88
+ end
89
+
90
+ context 'when the operand is a difference' do
91
+ let(:operand) { base_relation.difference(base_relation).order }
92
+
93
+ it_should_behave_like 'a generated SQL SELECT query'
94
+
95
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") EXCEPT (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
96
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") EXCEPT (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
97
+ end
98
+
99
+ context 'when the operand is an intersection' do
100
+ let(:operand) { base_relation.intersect(base_relation).order }
101
+
102
+ it_should_behave_like 'a generated SQL SELECT query'
103
+
104
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") INTERSECT (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
105
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") INTERSECT (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
106
+ end
107
+
108
+ context 'when the operand is a union' do
109
+ let(:operand) { base_relation.union(base_relation).order }
110
+
111
+ it_should_behave_like 'a generated SQL SELECT query'
112
+
113
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM ((SELECT * FROM "users") UNION (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
114
+ its(:to_subquery) { should eql('SELECT * FROM ((SELECT * FROM "users") UNION (SELECT * FROM "users")) AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
115
+ end
116
+
117
+ context 'when the operand is a join' do
118
+ let(:operand) { base_relation.join(base_relation).order }
119
+
120
+ it_should_behave_like 'a generated SQL SELECT query'
121
+
122
+ its(:to_s) { should eql('SELECT "id", "name", "age" FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
123
+ its(:to_subquery) { should eql('SELECT * FROM (SELECT * FROM "users" NATURAL JOIN "users") AS "users" ORDER BY "id" DESC, "name" DESC, "age" DESC') }
124
+ end
125
+ end
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Relation, '#visit' do
6
+ subject { object.visit(visitable) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Relation) }
9
+ let(:object) { described_class.new }
10
+
11
+ context 'with a handled object' do
12
+ let(:visitable) { mock('Visitable') }
13
+
14
+ before do
15
+ described_class.class_eval do
16
+ def visit_spec_mocks_mock(mock)
17
+ mock
18
+ end
19
+ end
20
+ end
21
+
22
+ it_should_behave_like 'a command method'
23
+
24
+ specify { expect { subject }.to change(object, :frozen?).from(false).to(true) }
25
+ end
26
+
27
+ context 'with a handled object more than once' do
28
+ let(:visitable) { mock('Visitable') }
29
+
30
+ before do
31
+ described_class.class_eval do
32
+ def visit_spec_mocks_mock(mock)
33
+ mock
34
+ end
35
+ end
36
+ end
37
+
38
+ before do
39
+ object.visit(visitable)
40
+ end
41
+
42
+ if RUBY_VERSION >= '1.9'
43
+ specify { expect { subject }.to raise_error(RuntimeError) }
44
+ else
45
+ specify { expect { subject }.to raise_error(TypeError) }
46
+ end
47
+ end
48
+
49
+ context 'with an unhandled object' do
50
+ let(:visitable) { mock('Not Handled') }
51
+
52
+ specify { expect { subject }.to raise_error(SQL::Generator::Visitor::UnknownObject, "No handler for #{visitable.class} in #{object.class}") }
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Relation, '#visited?' do
6
+ subject { object.visited? }
7
+
8
+ let(:id) { Attribute::Integer.new(:id) }
9
+ let(:name) { Attribute::String.new(:name) }
10
+ let(:age) { Attribute::Integer.new(:age, :required => false) }
11
+ let(:header) { [ id, name, age ] }
12
+ let(:body) { [ [ 1, 'Dan Kubb', 35 ] ].each }
13
+ let(:base_relation) { BaseRelation.new('users', header, body) }
14
+ let(:object) { described_class.new }
15
+
16
+ context 'when name is nil' do
17
+ it_should_behave_like 'an idempotent method'
18
+
19
+ it { should be(false) }
20
+ end
21
+
22
+ context 'when name is set' do
23
+ let(:name) { 'test' }
24
+
25
+ before do
26
+ # subclasses set @name, but nothing in this class
27
+ # does does so simulate it being set
28
+ object.instance_variable_set(:@name, name)
29
+ end
30
+
31
+ it_should_behave_like 'an idempotent method'
32
+
33
+ it { should be(true) }
34
+ end
35
+ end
@@ -0,0 +1,71 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Visitor, '.handler_for' do
6
+ subject { object.handler_for(visitable_class) }
7
+
8
+ let(:object) { Class.new(SQL::Generator::Visitor) }
9
+
10
+ before :all do
11
+ module ::MySpec
12
+ class Visitable; end
13
+ end
14
+ end
15
+
16
+ after :all do
17
+ MySpec.class_eval { remove_const(:Visitable) }
18
+ Object.class_eval { remove_const(:MySpec) }
19
+ end
20
+
21
+ context 'with an object handled by a public method' do
22
+ let(:visitable_class) { MySpec::Visitable }
23
+
24
+ before do
25
+ object.class_eval do
26
+ remove_instance_variable(:@handlers) if instance_variable_defined?(:@handlers)
27
+ define_method(:visit_my_spec_visitable) {}
28
+ end
29
+ end
30
+
31
+ after do
32
+ object.class_eval do
33
+ remove_instance_variable(:@handlers)
34
+ remove_method(:visit_my_spec_visitable)
35
+ end
36
+ end
37
+
38
+ it_should_behave_like 'an idempotent method'
39
+
40
+ it { should == :visit_my_spec_visitable }
41
+ end
42
+
43
+ context 'with an object handled by a private method' do
44
+ let(:visitable_class) { MySpec::Visitable }
45
+
46
+ before do
47
+ object.class_eval do
48
+ remove_instance_variable(:@handlers) if instance_variable_defined?(:@handlers)
49
+ define_method(:visit_my_spec_visitable) {}
50
+ private :visit_my_spec_visitable
51
+ end
52
+ end
53
+
54
+ after do
55
+ object.class_eval do
56
+ remove_instance_variable(:@handlers)
57
+ remove_method(:visit_my_spec_visitable)
58
+ end
59
+ end
60
+
61
+ it_should_behave_like 'an idempotent method'
62
+
63
+ it { should == :visit_my_spec_visitable }
64
+ end
65
+
66
+ context 'with an unhandled object' do
67
+ let(:visitable_class) { Class.new }
68
+
69
+ specify { expect { subject }.to raise_error(object::UnknownObject, "No handler for #{visitable_class} in #{object}") }
70
+ end
71
+ end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Visitor, '#visit' do
6
+ subject { object.visit(visitable) }
7
+
8
+ let(:visitable) { mock('handled object') }
9
+ let(:object) { described_class.new }
10
+
11
+ specify { expect { subject }.to raise_error(NotImplementedError, "#{described_class}#visit must be implemented") }
12
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Visitor, '#visited?' do
6
+ subject { object.visited? }
7
+
8
+ let(:object) { described_class.new }
9
+
10
+ specify { expect { subject }.to raise_error(NotImplementedError, "#{described_class}#visited? must be implemented") }
11
+ end