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,160 @@
1
+ # encoding: utf-8
2
+
3
+ module Veritas
4
+ module SQL
5
+ module Generator
6
+
7
+ # Generates an SQL statement for a literal
8
+ module Literal
9
+
10
+ TRUE = 'TRUE'.freeze
11
+ FALSE = 'FALSE'.freeze
12
+ NULL = 'NULL'.freeze
13
+ QUOTE = "'".freeze
14
+ ESCAPED_QUOTE = "''".freeze
15
+ SEPARATOR = ', '.freeze
16
+ DATE_FORMAT = '%F'.freeze
17
+ DATETIME_FORMAT = "#{DATE_FORMAT}T%T.%N%Z".freeze
18
+ TIME_SCALE = 9
19
+
20
+ # Returns an unfrozen object
21
+ #
22
+ # Some objects, like Date, DateTime and Time memoize values
23
+ # when serialized to a String, so when they are frozen this will
24
+ # dup them and then return the unfrozen copy.
25
+ #
26
+ # @param [Object] object
27
+ #
28
+ # @return [Object]
29
+ # non-frozen object
30
+ #
31
+ # @api private
32
+ def self.dup_frozen(object)
33
+ object.frozen? ? object.dup : object
34
+ end
35
+
36
+ # Visit an Enumerable
37
+ #
38
+ # @param [Enumerable] enumerable
39
+ #
40
+ # @return [#to_s]
41
+ #
42
+ # @api private
43
+ def visit_enumerable(enumerable)
44
+ "(#{enumerable.map { |entry| dispatch entry }.join(SEPARATOR)})"
45
+ end
46
+
47
+ # Visit a String
48
+ #
49
+ # @note The string must be utf-8 encoded
50
+ #
51
+ # @param [String] string
52
+ #
53
+ # @return [#to_s]
54
+ #
55
+ # @api private
56
+ def visit_string(string)
57
+ "#{QUOTE}#{string.gsub(QUOTE, ESCAPED_QUOTE)}#{QUOTE}"
58
+ end
59
+
60
+ # Visit a Numeric
61
+ #
62
+ # @param [Numeric] numeric
63
+ #
64
+ # @return [#to_s]
65
+ #
66
+ # @api private
67
+ def visit_numeric(numeric)
68
+ numeric.to_s
69
+ end
70
+
71
+ # Visit a Class
72
+ #
73
+ # @param [Class] klass
74
+ #
75
+ # @return [#to_s]
76
+ #
77
+ # @api private
78
+ def visit_class(klass)
79
+ name = klass.name.to_s
80
+ name.empty? ? NULL : visit_string(name)
81
+ end
82
+
83
+ # Visit a Date and return in ISO 8601 date format
84
+ #
85
+ # @param [Date] date
86
+ #
87
+ # @return [#to_s]
88
+ #
89
+ # @todo use Date#iso8601 when added to 1.8.7 by backports
90
+ #
91
+ # @api private
92
+ def visit_date(date)
93
+ dispatch Literal.dup_frozen(date).strftime(DATE_FORMAT)
94
+ end
95
+
96
+ # Visit a DateTime and return in ISO 8601 date-time format
97
+ #
98
+ # Converts the DateTime to UTC format.
99
+ #
100
+ # @param [DateTime] date_time
101
+ #
102
+ # @return [#to_s]
103
+ #
104
+ # @todo use DateTime#iso8601(TIME_SCALE) when added to 1.8.7 by backports
105
+ #
106
+ # @api private
107
+ def visit_date_time(date_time)
108
+ dispatch date_time.new_offset.strftime(DATETIME_FORMAT)
109
+ end
110
+
111
+ # Visit a Time
112
+ #
113
+ # Converts the Time to UTC format.
114
+ #
115
+ # @param [Time] time
116
+ #
117
+ # @return [#to_s]
118
+ #
119
+ # @api private
120
+ def visit_time(time)
121
+ dispatch Literal.dup_frozen(time).utc.iso8601(TIME_SCALE)
122
+ end
123
+
124
+ # Visit a true value
125
+ #
126
+ # @param [true]
127
+ #
128
+ # @return [#to_s]
129
+ #
130
+ # @api private
131
+ def visit_true_class(_true)
132
+ TRUE
133
+ end
134
+
135
+ # Visit a false value
136
+ #
137
+ # @param [false]
138
+ #
139
+ # @return [#to_s]
140
+ #
141
+ # @api private
142
+ def visit_false_class(_false)
143
+ FALSE
144
+ end
145
+
146
+ # Visit a nil value
147
+ #
148
+ # @param [nil]
149
+ #
150
+ # @return [#to_s]
151
+ #
152
+ # @api private
153
+ def visit_nil_class(_nil)
154
+ NULL
155
+ end
156
+
157
+ end # module Literal
158
+ end # module Generator
159
+ end # module SQL
160
+ end # module Veritas
@@ -0,0 +1,349 @@
1
+ # encoding: utf-8
2
+
3
+ module Veritas
4
+ module SQL
5
+ module Generator
6
+
7
+ # Generates an SQL statement for a logic expression
8
+ module Logic
9
+ include Attribute, Literal
10
+
11
+ EQUAL_TO = ' = '.freeze
12
+ EQUAL_TO_NULL = ' IS '.freeze
13
+ NOT_EQUAL_TO = ' <> '.freeze
14
+ NOT_EQUAL_TO_NULL = ' IS NOT '.freeze
15
+ GREATER_THAN = ' > '.freeze
16
+ GREATER_THAN_OR_EQUAL_TO = ' >= '.freeze
17
+ LESS_THAN = ' < '.freeze
18
+ LESS_THAN_OR_EQUAL_TO = ' <= '.freeze
19
+ IN = ' IN '.freeze
20
+ NOT_IN = ' NOT IN '.freeze
21
+ BETWEEN = ' BETWEEN '.freeze
22
+ NOT_BETWEEN = ' NOT BETWEEN '.freeze
23
+ AND = ' AND '.freeze
24
+ OR = ' OR '.freeze
25
+ MATCH_ALL = '1 = 1'.freeze
26
+ MATCH_NONE = '1 = 0'.freeze
27
+ EMPTY_ARRAY = [].freeze
28
+
29
+ # Visit an Equality predicate
30
+ #
31
+ # @param [Logic::Predicate::Equality] equality
32
+ #
33
+ # @return [#to_s]
34
+ #
35
+ # @api private
36
+ def visit_veritas_logic_predicate_equality(equality)
37
+ binary_operation_sql(equality.right.nil? ? EQUAL_TO_NULL : EQUAL_TO, equality)
38
+ end
39
+
40
+ # Visit an Inequality predicate
41
+ #
42
+ # @param [Logic::Predicate::Inequality] inequality
43
+ #
44
+ # @return [#to_s]
45
+ #
46
+ # @api private
47
+ def visit_veritas_logic_predicate_inequality(inequality)
48
+ expressions = inequality_expressions(inequality)
49
+ expressions.one? ? expressions.first : "(#{expressions.join(OR)})"
50
+ end
51
+
52
+ # Visit an GreaterThan predicate
53
+ #
54
+ # @param [Logic::Predicate::GreaterThan] greater_than
55
+ #
56
+ # @return [#to_s]
57
+ #
58
+ # @api private
59
+ def visit_veritas_logic_predicate_greater_than(greater_than)
60
+ binary_operation_sql(GREATER_THAN, greater_than)
61
+ end
62
+
63
+ # Visit an GreaterThanOrEqualTo predicate
64
+ #
65
+ # @param [Logic::Predicate::GreaterThanOrEqualTo] greater_than_or_equal_to
66
+ #
67
+ # @return [#to_s]
68
+ #
69
+ # @api private
70
+ def visit_veritas_logic_predicate_greater_than_or_equal_to(greater_than_or_equal_to)
71
+ binary_operation_sql(GREATER_THAN_OR_EQUAL_TO, greater_than_or_equal_to)
72
+ end
73
+
74
+ # Visit an LessThan predicate
75
+ #
76
+ # @param [Logic::Predicate::LessThan] less_than
77
+ #
78
+ # @return [#to_s]
79
+ #
80
+ # @api private
81
+ def visit_veritas_logic_predicate_less_than(less_than)
82
+ binary_operation_sql(LESS_THAN, less_than)
83
+ end
84
+
85
+ # Visit an LessThanOrEqualTo predicate
86
+ #
87
+ # @param [Logic::Predicate::LessThanOrEqualTo] less_than_or_equal_to
88
+ #
89
+ # @return [#to_s]
90
+ #
91
+ # @api private
92
+ def visit_veritas_logic_predicate_less_than_or_equal_to(less_than_or_equal_to)
93
+ binary_operation_sql(LESS_THAN_OR_EQUAL_TO, less_than_or_equal_to)
94
+ end
95
+
96
+ # Visit an Inclusion predicate
97
+ #
98
+ # @param [Logic::Predicate::Inclusion] inclusion
99
+ #
100
+ # @return [#to_s]
101
+ #
102
+ # @api private
103
+ def visit_veritas_logic_predicate_inclusion(inclusion)
104
+ case inclusion.right
105
+ when Range then range_inclusion_sql(inclusion)
106
+ when EMPTY_ARRAY then MATCH_NONE
107
+ else
108
+ binary_operation_sql(IN, inclusion)
109
+ end
110
+ end
111
+
112
+ # Visit an Exclusion predicate
113
+ #
114
+ # @param [Logic::Predicate::Exclusion] exclusion
115
+ #
116
+ # @return [#to_s]
117
+ #
118
+ # @api private
119
+ def visit_veritas_logic_predicate_exclusion(exclusion)
120
+ case exclusion.right
121
+ when Range then range_exclusion_sql(exclusion)
122
+ when EMPTY_ARRAY then MATCH_ALL
123
+ else
124
+ binary_operation_sql(NOT_IN, exclusion)
125
+ end
126
+ end
127
+
128
+ # Visit an Conjunction connective
129
+ #
130
+ # @param [Logic::Connective::Conjunction] conjunction
131
+ #
132
+ # @return [#to_s]
133
+ #
134
+ # @api private
135
+ def visit_veritas_logic_connective_conjunction(conjunction)
136
+ binary_connective_sql(AND, conjunction)
137
+ end
138
+
139
+ # Visit an Disjunction connective
140
+ #
141
+ # @param [Logic::Connective::Disjunction] disjunction
142
+ #
143
+ # @return [#to_s]
144
+ #
145
+ # @api private
146
+ def visit_veritas_logic_connective_disjunction(disjunction)
147
+ binary_connective_sql(OR, disjunction)
148
+ end
149
+
150
+ # Visit an Negation connective
151
+ #
152
+ # @param [Logic::Connective::Negation] negation
153
+ #
154
+ # @return [#to_s]
155
+ #
156
+ # @api private
157
+ def visit_veritas_logic_connective_negation(negation)
158
+ "NOT #{dispatch negation.operand}"
159
+ end
160
+
161
+ # Visit a Tautology
162
+ #
163
+ # @param [Logic::Proposition::Tautology] _tautology
164
+ #
165
+ # @return [#to_s]
166
+ #
167
+ # @api private
168
+ def visit_veritas_logic_proposition_tautology(_tautology)
169
+ MATCH_ALL
170
+ end
171
+
172
+ # Visit a Contradiction
173
+ #
174
+ # @param [Logic::Proposition::Contradiction] _contradiction
175
+ #
176
+ # @return [#to_s]
177
+ #
178
+ # @api private
179
+ def visit_veritas_logic_proposition_contradiction(_contradiction)
180
+ MATCH_NONE
181
+ end
182
+
183
+ private
184
+
185
+ # Return the SQL for an Inclusion using a Range
186
+ #
187
+ # @param [Logic::Predicate::Inclusion] predicate
188
+ #
189
+ # @return [#to_s]
190
+ #
191
+ # @api private
192
+ def range_inclusion_sql(inclusion)
193
+ if inclusion.right.exclude_end?
194
+ exclusive_range_inclusion_sql(inclusion)
195
+ else
196
+ inclusive_range_sql(BETWEEN, inclusion)
197
+ end
198
+ end
199
+
200
+ # Return the SQL for an Exclusion using a Range
201
+ #
202
+ # @param [Logic::Predicate::Exclusion] exclusion
203
+ #
204
+ # @return [#to_s]
205
+ #
206
+ # @api private
207
+ def range_exclusion_sql(exclusion)
208
+ if exclusion.right.exclude_end?
209
+ exclusive_range_exclusion_sql(exclusion)
210
+ else
211
+ inclusive_range_sql(NOT_BETWEEN, exclusion)
212
+ end
213
+ end
214
+
215
+ # Return the SQL for an Inclusion using an exclusive Range
216
+ #
217
+ # @param [Logic::Predicate::Inclusion] inclusion
218
+ #
219
+ # @return [#to_s]
220
+ #
221
+ # @api private
222
+ def exclusive_range_inclusion_sql(inclusion)
223
+ left = new_from_enumerable_predicate(Veritas::Logic::Predicate::GreaterThanOrEqualTo, inclusion, :first)
224
+ right = new_from_enumerable_predicate(Veritas::Logic::Predicate::LessThan, inclusion, :last)
225
+ dispatch left.and(right)
226
+ end
227
+
228
+ # Return the SQL for an Exclusion using an exclusive Range
229
+ #
230
+ # @param [Logic::Predicate::Exclusion] exclusion
231
+ #
232
+ # @return [#to_s]
233
+ #
234
+ # @api private
235
+ def exclusive_range_exclusion_sql(exclusion)
236
+ left = new_from_enumerable_predicate(Veritas::Logic::Predicate::LessThan, exclusion, :first)
237
+ right = new_from_enumerable_predicate(Veritas::Logic::Predicate::GreaterThanOrEqualTo, exclusion, :last)
238
+ dispatch left.or(right)
239
+ end
240
+
241
+ # Instantiate a new Predicate object from an Enumerable Predicate
242
+ #
243
+ # @param [Class<Logic::Predicate>] klass
244
+ # the type of predicate to create
245
+ # @param [Logic::Predicate::Enumerable] predicate
246
+ # the enumerable predicate
247
+ # @param [Symbol] method
248
+ # the method to call on the right operand of the predicate
249
+ # @return [Logic::Predicate]
250
+ #
251
+ # @api private
252
+ def new_from_enumerable_predicate(klass, predicate, method)
253
+ klass.new(predicate.left, predicate.right.send(method))
254
+ end
255
+
256
+ # Return the expressions for an inequality
257
+ #
258
+ # @param [Logic::Predicate::Inequality] inequality
259
+ #
260
+ # @return [Array<#to_s>]
261
+ #
262
+ # @api private
263
+ def inequality_expressions(inequality)
264
+ expressions = [
265
+ inequality_sql(inequality),
266
+ optional_is_null_sql(inequality.left),
267
+ optional_is_null_sql(inequality.right),
268
+ ]
269
+ expressions.compact!
270
+ expressions
271
+ end
272
+
273
+ # Return the SQL for an inequality predicate
274
+ #
275
+ # @param [Logic::Predicate::Inequality] inequality
276
+ #
277
+ # @return [#to_s]
278
+ #
279
+ # @api private
280
+ def inequality_sql(inequality)
281
+ binary_operation_sql(inequality.right.nil? ? NOT_EQUAL_TO_NULL : NOT_EQUAL_TO, inequality)
282
+ end
283
+
284
+ # Return the SQL for a Binary Connective
285
+ #
286
+ # @param [#to_s] operator
287
+ #
288
+ # @param [Logic::Connective::Binary] binary_connective
289
+ #
290
+ # @return [#to_s]
291
+ #
292
+ # @api private
293
+ def binary_connective_sql(operator, binary_connective)
294
+ "(#{binary_operation_sql(operator, binary_connective)})"
295
+ end
296
+
297
+ # Return the SQL for a predicate
298
+ #
299
+ # @param [#to_s] operator
300
+ #
301
+ # @param [Logic::Predicate] predicate
302
+ #
303
+ # @return [#to_s]
304
+ #
305
+ # @api private
306
+ def binary_operation_sql(operator, predicate)
307
+ "#{dispatch(predicate.left)}#{operator}#{dispatch(predicate.right)}"
308
+ end
309
+
310
+ # Return the SQL for an operation using an inclusive Range
311
+ #
312
+ # @param [#to_s] operator
313
+ #
314
+ # @param [Logic::Predicate::Enumerable] predicate
315
+ #
316
+ # @return [#to_s]
317
+ #
318
+ # @api private
319
+ def inclusive_range_sql(operator, predicate)
320
+ right = predicate.right
321
+ "#{dispatch(predicate.left)}#{operator}#{dispatch(right.first)}#{AND}#{dispatch(right.last)}"
322
+ end
323
+
324
+ # Return SQL for an Equality with a nil value for optional attributes
325
+ #
326
+ # @param [Attribute] attribute
327
+ #
328
+ # @return [#to_sql, nil]
329
+ #
330
+ # @api private
331
+ def optional_is_null_sql(attribute)
332
+ dispatch(attribute.eq(nil)) if optional?(attribute)
333
+ end
334
+
335
+ # Test if the object is not required
336
+ #
337
+ # @param [Object] operand
338
+ #
339
+ # @return [Boolean]
340
+ #
341
+ # @api private
342
+ def optional?(operand)
343
+ operand.respond_to?(:required?) && !operand.required?
344
+ end
345
+
346
+ end # module Logic
347
+ end # module Generator
348
+ end # module SQL
349
+ end # module Veritas