axiom-sql-generator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +37 -0
  4. data/.rspec +4 -0
  5. data/.rvmrc +1 -0
  6. data/.travis.yml +35 -0
  7. data/CONTRIBUTING.md +11 -0
  8. data/Gemfile +8 -0
  9. data/Gemfile.devtools +57 -0
  10. data/Guardfile +23 -0
  11. data/LICENSE +20 -0
  12. data/README.md +70 -0
  13. data/Rakefile +5 -0
  14. data/TODO +34 -0
  15. data/axiom-sql-generator.gemspec +25 -0
  16. data/config/flay.yml +3 -0
  17. data/config/flog.yml +2 -0
  18. data/config/mutant.yml +3 -0
  19. data/config/reek.yml +165 -0
  20. data/config/yardstick.yml +2 -0
  21. data/lib/axiom-sql-generator.rb +3 -0
  22. data/lib/axiom/sql/generator.rb +61 -0
  23. data/lib/axiom/sql/generator/attribute.rb +25 -0
  24. data/lib/axiom/sql/generator/core_ext/date.rb +20 -0
  25. data/lib/axiom/sql/generator/core_ext/date_time.rb +46 -0
  26. data/lib/axiom/sql/generator/direction.rb +38 -0
  27. data/lib/axiom/sql/generator/function.rb +55 -0
  28. data/lib/axiom/sql/generator/function/aggregate.rb +134 -0
  29. data/lib/axiom/sql/generator/function/connective.rb +53 -0
  30. data/lib/axiom/sql/generator/function/numeric.rb +135 -0
  31. data/lib/axiom/sql/generator/function/predicate.rb +266 -0
  32. data/lib/axiom/sql/generator/function/proposition.rb +38 -0
  33. data/lib/axiom/sql/generator/function/string.rb +29 -0
  34. data/lib/axiom/sql/generator/identifier.rb +28 -0
  35. data/lib/axiom/sql/generator/literal.rb +157 -0
  36. data/lib/axiom/sql/generator/relation.rb +240 -0
  37. data/lib/axiom/sql/generator/relation/base.rb +14 -0
  38. data/lib/axiom/sql/generator/relation/binary.rb +136 -0
  39. data/lib/axiom/sql/generator/relation/insertion.rb +62 -0
  40. data/lib/axiom/sql/generator/relation/materialized.rb +60 -0
  41. data/lib/axiom/sql/generator/relation/set.rb +107 -0
  42. data/lib/axiom/sql/generator/relation/unary.rb +379 -0
  43. data/lib/axiom/sql/generator/version.rb +12 -0
  44. data/lib/axiom/sql/generator/visitor.rb +121 -0
  45. data/spec/rcov.opts +7 -0
  46. data/spec/shared/generated_sql_behavior.rb +15 -0
  47. data/spec/spec_helper.rb +33 -0
  48. data/spec/support/config_alias.rb +3 -0
  49. data/spec/unit/axiom/sql/generator/attribute/visit_axiom_attribute_spec.rb +15 -0
  50. data/spec/unit/axiom/sql/generator/class_methods/parenthesize_spec.rb +18 -0
  51. data/spec/unit/axiom/sql/generator/direction/visit_axiom_relation_operation_order_ascending_spec.rb +15 -0
  52. data/spec/unit/axiom/sql/generator/direction/visit_axiom_relation_operation_order_descending_spec.rb +15 -0
  53. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_count_spec.rb +16 -0
  54. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_maximum_spec.rb +16 -0
  55. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_mean_spec.rb +16 -0
  56. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_minimum_spec.rb +16 -0
  57. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_standard_deviation_spec.rb +16 -0
  58. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_sum_spec.rb +16 -0
  59. data/spec/unit/axiom/sql/generator/function/aggregate/visit_axiom_aggregate_variance_spec.rb +16 -0
  60. data/spec/unit/axiom/sql/generator/function/connective/visit_axiom_function_connective_conjunction_spec.rb +20 -0
  61. data/spec/unit/axiom/sql/generator/function/connective/visit_axiom_function_connective_disjunction_spec.rb +20 -0
  62. data/spec/unit/axiom/sql/generator/function/connective/visit_axiom_function_connective_negation_spec.rb +20 -0
  63. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_absolute_spec.rb +15 -0
  64. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_addition_spec.rb +15 -0
  65. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_division_spec.rb +15 -0
  66. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_exponentiation_spec.rb +15 -0
  67. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_modulo_spec.rb +15 -0
  68. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_multiplication_spec.rb +15 -0
  69. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_square_root_spec.rb +15 -0
  70. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_subtraction_spec.rb +15 -0
  71. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_unary_minus_spec.rb +15 -0
  72. data/spec/unit/axiom/sql/generator/function/numeric/visit_axiom_function_numeric_unary_plus_spec.rb +15 -0
  73. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_equality_spec.rb +27 -0
  74. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_exclusion_spec.rb +47 -0
  75. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_greater_than_or_equal_to_spec.rb +15 -0
  76. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_greater_than_spec.rb +15 -0
  77. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_inclusion_spec.rb +47 -0
  78. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_inequality_spec.rb +55 -0
  79. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_less_than_or_equal_to_spec.rb +15 -0
  80. data/spec/unit/axiom/sql/generator/function/predicate/visit_axiom_function_predicate_less_than_spec.rb +15 -0
  81. data/spec/unit/axiom/sql/generator/function/proposition/visit_axiom_function_proposition_contradiction_spec.rb +15 -0
  82. data/spec/unit/axiom/sql/generator/function/proposition/visit_axiom_function_proposition_tautology_spec.rb +15 -0
  83. data/spec/unit/axiom/sql/generator/function/string/visit_axiom_function_string_length_spec.rb +15 -0
  84. data/spec/unit/axiom/sql/generator/identifier/visit_identifier_spec.rb +26 -0
  85. data/spec/unit/axiom/sql/generator/literal/class_methods/dup_frozen_spec.rb +23 -0
  86. data/spec/unit/axiom/sql/generator/literal/visit_class_spec.rb +31 -0
  87. data/spec/unit/axiom/sql/generator/literal/visit_date_spec.rb +15 -0
  88. data/spec/unit/axiom/sql/generator/literal/visit_date_time_spec.rb +55 -0
  89. data/spec/unit/axiom/sql/generator/literal/visit_enumerable_spec.rb +15 -0
  90. data/spec/unit/axiom/sql/generator/literal/visit_false_class_spec.rb +14 -0
  91. data/spec/unit/axiom/sql/generator/literal/visit_nil_class_spec.rb +14 -0
  92. data/spec/unit/axiom/sql/generator/literal/visit_numeric_spec.rb +34 -0
  93. data/spec/unit/axiom/sql/generator/literal/visit_string_spec.rb +26 -0
  94. data/spec/unit/axiom/sql/generator/literal/visit_time_spec.rb +97 -0
  95. data/spec/unit/axiom/sql/generator/literal/visit_true_class_spec.rb +14 -0
  96. data/spec/unit/axiom/sql/generator/relation/binary/base/to_subquery_spec.rb +35 -0
  97. data/spec/unit/axiom/sql/generator/relation/binary/base/visit_axiom_relation_base_spec.rb +22 -0
  98. data/spec/unit/axiom/sql/generator/relation/binary/to_s_spec.rb +35 -0
  99. data/spec/unit/axiom/sql/generator/relation/binary/to_subquery_spec.rb +35 -0
  100. data/spec/unit/axiom/sql/generator/relation/binary/visit_axiom_algebra_join_spec.rb +179 -0
  101. data/spec/unit/axiom/sql/generator/relation/binary/visit_axiom_algebra_product_spec.rb +183 -0
  102. data/spec/unit/axiom/sql/generator/relation/class_methods/visit_spec.rb +71 -0
  103. data/spec/unit/axiom/sql/generator/relation/insertion/to_subquery_spec.rb +15 -0
  104. data/spec/unit/axiom/sql/generator/relation/insertion/visit_axiom_relation_operation_insertion_spec.rb +187 -0
  105. data/spec/unit/axiom/sql/generator/relation/materialized/visit_axiom_relation_materialized_spec.rb +28 -0
  106. data/spec/unit/axiom/sql/generator/relation/materialized/visited_spec.rb +26 -0
  107. data/spec/unit/axiom/sql/generator/relation/name_spec.rb +30 -0
  108. data/spec/unit/axiom/sql/generator/relation/set/class_methods/normalize_operand_headers_spec.rb +35 -0
  109. data/spec/unit/axiom/sql/generator/relation/set/to_s_spec.rb +55 -0
  110. data/spec/unit/axiom/sql/generator/relation/set/to_subquery_spec.rb +55 -0
  111. data/spec/unit/axiom/sql/generator/relation/set/visit_axiom_algebra_difference_spec.rb +191 -0
  112. data/spec/unit/axiom/sql/generator/relation/set/visit_axiom_algebra_intersection_spec.rb +188 -0
  113. data/spec/unit/axiom/sql/generator/relation/set/visit_axiom_algebra_union_spec.rb +188 -0
  114. data/spec/unit/axiom/sql/generator/relation/to_s_spec.rb +50 -0
  115. data/spec/unit/axiom/sql/generator/relation/to_sql_spec.rb +52 -0
  116. data/spec/unit/axiom/sql/generator/relation/to_subquery_spec.rb +49 -0
  117. data/spec/unit/axiom/sql/generator/relation/unary/to_s_spec.rb +55 -0
  118. data/spec/unit/axiom/sql/generator/relation/unary/to_subquery_spec.rb +75 -0
  119. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_algebra_extension_spec.rb +165 -0
  120. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_algebra_projection_spec.rb +193 -0
  121. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_algebra_rename_spec.rb +178 -0
  122. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_algebra_restriction_spec.rb +199 -0
  123. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_algebra_summarization_spec.rb +652 -0
  124. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_relation_base_spec.rb +21 -0
  125. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_relation_operation_limit_spec.rb +165 -0
  126. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_relation_operation_offset_spec.rb +165 -0
  127. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_relation_operation_order_spec.rb +183 -0
  128. data/spec/unit/axiom/sql/generator/relation/unary/visit_axiom_relation_operation_reverse_spec.rb +165 -0
  129. data/spec/unit/axiom/sql/generator/relation/visit_spec.rb +54 -0
  130. data/spec/unit/axiom/sql/generator/relation/visited_spec.rb +35 -0
  131. data/spec/unit/axiom/sql/generator/visitor/class_methods/handler_for_spec.rb +71 -0
  132. data/spec/unit/axiom/sql/generator/visitor/visit_spec.rb +12 -0
  133. data/spec/unit/axiom/sql/generator/visitor/visited_spec.rb +11 -0
  134. data/spec/unit/date/iso8601_spec.rb +23 -0
  135. data/spec/unit/date_time/iso8601_spec.rb +112 -0
  136. metadata +325 -0
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 100
@@ -0,0 +1,3 @@
1
+ # encoding: utf-8
2
+
3
+ require 'axiom/sql/generator'
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'date'
4
+ require 'time'
5
+
6
+ require 'axiom'
7
+
8
+ require 'axiom/sql/generator/core_ext/date'
9
+ require 'axiom/sql/generator/core_ext/date_time'
10
+
11
+ require 'axiom/sql/generator/visitor'
12
+
13
+ require 'axiom/sql/generator/identifier'
14
+ require 'axiom/sql/generator/attribute'
15
+ require 'axiom/sql/generator/direction'
16
+ require 'axiom/sql/generator/literal'
17
+
18
+ require 'axiom/sql/generator/function'
19
+ require 'axiom/sql/generator/function/aggregate'
20
+ require 'axiom/sql/generator/function/connective'
21
+ require 'axiom/sql/generator/function/numeric'
22
+ require 'axiom/sql/generator/function/predicate'
23
+ require 'axiom/sql/generator/function/proposition'
24
+ require 'axiom/sql/generator/function/string'
25
+
26
+ require 'axiom/sql/generator/relation'
27
+ require 'axiom/sql/generator/relation/unary'
28
+ require 'axiom/sql/generator/relation/base'
29
+ require 'axiom/sql/generator/relation/binary'
30
+ require 'axiom/sql/generator/relation/materialized'
31
+ require 'axiom/sql/generator/relation/set'
32
+
33
+ require 'axiom/sql/generator/relation/insertion'
34
+
35
+ require 'axiom/sql/generator/version'
36
+
37
+ module Axiom
38
+ module SQL
39
+ module Generator
40
+
41
+ # Raised when an invalid relation is visited
42
+ class InvalidRelationError < StandardError; end
43
+
44
+ LEFT_PARENTHESIS = '('.freeze
45
+ RIGHT_PARENTHESIS = ')'.freeze
46
+
47
+ # Return a parenthesized SQL statement (inline modification)
48
+ #
49
+ # @param [#to_s] sql
50
+ #
51
+ # @return [#to_s]
52
+ # same instance as sql
53
+ #
54
+ # @api private
55
+ def self.parenthesize!(sql)
56
+ sql.insert(0, LEFT_PARENTHESIS) << RIGHT_PARENTHESIS
57
+ end
58
+
59
+ end # module Generator
60
+ end # module SQL
61
+ end # module Axiom
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module SQL
5
+ module Generator
6
+
7
+ # Generates an SQL statement for an attribute
8
+ module Attribute
9
+ include Identifier
10
+
11
+ # Visit an Attribute
12
+ #
13
+ # @param [Attribute] attribute
14
+ #
15
+ # @return [#to_s]
16
+ #
17
+ # @api private
18
+ def visit_axiom_attribute(attribute)
19
+ visit_identifier(attribute.name)
20
+ end
21
+
22
+ end # module Attribute
23
+ end # module Generator
24
+ end # module SQL
25
+ end # module Axiom
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ # Extend Date with methods available in ruby 1.9
4
+ class Date
5
+
6
+ ISO_8601_FORMAT = '%F'.freeze
7
+
8
+ # Return the Date in ISO8601 date format
9
+ #
10
+ # @return [#to_s]
11
+ #
12
+ # @todo Remove once backports adds this method
13
+ #
14
+ # @api private
15
+ def iso8601
16
+ date = frozen? ? dup : self
17
+ date.strftime(ISO_8601_FORMAT)
18
+ end
19
+
20
+ end # class Date
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ # Extend DateTime with methods available in ruby 1.9
4
+ class DateTime
5
+
6
+ # TODO: remove the rbx guard when fractional seconds are handled properly in 1.9 mode
7
+ SEC_FRACTION_MULTIPLIER = RUBY_VERSION < '1.9' ? 60 * 60 * 24 : 1
8
+
9
+ # Return the DateTime in ISO8601 date-time format
10
+ #
11
+ # @param [Integer] time_scale
12
+ # the number of significant digits to use for fractional seconds
13
+ #
14
+ # @return [#to_s]
15
+ #
16
+ # @todo Remove once backports adds this method
17
+ #
18
+ # @api private
19
+ def iso8601(time_scale = 0)
20
+ super() + iso8601_timediv(time_scale)
21
+ end
22
+
23
+ private
24
+
25
+ # Return the time with fraction seconds
26
+ #
27
+ # @param [Integer] time_scale
28
+ # the number of significant digits to use for fractional seconds
29
+ #
30
+ # @return [#to_s]
31
+ #
32
+ # @api private
33
+ def iso8601_timediv(time_scale)
34
+ date_time = frozen? ? dup : self
35
+
36
+ fractional_seconds = unless time_scale.zero?
37
+ '.%0*d' % [
38
+ time_scale,
39
+ date_time.sec_fraction * SEC_FRACTION_MULTIPLIER * 10**time_scale
40
+ ]
41
+ end
42
+
43
+ date_time.strftime("T%T#{fractional_seconds}%Z")
44
+ end
45
+
46
+ end # class DateTime
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module SQL
5
+ module Generator
6
+
7
+ # Generates an SQL statement for a direction
8
+ module Direction
9
+ include Attribute
10
+
11
+ DESC = ' DESC'.freeze
12
+
13
+ # Visit an Ascending Direction
14
+ #
15
+ # @param [Relation::Operation::Order::Ascending] direction
16
+ #
17
+ # @return [#to_s]
18
+ #
19
+ # @api private
20
+ def visit_axiom_relation_operation_order_ascending(direction)
21
+ dispatch direction.attribute
22
+ end
23
+
24
+ # Visit an Descending Direction
25
+ #
26
+ # @param [Relation::Operation::Order::Descending] direction
27
+ #
28
+ # @return [#to_s]
29
+ #
30
+ # @api private
31
+ def visit_axiom_relation_operation_order_descending(direction)
32
+ dispatch(direction.attribute) << DESC
33
+ end
34
+
35
+ end # module Direction
36
+ end # module Generator
37
+ end # module SQL
38
+ end # module Axiom
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module SQL
5
+ module Generator
6
+
7
+ # Generates an SQL statement for a function expression
8
+ module Function
9
+ include Attribute, Literal
10
+
11
+ private
12
+
13
+ # Return the SQL for a umary prefix operation
14
+ #
15
+ # @param [#to_s] operator
16
+ #
17
+ # @param [Function::Unary] function
18
+ #
19
+ # @return [#to_s]
20
+ #
21
+ # @api private
22
+ def unary_prefix_operation_sql(operator, function)
23
+ "#{operator} (#{dispatch(function.operand)})"
24
+ end
25
+
26
+ # Return the SQL for a binary prefix operation
27
+ #
28
+ # @param [#to_s] operator
29
+ #
30
+ # @param [Function::Binary] function
31
+ #
32
+ # @return [#to_s]
33
+ #
34
+ # @api private
35
+ def binary_prefix_operation_sql(operator, function)
36
+ "#{operator} (#{dispatch(function.left)}, #{dispatch(function.right)})"
37
+ end
38
+
39
+ # Return the SQL for a binary infix operation
40
+ #
41
+ # @param [#to_s] operator
42
+ #
43
+ # @param [Function::Binary] function
44
+ #
45
+ # @return [#to_s]
46
+ #
47
+ # @api private
48
+ def binary_infix_operation_sql(operator, function)
49
+ "#{dispatch(function.left)} #{operator} #{dispatch(function.right)}"
50
+ end
51
+
52
+ end # module Function
53
+ end # module Generator
54
+ end # module SQL
55
+ end # module Axiom
@@ -0,0 +1,134 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module SQL
5
+ module Generator
6
+ module Function
7
+
8
+ # Generates an SQL statement for an aggregate function
9
+ module Aggregate
10
+ include Function
11
+
12
+ COUNT = 'COUNT'.freeze
13
+ SUM = 'SUM'.freeze
14
+ MINIMUM = 'MIN'.freeze
15
+ MAXIMUM = 'MAX'.freeze
16
+ MEAN = 'AVG'.freeze
17
+ VARIANCE = 'VAR_POP'.freeze
18
+ STANDARD_DEVIATION = 'STDDEV_POP'.freeze
19
+
20
+ # Visit a count aggregate function
21
+ #
22
+ # @param [Axiom::Aggregate::Count] count
23
+ #
24
+ # @return [#to_s]
25
+ #
26
+ # @api private
27
+ def visit_axiom_aggregate_count(count)
28
+ unary_prefix_operation_sql(COUNT, count)
29
+ end
30
+
31
+ # Visit a sum aggregate function
32
+ #
33
+ # @param [Axiom::Aggregate::Sum] sum
34
+ #
35
+ # @return [#to_s]
36
+ #
37
+ # @api private
38
+ def visit_axiom_aggregate_sum(sum)
39
+ aggregate_function_sql(SUM, sum)
40
+ end
41
+
42
+ # Visit a minimum aggregate function
43
+ #
44
+ # @param [Axiom::Aggregate::Minimum] minimum
45
+ #
46
+ # @return [#to_s]
47
+ #
48
+ # @api private
49
+ def visit_axiom_aggregate_minimum(minimum)
50
+ # TODO: wrap this in a coalesce operation once the default can be made sane
51
+ unary_prefix_operation_sql(MINIMUM, minimum)
52
+ end
53
+
54
+ # Visit a maximum aggregate function
55
+ #
56
+ # @param [Axiom::Aggregate::Maximum] maximum
57
+ #
58
+ # @return [#to_s]
59
+ #
60
+ # @api private
61
+ def visit_axiom_aggregate_maximum(maximum)
62
+ # TODO: wrap this in a coalesce operation once the default can be made sane
63
+ unary_prefix_operation_sql(MAXIMUM, maximum)
64
+ end
65
+
66
+ # Visit a mean aggregate function
67
+ #
68
+ # @param [Axiom::Aggregate::Mean] mean
69
+ #
70
+ # @return [#to_s]
71
+ #
72
+ # @api private
73
+ def visit_axiom_aggregate_mean(mean)
74
+ unary_prefix_operation_sql(MEAN, mean)
75
+ end
76
+
77
+ # Visit a variance aggregate function
78
+ #
79
+ # @param [Axiom::Aggregate::Variance] variance
80
+ #
81
+ # @return [#to_s]
82
+ #
83
+ # @api private
84
+ def visit_axiom_aggregate_variance(variance)
85
+ unary_prefix_operation_sql(VARIANCE, variance)
86
+ end
87
+
88
+ # Visit a standard deviation aggregate function
89
+ #
90
+ # @param [Axiom::Aggregate::StandardDeviation] standard_deviation
91
+ #
92
+ # @return [#to_s]
93
+ #
94
+ # @api private
95
+ def visit_axiom_aggregate_standard_deviation(standard_deviation)
96
+ unary_prefix_operation_sql(STANDARD_DEVIATION, standard_deviation)
97
+ end
98
+
99
+ private
100
+
101
+ # Return the SQL
102
+ #
103
+ # @param [#to_s] operation
104
+ #
105
+ # @param [Axiom::Aggregate] aggregate
106
+ #
107
+ # @return [#to_s]
108
+ #
109
+ # @api private
110
+ def aggregate_function_sql(operation, aggregate)
111
+ default_when_null(
112
+ unary_prefix_operation_sql(operation, aggregate),
113
+ aggregate.finalize(aggregate.default)
114
+ )
115
+ end
116
+
117
+ # Specify a default value when SQL expression evaluates to NULL
118
+ #
119
+ # @param [#to_s] sql
120
+ #
121
+ # @param [Visitable] default
122
+ #
123
+ # @return [#to_s]
124
+ #
125
+ # @api private
126
+ def default_when_null(sql, default)
127
+ "COALESCE (#{sql}, #{dispatch(default)})"
128
+ end
129
+
130
+ end # module Aggregate
131
+ end # module Function
132
+ end # module Generator
133
+ end # module SQL
134
+ end # module Axiom
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module SQL
5
+ module Generator
6
+ module Function
7
+
8
+ # Generates an SQL statement for a connective
9
+ module Connective
10
+ include Function
11
+
12
+ AND = 'AND'.freeze
13
+ OR = 'OR'.freeze
14
+ NOT = 'NOT'.freeze
15
+
16
+ # Visit an Conjunction connective
17
+ #
18
+ # @param [Function::Connective::Conjunction] conjunction
19
+ #
20
+ # @return [#to_s]
21
+ #
22
+ # @api private
23
+ def visit_axiom_function_connective_conjunction(conjunction)
24
+ Generator.parenthesize!(binary_infix_operation_sql(AND, conjunction))
25
+ end
26
+
27
+ # Visit an Disjunction connective
28
+ #
29
+ # @param [Function::Connective::Disjunction] disjunction
30
+ #
31
+ # @return [#to_s]
32
+ #
33
+ # @api private
34
+ def visit_axiom_function_connective_disjunction(disjunction)
35
+ Generator.parenthesize!(binary_infix_operation_sql(OR, disjunction))
36
+ end
37
+
38
+ # Visit an Negation connective
39
+ #
40
+ # @param [Function::Connective::Negation] negation
41
+ #
42
+ # @return [#to_s]
43
+ #
44
+ # @api private
45
+ def visit_axiom_function_connective_negation(negation)
46
+ unary_prefix_operation_sql(NOT, negation)
47
+ end
48
+
49
+ end # module Connective
50
+ end # module Function
51
+ end # module Generator
52
+ end # module SQL
53
+ end # module Axiom