axiom-sql-generator 0.1.0

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