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,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Veritas
4
+ module SQL
5
+ module Generator
6
+ VERSION = '0.0.3'
7
+ end # module Generator
8
+ end # module SQL
9
+ end # module Veritas
@@ -0,0 +1,121 @@
1
+ # encoding: utf-8
2
+
3
+ module Veritas
4
+ module SQL
5
+ module Generator
6
+
7
+ # Visit each node in a veritas AST and execute an associated method
8
+ class Visitor
9
+
10
+ # Raised when the object is not handled by the generator
11
+ class UnknownObject < StandardError; end
12
+
13
+ NAME_SEP_REGEXP = /([a-z])([A-Z])/.freeze
14
+ NAME_REP = '\1_\2'.freeze
15
+ DOUBLE_COLON = '::'.freeze
16
+ UNDERSCORE = '_'.freeze
17
+
18
+ # Lookup the handler method for a visitable class
19
+ #
20
+ # @param [Class<Visitable>] visitable_class
21
+ #
22
+ # @return [#to_sym]
23
+ #
24
+ # @raise [UnknownObject]
25
+ # raised when the visitable object has no handler
26
+ #
27
+ # @api private
28
+ def self.handler_for(visitable_class)
29
+ handlers[visitable_class] or raise UnknownObject, "No handler for #{visitable_class} in #{self}"
30
+ end
31
+
32
+ # Return the handler cache that maps modules to method names
33
+ #
34
+ # @return [Hash]
35
+ #
36
+ # @api private
37
+ def self.handlers
38
+ @handlers ||= Hash.new do |hash, key|
39
+ hash[key] = ancestor_methods_for(key).detect do |method|
40
+ method_defined?(method) || private_method_defined?(method)
41
+ end
42
+ end
43
+ end
44
+
45
+ # Return handler methods for a module's ancestors
46
+ #
47
+ # @param [Module] mod
48
+ #
49
+ # @return [Array<Symbol>]
50
+ #
51
+ # @api private
52
+ def self.ancestor_methods_for(mod)
53
+ mod.ancestors.map { |ancestor| method_for(ancestor) }
54
+ end
55
+
56
+ # Return the handler method for a given module
57
+ #
58
+ # @param [Module] mod
59
+ #
60
+ # @return [Symbol]
61
+ #
62
+ # @api private
63
+ def self.method_for(mod)
64
+ name = "visit_#{mod.name}"
65
+ name.gsub!(NAME_SEP_REGEXP, NAME_REP)
66
+ name.gsub!(DOUBLE_COLON, UNDERSCORE)
67
+ name.downcase!
68
+ name.to_sym
69
+ end
70
+
71
+ private_class_method :handlers, :ancestor_methods_for, :method_for
72
+
73
+ # Visit an object and generate SQL from each node
74
+ #
75
+ # @example
76
+ # generator.visit(visitable)
77
+ #
78
+ # @param [Visitable] visitable
79
+ #
80
+ # @return [self]
81
+ #
82
+ # @raise [UnknownObject]
83
+ # raised when the visitable object has no handler
84
+ #
85
+ # @api public
86
+ def visit(visitable)
87
+ raise NotImplementedError, "#{self.class}#visit must be implemented"
88
+ end
89
+
90
+ # Test if a visitable object has been visited
91
+ #
92
+ # @example
93
+ # visitor.visited? # true or false
94
+ #
95
+ # @return [Boolean]
96
+ #
97
+ # @api public
98
+ def visited?
99
+ raise NotImplementedError, "#{self.class}#visited? must be implemented"
100
+ end
101
+
102
+ private
103
+
104
+ # Dispatch the visitable object to a handler method
105
+ #
106
+ # @param [Visitable] visitable
107
+ #
108
+ # @return [#to_s]
109
+ #
110
+ # @raise [UnknownObject]
111
+ # raised when the visitable object has no handler
112
+ #
113
+ # @api private
114
+ def dispatch(visitable)
115
+ send(self.class.handler_for(visitable.class), visitable)
116
+ end
117
+
118
+ end # class Visitor
119
+ end # module Generator
120
+ end # module SQL
121
+ end # module Veritas
@@ -0,0 +1,6 @@
1
+ --exclude-only "spec/,^/"
2
+ --sort coverage
3
+ --callsites
4
+ --xrefs
5
+ --profile
6
+ --text-summary
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples_for 'a command method' do
4
+ it 'returns self' do
5
+ should equal(object)
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples_for 'a generated SQL expression' do
4
+ it { should respond_to(:to_s) }
5
+
6
+ its(:to_s) { should be_kind_of(String) }
7
+ end
8
+
9
+ shared_examples_for 'a generated SQL SELECT query' do
10
+ it_should_behave_like 'a generated SQL expression'
11
+
12
+ its(:name) { should == relation_name }
13
+
14
+ its(:name) { should be_frozen }
15
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples_for 'an idempotent method' do
4
+ it 'is idempotent' do
5
+ should equal(instance_eval(&self.class.subject))
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ --color
2
+ --loadby random
3
+ --format profile
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'backports'
5
+ require 'veritas/sql/generator'
6
+ require 'spec'
7
+ require 'spec/autorun'
8
+
9
+ include Veritas
10
+
11
+ # require spec support files and shared behavior
12
+ Dir[File.expand_path('../{support,shared}/**/*.rb', __FILE__)].each { |f| require f }
13
+
14
+ Spec::Runner.configure do |config|
15
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe BaseRelation, '#name' do
6
+ subject { object.name }
7
+
8
+ let(:header) { [ [ :id, Integer ] ] }
9
+ let(:body) { [ [ 1 ] ].each }
10
+ let(:object) { described_class.new(name, header, body) }
11
+
12
+ context 'when name is a frozen String' do
13
+ let(:name) { 'users'.freeze }
14
+
15
+ it_should_behave_like 'an idempotent method'
16
+
17
+ it { should equal(name) }
18
+
19
+ it { should be_frozen }
20
+ end
21
+
22
+ context 'when name is a String' do
23
+ let(:name) { 'users' }
24
+
25
+ it_should_behave_like 'an idempotent method'
26
+
27
+ it { should_not equal(name) }
28
+
29
+ it { should eql(name) }
30
+
31
+ it { should be_frozen }
32
+ end
33
+
34
+ context 'when name responds to #to_s' do
35
+ let(:name) { :users }
36
+
37
+ it_should_behave_like 'an idempotent method'
38
+
39
+ it { should_not equal(name) }
40
+
41
+ it { should eql(name.to_s) }
42
+
43
+ it { should be_frozen }
44
+ end
45
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Attribute, '#visit_veritas_attribute' do
6
+ subject { object.visit_veritas_attribute(attribute) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Attribute } }
9
+ let(:attribute) { Attribute::Integer.new(:id) }
10
+ let(:object) { described_class.new }
11
+
12
+ it_should_behave_like 'a generated SQL expression'
13
+
14
+ its(:to_s) { should eql('"id"') }
15
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Direction, '#visit_veritas_relation_operation_order_ascending' do
6
+ subject { object.visit_veritas_relation_operation_order_ascending(direction) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Direction } }
9
+ let(:direction) { Attribute::Integer.new(:id).asc }
10
+ let(:object) { described_class.new }
11
+
12
+ it_should_behave_like 'a generated SQL expression'
13
+
14
+ its(:to_s) { should eql('"id"') }
15
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Direction, '#visit_veritas_relation_operation_order_descending' do
6
+ subject { object.visit_veritas_relation_operation_order_descending(direction) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Direction } }
9
+ let(:direction) { Attribute::Integer.new(:id).desc }
10
+ let(:object) { described_class.new }
11
+
12
+ it_should_behave_like 'a generated SQL expression'
13
+
14
+ its(:to_s) { should eql('"id" DESC') }
15
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Identifier, '#visit_identifier' do
6
+ subject { object.visit_identifier(identifier) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Identifier } }
9
+ let(:object) { described_class.new }
10
+
11
+ context 'with an identifier containing no quotes' do
12
+ let(:identifier) { 'users' }
13
+
14
+ it_should_behave_like 'a generated SQL expression'
15
+
16
+ its(:to_s) { should eql('"users"') }
17
+ end
18
+
19
+ context 'with an identifier containing quotes' do
20
+ let(:identifier) { 'users"name' }
21
+
22
+ it_should_behave_like 'a generated SQL expression'
23
+
24
+ its(:to_s) { should eql('"users""name"') }
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Literal, '.dup_frozen' do
6
+ subject { object.dup_frozen(object_arg) }
7
+
8
+ let(:object) { SQL::Generator::Literal }
9
+
10
+ context 'with a frozen object' do
11
+ let(:object_arg) { Date.today.freeze }
12
+
13
+ it { should_not equal(object_arg) }
14
+
15
+ it { should == object_arg }
16
+ end
17
+
18
+ context 'with a non-frozen object' do
19
+ let(:object_arg) { Date.today }
20
+
21
+ it { should equal(object_arg) }
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Literal, '#visit_class' do
6
+ subject { object.visit_class(klass) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Literal } }
9
+ let(:object) { described_class.new }
10
+
11
+ before do
12
+ Object.class_eval { remove_const(:NamedClass) if const_defined?(:NamedClass) }
13
+ class ::NamedClass; end
14
+ end
15
+
16
+ context 'with a named class' do
17
+ let(:klass) { NamedClass.freeze }
18
+
19
+ it_should_behave_like 'a generated SQL expression'
20
+
21
+ its(:to_s) { should eql("'NamedClass'") }
22
+ end
23
+
24
+ context 'with an anonymous class' do
25
+ let(:klass) { described_class }
26
+
27
+ it_should_behave_like 'a generated SQL expression'
28
+
29
+ its(:to_s) { should eql('NULL') }
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Literal, '#visit_date' do
6
+ subject { object.visit_date(date) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Literal } }
9
+ let(:date) { Date.new(2010, 12, 31).freeze }
10
+ let(:object) { described_class.new }
11
+
12
+ it_should_behave_like 'a generated SQL expression'
13
+
14
+ its(:to_s) { should eql("'2010-12-31'") }
15
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SQL::Generator::Literal, '#visit_date_time' do
6
+ subject { object.visit_date_time(date_time) }
7
+
8
+ let(:described_class) { Class.new(SQL::Generator::Visitor) { include SQL::Generator::Literal } }
9
+ let(:nsec_in_seconds) { Rational(nsec, 10**9) }
10
+ let(:object) { described_class.new }
11
+
12
+ context 'when the DateTime is UTC' do
13
+ let(:offset) { 0 }
14
+
15
+ context 'and the nanoseconds are equal to 0' do
16
+ let(:nsec) { 0 }
17
+ let(:date_time) { DateTime.new(2010, 12, 31, 23, 59, 59 + nsec_in_seconds, offset).freeze }
18
+
19
+ it_should_behave_like 'a generated SQL expression'
20
+
21
+ its(:to_s) { should eql("'2010-12-31T23:59:59.000000000+00:00'") }
22
+ end
23
+
24
+ # rubinius 1.2.3 has problems with fractional seconds above 59
25
+ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' && Rubinius::VERSION <= '1.2.3'
26
+ context 'and the nanoseconds are greater than 0' do
27
+ let(:nsec) { 1 }
28
+ let(:date_time) { DateTime.new(2010, 12, 31, 23, 59, 59 + nsec_in_seconds, offset).freeze }
29
+
30
+ it_should_behave_like 'a generated SQL expression'
31
+
32
+ its(:to_s) { should eql("'2010-12-31T23:59:59.000000001+00:00'") }
33
+ end
34
+ end
35
+ end
36
+
37
+ context 'when the DateTime is not UTC' do
38
+ let(:offset) { Rational(-8, 24) }
39
+
40
+ context 'and the nanoseconds are equal to 0' do
41
+ let(:nsec) { 0 }
42
+ let(:date_time) { DateTime.new(2010, 12, 31, 15, 59, 59 + nsec_in_seconds, offset).freeze }
43
+
44
+ it_should_behave_like 'a generated SQL expression'
45
+
46
+ its(:to_s) { should eql("'2010-12-31T23:59:59.000000000+00:00'") }
47
+ end
48
+
49
+ # rubinius 1.2.3 has problems with fractional seconds above 59
50
+ unless defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' && Rubinius::VERSION <= '1.2.3'
51
+ context 'and the nanoseconds are greater than 0' do
52
+ let(:nsec) { 1 }
53
+ let(:date_time) { DateTime.new(2010, 12, 31, 15, 59, 59 + nsec_in_seconds, offset).freeze }
54
+
55
+ it_should_behave_like 'a generated SQL expression'
56
+
57
+ its(:to_s) { should eql("'2010-12-31T23:59:59.000000001+00:00'") }
58
+ end
59
+ end
60
+ end
61
+ end