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.
- data/Gemfile +33 -0
- data/LICENSE +20 -0
- data/README.rdoc +27 -0
- data/Rakefile +25 -0
- data/TODO +17 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +16 -0
- data/config/site.reek +124 -0
- data/config/yardstick.yml +2 -0
- data/lib/veritas-sql-generator.rb +3 -0
- data/lib/veritas/base_relation.rb +36 -0
- data/lib/veritas/sql/generator.rb +35 -0
- data/lib/veritas/sql/generator/attribute.rb +25 -0
- data/lib/veritas/sql/generator/direction.rb +36 -0
- data/lib/veritas/sql/generator/identifier.rb +27 -0
- data/lib/veritas/sql/generator/literal.rb +160 -0
- data/lib/veritas/sql/generator/logic.rb +349 -0
- data/lib/veritas/sql/generator/relation.rb +111 -0
- data/lib/veritas/sql/generator/relation/base.rb +14 -0
- data/lib/veritas/sql/generator/relation/binary.rb +184 -0
- data/lib/veritas/sql/generator/relation/set.rb +99 -0
- data/lib/veritas/sql/generator/relation/unary.rb +326 -0
- data/lib/veritas/sql/generator/version.rb +9 -0
- data/lib/veritas/sql/generator/visitor.rb +121 -0
- data/spec/rcov.opts +6 -0
- data/spec/shared/command_method_behavior.rb +7 -0
- data/spec/shared/generated_sql_behavior.rb +15 -0
- data/spec/shared/idempotent_method_behavior.rb +7 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/unit/veritas/base_relation/name_spec.rb +45 -0
- data/spec/unit/veritas/sql/generator/attribute/visit_veritas_attribute_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/direction/visit_veritas_relation_operation_order_ascending_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/direction/visit_veritas_relation_operation_order_descending_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/identifier/visit_identifier_spec.rb +26 -0
- data/spec/unit/veritas/sql/generator/literal/class_methods/dup_frozen_spec.rb +23 -0
- data/spec/unit/veritas/sql/generator/literal/visit_class_spec.rb +31 -0
- data/spec/unit/veritas/sql/generator/literal/visit_date_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/literal/visit_date_time_spec.rb +61 -0
- data/spec/unit/veritas/sql/generator/literal/visit_enumerable_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/literal/visit_false_class_spec.rb +14 -0
- data/spec/unit/veritas/sql/generator/literal/visit_nil_class_spec.rb +14 -0
- data/spec/unit/veritas/sql/generator/literal/visit_numeric_spec.rb +34 -0
- data/spec/unit/veritas/sql/generator/literal/visit_string_spec.rb +26 -0
- data/spec/unit/veritas/sql/generator/literal/visit_time_spec.rb +97 -0
- data/spec/unit/veritas/sql/generator/literal/visit_true_class_spec.rb +14 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_conjunction_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_disjunction_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_connective_negation_spec.rb +16 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_equality_spec.rb +27 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_exclusion_spec.rb +43 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_greater_than_or_equal_to_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_greater_than_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_inclusion_spec.rb +43 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_inequality_spec.rb +55 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_less_than_or_equal_to_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_predicate_less_than_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_contradiction_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/logic/visit_veritas_logic_proposition_tautology_spec.rb +15 -0
- data/spec/unit/veritas/sql/generator/relation/binary/base/to_subquery_spec.rb +35 -0
- data/spec/unit/veritas/sql/generator/relation/binary/base/visit_veritas_base_relation_spec.rb +22 -0
- data/spec/unit/veritas/sql/generator/relation/binary/class_methods/subquery_spec.rb +42 -0
- data/spec/unit/veritas/sql/generator/relation/binary/to_s_spec.rb +35 -0
- data/spec/unit/veritas/sql/generator/relation/binary/to_subquery_spec.rb +35 -0
- data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_join_spec.rb +138 -0
- data/spec/unit/veritas/sql/generator/relation/binary/visit_veritas_algebra_product_spec.rb +139 -0
- data/spec/unit/veritas/sql/generator/relation/class_methods/subquery_spec.rb +33 -0
- data/spec/unit/veritas/sql/generator/relation/class_methods/visit_spec.rb +61 -0
- data/spec/unit/veritas/sql/generator/relation/name_spec.rb +30 -0
- data/spec/unit/veritas/sql/generator/relation/set/to_s_spec.rb +55 -0
- data/spec/unit/veritas/sql/generator/relation/set/to_subquery_spec.rb +55 -0
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_difference_spec.rb +138 -0
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_intersection_spec.rb +138 -0
- data/spec/unit/veritas/sql/generator/relation/set/visit_veritas_algebra_union_spec.rb +138 -0
- data/spec/unit/veritas/sql/generator/relation/to_sql_spec.rb +52 -0
- data/spec/unit/veritas/sql/generator/relation/unary/to_s_spec.rb +55 -0
- data/spec/unit/veritas/sql/generator/relation/unary/to_subquery_spec.rb +75 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_projection_spec.rb +138 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_rename_spec.rb +136 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_algebra_restriction_spec.rb +157 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_base_relation_spec.rb +21 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_limit_spec.rb +125 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_offset_spec.rb +125 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_order_spec.rb +136 -0
- data/spec/unit/veritas/sql/generator/relation/unary/visit_veritas_relation_operation_reverse_spec.rb +125 -0
- data/spec/unit/veritas/sql/generator/relation/visit_spec.rb +54 -0
- data/spec/unit/veritas/sql/generator/relation/visited_spec.rb +35 -0
- data/spec/unit/veritas/sql/generator/visitor/class_methods/handler_for_spec.rb +71 -0
- data/spec/unit/veritas/sql/generator/visitor/visit_spec.rb +12 -0
- data/spec/unit/veritas/sql/generator/visitor/visited_spec.rb +11 -0
- data/tasks/quality/ci.rake +2 -0
- data/tasks/quality/flay.rake +41 -0
- data/tasks/quality/flog.rake +45 -0
- data/tasks/quality/heckle.rake +203 -0
- data/tasks/quality/metric_fu.rake +26 -0
- data/tasks/quality/reek.rake +9 -0
- data/tasks/quality/roodi.rake +15 -0
- data/tasks/quality/yardstick.rake +23 -0
- data/tasks/spec.rake +38 -0
- data/tasks/yard.rake +9 -0
- data/veritas-sql-generator.gemspec +222 -0
- metadata +285 -0
|
@@ -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
|
data/spec/rcov.opts
ADDED
|
@@ -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
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
|
@@ -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
|