arel 2.1.1 → 2.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/arel.gemspec +16 -16
- data/lib/arel.rb +1 -1
- data/lib/arel/nodes.rb +2 -1
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/named_function.rb +0 -2
- data/lib/arel/nodes/ordering.rb +1 -15
- data/lib/arel/nodes/unary.rb +1 -0
- data/lib/arel/order_predications.rb +2 -2
- data/lib/arel/visitors.rb +2 -0
- data/lib/arel/visitors/depth_first.rb +1 -1
- data/lib/arel/visitors/dot.rb +0 -1
- data/lib/arel/visitors/mssql.rb +59 -9
- data/lib/arel/visitors/to_sql.rb +6 -2
- data/lib/arel/visitors/visitor.rb +8 -4
- data/test/attributes/test_attribute.rb +4 -4
- data/test/nodes/test_ascending.rb +34 -0
- data/test/nodes/test_count.rb +9 -0
- data/test/nodes/test_descending.rb +34 -0
- data/test/nodes/test_infix_operation.rb +2 -2
- data/test/visitors/test_depth_first.rb +1 -1
- data/test/visitors/test_dot.rb +1 -1
- data/test/visitors/test_informix.rb +42 -0
- data/test/visitors/test_mssql.rb +47 -8
- data/test/visitors/test_to_sql.rb +16 -0
- metadata +61 -50
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 2.1.2 / Unreleased
|
2
|
+
|
3
|
+
* Bug Fixes
|
4
|
+
|
5
|
+
* Visitors can define their own cache strategey so caches are not shared.
|
6
|
+
Fixes #57
|
7
|
+
* Informix support fixed. Thanks Khronos.
|
8
|
+
* Ordering nodes broken to subclasses. Thanks Ernie Miller!
|
9
|
+
* Reversal supported in ordering nodes. Thanks Ernie Miller!
|
10
|
+
|
1
11
|
== 2.1.1 / 2011/05/14
|
2
12
|
|
3
13
|
* Bug fixes
|
data/arel.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{arel}
|
5
|
-
s.version = "2.1.
|
5
|
+
s.version = "2.1.2.20110627094400"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = [
|
9
|
-
s.date = %q{2011-
|
8
|
+
s.authors = [%q{Aaron Patterson}, %q{Bryan Halmkamp}, %q{Emilio Tagua}, %q{Nick Kallen}]
|
9
|
+
s.date = %q{2011-06-27}
|
10
10
|
s.description = %q{Arel is a SQL AST manager for Ruby. It
|
11
11
|
|
12
12
|
1. Simplifies the generation complex of SQL queries
|
@@ -15,29 +15,29 @@ Gem::Specification.new do |s|
|
|
15
15
|
It is intended to be a framework framework; that is, you can build your own ORM
|
16
16
|
with it, focusing on innovative object and collection modeling as opposed to
|
17
17
|
database compatibility and query generation.}
|
18
|
-
s.email = [
|
19
|
-
s.extra_rdoc_files = [
|
20
|
-
s.files = [
|
18
|
+
s.email = [%q{aaron@tenderlovemaking.com}, %q{bryan@brynary.com}, %q{miloops@gmail.com}, %q{nick@example.org}]
|
19
|
+
s.extra_rdoc_files = [%q{History.txt}, %q{MIT-LICENSE.txt}, %q{Manifest.txt}, %q{README.markdown}]
|
20
|
+
s.files = [%q{.autotest}, %q{.gemtest}, %q{History.txt}, %q{MIT-LICENSE.txt}, %q{Manifest.txt}, %q{README.markdown}, %q{Rakefile}, %q{arel.gemspec}, %q{lib/arel.rb}, %q{lib/arel/alias_predication.rb}, %q{lib/arel/attributes.rb}, %q{lib/arel/attributes/attribute.rb}, %q{lib/arel/compatibility/wheres.rb}, %q{lib/arel/crud.rb}, %q{lib/arel/delete_manager.rb}, %q{lib/arel/deprecated.rb}, %q{lib/arel/expression.rb}, %q{lib/arel/expressions.rb}, %q{lib/arel/factory_methods.rb}, %q{lib/arel/insert_manager.rb}, %q{lib/arel/math.rb}, %q{lib/arel/nodes.rb}, %q{lib/arel/nodes/and.rb}, %q{lib/arel/nodes/binary.rb}, %q{lib/arel/nodes/count.rb}, %q{lib/arel/nodes/delete_statement.rb}, %q{lib/arel/nodes/equality.rb}, %q{lib/arel/nodes/function.rb}, %q{lib/arel/nodes/in.rb}, %q{lib/arel/nodes/infix_operation.rb}, %q{lib/arel/nodes/inner_join.rb}, %q{lib/arel/nodes/insert_statement.rb}, %q{lib/arel/nodes/join_source.rb}, %q{lib/arel/nodes/named_function.rb}, %q{lib/arel/nodes/node.rb}, %q{lib/arel/nodes/ordering.rb}, %q{lib/arel/nodes/outer_join.rb}, %q{lib/arel/nodes/select_core.rb}, %q{lib/arel/nodes/select_statement.rb}, %q{lib/arel/nodes/sql_literal.rb}, %q{lib/arel/nodes/string_join.rb}, %q{lib/arel/nodes/table_alias.rb}, %q{lib/arel/nodes/terminal.rb}, %q{lib/arel/nodes/unary.rb}, %q{lib/arel/nodes/unqualified_column.rb}, %q{lib/arel/nodes/update_statement.rb}, %q{lib/arel/nodes/values.rb}, %q{lib/arel/nodes/with.rb}, %q{lib/arel/order_predications.rb}, %q{lib/arel/predications.rb}, %q{lib/arel/relation.rb}, %q{lib/arel/select_manager.rb}, %q{lib/arel/sql/engine.rb}, %q{lib/arel/sql_literal.rb}, %q{lib/arel/table.rb}, %q{lib/arel/tree_manager.rb}, %q{lib/arel/update_manager.rb}, %q{lib/arel/visitors.rb}, %q{lib/arel/visitors/depth_first.rb}, %q{lib/arel/visitors/dot.rb}, %q{lib/arel/visitors/ibm_db.rb}, %q{lib/arel/visitors/join_sql.rb}, %q{lib/arel/visitors/mssql.rb}, %q{lib/arel/visitors/mysql.rb}, %q{lib/arel/visitors/oracle.rb}, %q{lib/arel/visitors/order_clauses.rb}, %q{lib/arel/visitors/postgresql.rb}, %q{lib/arel/visitors/sqlite.rb}, %q{lib/arel/visitors/to_sql.rb}, %q{lib/arel/visitors/visitor.rb}, %q{lib/arel/visitors/where_sql.rb}, %q{test/attributes/test_attribute.rb}, %q{test/helper.rb}, %q{test/nodes/test_as.rb}, %q{test/nodes/test_bin.rb}, %q{test/nodes/test_count.rb}, %q{test/nodes/test_delete_statement.rb}, %q{test/nodes/test_equality.rb}, %q{test/nodes/test_insert_statement.rb}, %q{test/nodes/test_named_function.rb}, %q{test/nodes/test_node.rb}, %q{test/nodes/test_not.rb}, %q{test/nodes/test_or.rb}, %q{test/nodes/test_select_core.rb}, %q{test/nodes/test_select_statement.rb}, %q{test/nodes/test_sql_literal.rb}, %q{test/nodes/test_sum.rb}, %q{test/nodes/test_update_statement.rb}, %q{test/support/fake_record.rb}, %q{test/test_activerecord_compat.rb}, %q{test/test_attributes.rb}, %q{test/test_crud.rb}, %q{test/test_delete_manager.rb}, %q{test/test_factory_methods.rb}, %q{test/test_insert_manager.rb}, %q{test/test_select_manager.rb}, %q{test/test_table.rb}, %q{test/test_update_manager.rb}, %q{test/visitors/test_depth_first.rb}, %q{test/visitors/test_dot.rb}, %q{test/visitors/test_ibm_db.rb}, %q{test/visitors/test_join_sql.rb}, %q{test/visitors/test_mssql.rb}, %q{test/visitors/test_mysql.rb}, %q{test/visitors/test_oracle.rb}, %q{test/visitors/test_postgres.rb}, %q{test/visitors/test_sqlite.rb}, %q{test/visitors/test_to_sql.rb}, %q{test/nodes/test_ascending.rb}, %q{test/nodes/test_descending.rb}, %q{test/nodes/test_infix_operation.rb}, %q{test/visitors/test_informix.rb}]
|
21
21
|
s.homepage = %q{http://github.com/rails/arel}
|
22
|
-
s.rdoc_options = [
|
23
|
-
s.require_paths = [
|
22
|
+
s.rdoc_options = [%q{--main}, %q{README.markdown}]
|
23
|
+
s.require_paths = [%q{lib}]
|
24
24
|
s.rubyforge_project = %q{arel}
|
25
|
-
s.rubygems_version = %q{1.
|
25
|
+
s.rubygems_version = %q{1.8.5}
|
26
26
|
s.summary = %q{Arel is a SQL AST manager for Ruby}
|
27
|
-
s.test_files = [
|
27
|
+
s.test_files = [%q{test/attributes/test_attribute.rb}, %q{test/nodes/test_as.rb}, %q{test/nodes/test_ascending.rb}, %q{test/nodes/test_bin.rb}, %q{test/nodes/test_count.rb}, %q{test/nodes/test_delete_statement.rb}, %q{test/nodes/test_descending.rb}, %q{test/nodes/test_equality.rb}, %q{test/nodes/test_infix_operation.rb}, %q{test/nodes/test_insert_statement.rb}, %q{test/nodes/test_named_function.rb}, %q{test/nodes/test_node.rb}, %q{test/nodes/test_not.rb}, %q{test/nodes/test_or.rb}, %q{test/nodes/test_select_core.rb}, %q{test/nodes/test_select_statement.rb}, %q{test/nodes/test_sql_literal.rb}, %q{test/nodes/test_sum.rb}, %q{test/nodes/test_update_statement.rb}, %q{test/test_activerecord_compat.rb}, %q{test/test_attributes.rb}, %q{test/test_crud.rb}, %q{test/test_delete_manager.rb}, %q{test/test_factory_methods.rb}, %q{test/test_insert_manager.rb}, %q{test/test_select_manager.rb}, %q{test/test_table.rb}, %q{test/test_update_manager.rb}, %q{test/visitors/test_depth_first.rb}, %q{test/visitors/test_dot.rb}, %q{test/visitors/test_ibm_db.rb}, %q{test/visitors/test_informix.rb}, %q{test/visitors/test_join_sql.rb}, %q{test/visitors/test_mssql.rb}, %q{test/visitors/test_mysql.rb}, %q{test/visitors/test_oracle.rb}, %q{test/visitors/test_postgres.rb}, %q{test/visitors/test_sqlite.rb}, %q{test/visitors/test_to_sql.rb}]
|
28
28
|
|
29
29
|
if s.respond_to? :specification_version then
|
30
30
|
s.specification_version = 3
|
31
31
|
|
32
32
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
33
|
-
s.add_development_dependency(%q<minitest>, [">= 2.
|
34
|
-
s.add_development_dependency(%q<hoe>, [">= 2.9.
|
33
|
+
s.add_development_dependency(%q<minitest>, [">= 2.2.2"])
|
34
|
+
s.add_development_dependency(%q<hoe>, [">= 2.9.4"])
|
35
35
|
else
|
36
|
-
s.add_dependency(%q<minitest>, [">= 2.
|
37
|
-
s.add_dependency(%q<hoe>, [">= 2.9.
|
36
|
+
s.add_dependency(%q<minitest>, [">= 2.2.2"])
|
37
|
+
s.add_dependency(%q<hoe>, [">= 2.9.4"])
|
38
38
|
end
|
39
39
|
else
|
40
|
-
s.add_dependency(%q<minitest>, [">= 2.
|
41
|
-
s.add_dependency(%q<hoe>, [">= 2.9.
|
40
|
+
s.add_dependency(%q<minitest>, [">= 2.2.2"])
|
41
|
+
s.add_dependency(%q<hoe>, [">= 2.9.4"])
|
42
42
|
end
|
43
43
|
end
|
data/lib/arel.rb
CHANGED
data/lib/arel/nodes.rb
CHANGED
@@ -11,6 +11,8 @@ require 'arel/nodes/terminal'
|
|
11
11
|
|
12
12
|
# unary
|
13
13
|
require 'arel/nodes/unary'
|
14
|
+
require 'arel/nodes/ascending'
|
15
|
+
require 'arel/nodes/descending'
|
14
16
|
require 'arel/nodes/unqualified_column'
|
15
17
|
require 'arel/nodes/with'
|
16
18
|
|
@@ -19,7 +21,6 @@ require 'arel/nodes/binary'
|
|
19
21
|
require 'arel/nodes/equality'
|
20
22
|
require 'arel/nodes/in' # Why is this subclassed from equality?
|
21
23
|
require 'arel/nodes/join_source'
|
22
|
-
require 'arel/nodes/ordering'
|
23
24
|
require 'arel/nodes/delete_statement'
|
24
25
|
require 'arel/nodes/table_alias'
|
25
26
|
require 'arel/nodes/infix_operation'
|
data/lib/arel/nodes/function.rb
CHANGED
data/lib/arel/nodes/ordering.rb
CHANGED
@@ -1,20 +1,6 @@
|
|
1
1
|
module Arel
|
2
2
|
module Nodes
|
3
|
-
class Ordering <
|
4
|
-
alias :expr :left
|
5
|
-
alias :direction :right
|
6
|
-
|
7
|
-
def initialize expr, direction = :asc
|
8
|
-
super
|
9
|
-
end
|
10
|
-
|
11
|
-
def ascending?
|
12
|
-
direction == :asc
|
13
|
-
end
|
14
|
-
|
15
|
-
def descending?
|
16
|
-
direction == :desc
|
17
|
-
end
|
3
|
+
class Ordering < Unary
|
18
4
|
end
|
19
5
|
end
|
20
6
|
end
|
data/lib/arel/nodes/unary.rb
CHANGED
data/lib/arel/visitors.rb
CHANGED
@@ -11,6 +11,7 @@ require 'arel/visitors/where_sql'
|
|
11
11
|
require 'arel/visitors/order_clauses'
|
12
12
|
require 'arel/visitors/dot'
|
13
13
|
require 'arel/visitors/ibm_db'
|
14
|
+
require 'arel/visitors/informix'
|
14
15
|
|
15
16
|
module Arel
|
16
17
|
module Visitors
|
@@ -24,6 +25,7 @@ module Arel
|
|
24
25
|
'sqlite' => Arel::Visitors::SQLite,
|
25
26
|
'sqlite3' => Arel::Visitors::SQLite,
|
26
27
|
'ibm_db' => Arel::Visitors::IBM_DB,
|
28
|
+
'informix' => Arel::Visitors::Informix,
|
27
29
|
}
|
28
30
|
|
29
31
|
ENGINE_VISITORS = Hash.new do |hash, engine|
|
@@ -22,6 +22,7 @@ module Arel
|
|
22
22
|
alias :visit_Arel_Nodes_Not :unary
|
23
23
|
alias :visit_Arel_Nodes_Offset :unary
|
24
24
|
alias :visit_Arel_Nodes_On :unary
|
25
|
+
alias :visit_Arel_Nodes_Ordering :unary
|
25
26
|
alias :visit_Arel_Nodes_Top :unary
|
26
27
|
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
|
27
28
|
|
@@ -75,7 +76,6 @@ module Arel
|
|
75
76
|
alias :visit_Arel_Nodes_NotEqual :binary
|
76
77
|
alias :visit_Arel_Nodes_NotIn :binary
|
77
78
|
alias :visit_Arel_Nodes_Or :binary
|
78
|
-
alias :visit_Arel_Nodes_Ordering :binary
|
79
79
|
alias :visit_Arel_Nodes_OuterJoin :binary
|
80
80
|
alias :visit_Arel_Nodes_TableAlias :binary
|
81
81
|
alias :visit_Arel_Nodes_Values :binary
|
data/lib/arel/visitors/dot.rb
CHANGED
data/lib/arel/visitors/mssql.rb
CHANGED
@@ -3,21 +3,71 @@ module Arel
|
|
3
3
|
class MSSQL < Arel::Visitors::ToSql
|
4
4
|
private
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
# `top` wouldn't really work here. I.e. User.select("distinct first_name").limit(10) would generate
|
7
|
+
# "select top 10 distinct first_name from users", which is invalid query! it should be
|
8
|
+
# "select distinct top 10 first_name from users"
|
9
|
+
def visit_Arel_Nodes_Top o
|
10
|
+
""
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
13
|
+
def visit_Arel_Nodes_SelectStatement o
|
14
|
+
if !o.limit && !o.offset
|
15
|
+
return super o
|
16
|
+
end
|
17
|
+
|
18
|
+
select_order_by = "ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?
|
19
|
+
|
20
|
+
is_select_count = false
|
21
|
+
sql = o.cores.map { |x|
|
22
|
+
core_order_by = select_order_by || determine_order_by(x)
|
23
|
+
if select_count? x
|
24
|
+
x.projections = [row_num_literal(core_order_by)]
|
25
|
+
is_select_count = true
|
26
|
+
else
|
27
|
+
x.projections << row_num_literal(core_order_by)
|
28
|
+
end
|
29
|
+
|
30
|
+
visit_Arel_Nodes_SelectCore x
|
31
|
+
}.join
|
32
|
+
|
33
|
+
sql = "SELECT _t.* FROM (#{sql}) as _t WHERE #{get_offset_limit_clause(o)}"
|
34
|
+
# fixme count distinct wouldn't work with limit or offset
|
35
|
+
sql = "SELECT COUNT(1) as count_id FROM (#{sql}) AS subquery" if is_select_count
|
36
|
+
sql
|
15
37
|
end
|
16
38
|
|
17
|
-
def
|
18
|
-
|
39
|
+
def get_offset_limit_clause o
|
40
|
+
first_row = o.offset ? o.offset.expr.to_i + 1 : 1
|
41
|
+
last_row = o.limit ? o.limit.expr.to_i - 1 + first_row : nil
|
42
|
+
if last_row
|
43
|
+
" _row_num BETWEEN #{first_row} AND #{last_row}"
|
44
|
+
else
|
45
|
+
" _row_num >= #{first_row}"
|
46
|
+
end
|
19
47
|
end
|
20
48
|
|
49
|
+
def determine_order_by x
|
50
|
+
unless x.groups.empty?
|
51
|
+
"ORDER BY #{x.groups.map { |g| visit g }.join ', ' }"
|
52
|
+
else
|
53
|
+
"ORDER BY #{find_left_table_pk(x.froms)}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def row_num_literal order_by
|
58
|
+
Nodes::SqlLiteral.new("ROW_NUMBER() OVER (#{order_by}) as _row_num")
|
59
|
+
end
|
60
|
+
|
61
|
+
def select_count? x
|
62
|
+
x.projections.length == 1 && Arel::Nodes::Count === x.projections.first
|
63
|
+
end
|
64
|
+
|
65
|
+
# fixme raise exception of there is no pk?
|
66
|
+
# fixme!! Table.primary_key will be depricated. What is the replacement??
|
67
|
+
def find_left_table_pk o
|
68
|
+
return visit o.primary_key if o.instance_of? Arel::Table
|
69
|
+
find_left_table_pk o.left if o.kind_of? Arel::Nodes::Join
|
70
|
+
end
|
21
71
|
end
|
22
72
|
end
|
23
73
|
end
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -203,8 +203,12 @@ key on UpdateManager using UpdateManager#key=
|
|
203
203
|
"(#{visit o.expr})"
|
204
204
|
end
|
205
205
|
|
206
|
-
def
|
207
|
-
"#{visit o.expr}
|
206
|
+
def visit_Arel_Nodes_Ascending o
|
207
|
+
"#{visit o.expr} ASC"
|
208
|
+
end
|
209
|
+
|
210
|
+
def visit_Arel_Nodes_Descending o
|
211
|
+
"#{visit o.expr} DESC"
|
208
212
|
end
|
209
213
|
|
210
214
|
def visit_Arel_Nodes_Group o
|
@@ -11,15 +11,19 @@ module Arel
|
|
11
11
|
hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}"
|
12
12
|
end
|
13
13
|
|
14
|
+
def dispatch
|
15
|
+
DISPATCH
|
16
|
+
end
|
17
|
+
|
14
18
|
def visit object
|
15
|
-
send
|
19
|
+
send dispatch[object.class], object
|
16
20
|
rescue NoMethodError => e
|
17
|
-
raise e if respond_to?(
|
21
|
+
raise e if respond_to?(dispatch[object.class], true)
|
18
22
|
superklass = object.class.ancestors.find { |klass|
|
19
|
-
respond_to?(
|
23
|
+
respond_to?(dispatch[klass], true)
|
20
24
|
}
|
21
25
|
raise(TypeError, "Cannot visit #{object.class}") unless superklass
|
22
|
-
|
26
|
+
dispatch[object.class] = dispatch[superklass]
|
23
27
|
retry
|
24
28
|
end
|
25
29
|
end
|
@@ -619,9 +619,9 @@ module Arel
|
|
619
619
|
end
|
620
620
|
|
621
621
|
describe '#asc' do
|
622
|
-
it 'should create an
|
622
|
+
it 'should create an Ascending node' do
|
623
623
|
relation = Table.new(:users)
|
624
|
-
relation[:id].asc.must_be_kind_of Nodes::
|
624
|
+
relation[:id].asc.must_be_kind_of Nodes::Ascending
|
625
625
|
end
|
626
626
|
|
627
627
|
it 'should generate ASC in sql' do
|
@@ -635,9 +635,9 @@ module Arel
|
|
635
635
|
end
|
636
636
|
|
637
637
|
describe '#desc' do
|
638
|
-
it 'should create
|
638
|
+
it 'should create a Descending node' do
|
639
639
|
relation = Table.new(:users)
|
640
|
-
relation[:id].desc.must_be_kind_of Nodes::
|
640
|
+
relation[:id].desc.must_be_kind_of Nodes::Descending
|
641
641
|
end
|
642
642
|
|
643
643
|
it 'should generate DESC in sql' do
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Nodes
|
5
|
+
class TestAscending < MiniTest::Unit::TestCase
|
6
|
+
def test_construct
|
7
|
+
ascending = Ascending.new 'zomg'
|
8
|
+
assert_equal 'zomg', ascending.expr
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_reverse
|
12
|
+
ascending = Ascending.new 'zomg'
|
13
|
+
descending = ascending.reverse
|
14
|
+
assert_kind_of Descending, descending
|
15
|
+
assert_equal ascending.expr, descending.expr
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_direction
|
19
|
+
ascending = Ascending.new 'zomg'
|
20
|
+
assert_equal :asc, ascending.direction
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_ascending?
|
24
|
+
ascending = Ascending.new 'zomg'
|
25
|
+
assert ascending.ascending?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_descending?
|
29
|
+
ascending = Ascending.new 'zomg'
|
30
|
+
assert !ascending.descending?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/test/nodes/test_count.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Nodes
|
5
|
+
class TestDescending < MiniTest::Unit::TestCase
|
6
|
+
def test_construct
|
7
|
+
descending = Descending.new 'zomg'
|
8
|
+
assert_equal 'zomg', descending.expr
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_reverse
|
12
|
+
descending = Descending.new 'zomg'
|
13
|
+
ascending = descending.reverse
|
14
|
+
assert_kind_of Ascending, ascending
|
15
|
+
assert_equal descending.expr, ascending.expr
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_direction
|
19
|
+
descending = Descending.new 'zomg'
|
20
|
+
assert_equal :desc, descending.direction
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_ascending?
|
24
|
+
descending = Descending.new 'zomg'
|
25
|
+
assert !descending.ascending?
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_descending?
|
29
|
+
descending = Descending.new 'zomg'
|
30
|
+
assert descending.descending?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -21,9 +21,9 @@ module Arel
|
|
21
21
|
def test_opertaion_ordering
|
22
22
|
operation = InfixOperation.new :+, 1, 2
|
23
23
|
ordering = operation.desc
|
24
|
-
assert_kind_of
|
24
|
+
assert_kind_of Descending, ordering
|
25
25
|
assert_equal operation, ordering.expr
|
26
|
-
|
26
|
+
assert ordering.descending?
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -28,6 +28,7 @@ module Arel
|
|
28
28
|
Arel::Nodes::On,
|
29
29
|
Arel::Nodes::Grouping,
|
30
30
|
Arel::Nodes::Offset,
|
31
|
+
Arel::Nodes::Ordering,
|
31
32
|
Arel::Nodes::Having,
|
32
33
|
Arel::Nodes::StringJoin,
|
33
34
|
Arel::Nodes::UnqualifiedColumn,
|
@@ -104,7 +105,6 @@ module Arel
|
|
104
105
|
Arel::Nodes::Values,
|
105
106
|
Arel::Nodes::As,
|
106
107
|
Arel::Nodes::DeleteStatement,
|
107
|
-
Arel::Nodes::Ordering,
|
108
108
|
Arel::Nodes::JoinSource,
|
109
109
|
].each do |klass|
|
110
110
|
define_method("test_#{klass.name.gsub('::', '_')}") do
|
data/test/visitors/test_dot.rb
CHANGED
@@ -33,6 +33,7 @@ module Arel
|
|
33
33
|
Arel::Nodes::On,
|
34
34
|
Arel::Nodes::Grouping,
|
35
35
|
Arel::Nodes::Offset,
|
36
|
+
Arel::Nodes::Ordering,
|
36
37
|
Arel::Nodes::Having,
|
37
38
|
Arel::Nodes::UnqualifiedColumn,
|
38
39
|
Arel::Nodes::Top,
|
@@ -63,7 +64,6 @@ module Arel
|
|
63
64
|
Arel::Nodes::Values,
|
64
65
|
Arel::Nodes::As,
|
65
66
|
Arel::Nodes::DeleteStatement,
|
66
|
-
Arel::Nodes::Ordering,
|
67
67
|
Arel::Nodes::JoinSource,
|
68
68
|
].each do |klass|
|
69
69
|
define_method("test_#{klass.name.gsub('::', '_')}") do
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
module Arel
|
4
|
+
module Visitors
|
5
|
+
describe 'the informix visitor' do
|
6
|
+
before do
|
7
|
+
@visitor = Informix.new Table.engine
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'uses LIMIT n to limit results' do
|
11
|
+
stmt = Nodes::SelectStatement.new
|
12
|
+
stmt.limit = Nodes::Limit.new(1)
|
13
|
+
sql = @visitor.accept(stmt)
|
14
|
+
sql.must_be_like "SELECT LIMIT 1"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'uses LIMIT n in updates with a limit' do
|
18
|
+
stmt = Nodes::UpdateStatement.new
|
19
|
+
stmt.limit = Nodes::Limit.new(1)
|
20
|
+
stmt.key = 'id'
|
21
|
+
sql = @visitor.accept(stmt)
|
22
|
+
sql.must_be_like "UPDATE NULL WHERE 'id' IN (SELECT LIMIT 1 'id')"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'uses SKIP n to jump results' do
|
26
|
+
stmt = Nodes::SelectStatement.new
|
27
|
+
stmt.offset = Nodes::Offset.new(10)
|
28
|
+
sql = @visitor.accept(stmt)
|
29
|
+
sql.must_be_like "SELECT SKIP 10"
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'uses SKIP before LIMIT' do
|
33
|
+
stmt = Nodes::SelectStatement.new
|
34
|
+
stmt.limit = Nodes::Limit.new(1)
|
35
|
+
stmt.offset = Nodes::Offset.new(1)
|
36
|
+
sql = @visitor.accept(stmt)
|
37
|
+
sql.must_be_like "SELECT SKIP 1 LIMIT 1"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/visitors/test_mssql.rb
CHANGED
@@ -5,21 +5,60 @@ module Arel
|
|
5
5
|
describe 'the mssql visitor' do
|
6
6
|
before do
|
7
7
|
@visitor = MSSQL.new Table.engine
|
8
|
+
@table = Arel::Table.new "users"
|
8
9
|
end
|
9
10
|
|
10
|
-
it '
|
11
|
+
it 'should not modify query if no offset or limit' do
|
11
12
|
stmt = Nodes::SelectStatement.new
|
12
|
-
stmt.cores.last.top = Nodes::Top.new(1)
|
13
13
|
sql = @visitor.accept(stmt)
|
14
|
-
sql.must_be_like "SELECT
|
14
|
+
sql.must_be_like "SELECT"
|
15
15
|
end
|
16
16
|
|
17
|
-
it '
|
18
|
-
stmt = Nodes::
|
19
|
-
stmt.
|
20
|
-
stmt.
|
17
|
+
it 'should go over table PK if no .order() or .group()' do
|
18
|
+
stmt = Nodes::SelectStatement.new
|
19
|
+
stmt.cores.first.from = @table
|
20
|
+
stmt.limit = Nodes::Limit.new(10)
|
21
|
+
sql = @visitor.accept(stmt)
|
22
|
+
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY \"users\".\"id\") as _row_num FROM \"users\" ) as _t WHERE _row_num BETWEEN 1 AND 10"
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should go over query ORDER BY if .order()' do
|
26
|
+
stmt = Nodes::SelectStatement.new
|
27
|
+
stmt.limit = Nodes::Limit.new(10)
|
28
|
+
stmt.orders << Nodes::SqlLiteral.new('order_by')
|
29
|
+
sql = @visitor.accept(stmt)
|
30
|
+
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY order_by) as _row_num) as _t WHERE _row_num BETWEEN 1 AND 10"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should go over query GROUP BY if no .order() and there is .group()' do
|
34
|
+
stmt = Nodes::SelectStatement.new
|
35
|
+
stmt.cores.first.groups << Nodes::SqlLiteral.new('group_by')
|
36
|
+
stmt.limit = Nodes::Limit.new(10)
|
37
|
+
sql = @visitor.accept(stmt)
|
38
|
+
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY group_by) as _row_num GROUP BY group_by) as _t WHERE _row_num BETWEEN 1 AND 10"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should use BETWEEN if both .limit() and .offset' do
|
42
|
+
stmt = Nodes::SelectStatement.new
|
43
|
+
stmt.limit = Nodes::Limit.new(10)
|
44
|
+
stmt.offset = Nodes::Offset.new(20)
|
45
|
+
sql = @visitor.accept(stmt)
|
46
|
+
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num BETWEEN 21 AND 30"
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should use >= if only .offset' do
|
50
|
+
stmt = Nodes::SelectStatement.new
|
51
|
+
stmt.offset = Nodes::Offset.new(20)
|
52
|
+
sql = @visitor.accept(stmt)
|
53
|
+
sql.must_be_like "SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num >= 21"
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should generate subquery for .count' do
|
57
|
+
stmt = Nodes::SelectStatement.new
|
58
|
+
stmt.limit = Nodes::Limit.new(10)
|
59
|
+
stmt.cores.first.projections << Nodes::Count.new('*')
|
21
60
|
sql = @visitor.accept(stmt)
|
22
|
-
sql.must_be_like "
|
61
|
+
sql.must_be_like "SELECT COUNT(1) as count_id FROM (SELECT _t.* FROM (SELECT ROW_NUMBER() OVER (ORDER BY ) as _row_num) as _t WHERE _row_num BETWEEN 1 AND 10) AS subquery"
|
23
62
|
end
|
24
63
|
|
25
64
|
end
|
@@ -13,6 +13,22 @@ module Arel
|
|
13
13
|
@attr = @table[:id]
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'can define a dispatch method' do
|
17
|
+
visited = false
|
18
|
+
viz = Class.new(Arel::Visitors::Visitor) {
|
19
|
+
define_method(:hello) do |node|
|
20
|
+
visited = true
|
21
|
+
end
|
22
|
+
|
23
|
+
def dispatch
|
24
|
+
{ Arel::Table => 'hello' }
|
25
|
+
end
|
26
|
+
}.new
|
27
|
+
|
28
|
+
viz.accept(@table)
|
29
|
+
assert visited, 'hello method was called'
|
30
|
+
end
|
31
|
+
|
16
32
|
it "should be thread safe around usage of last_column" do
|
17
33
|
visit_integer_column = Thread.new do
|
18
34
|
Thread.stop
|
metadata
CHANGED
@@ -1,10 +1,15 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 2
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 2.1.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Aaron Patterson
|
9
14
|
- Bryan Halmkamp
|
10
15
|
- Emilio Tagua
|
@@ -12,56 +17,48 @@ authors:
|
|
12
17
|
autorequire:
|
13
18
|
bindir: bin
|
14
19
|
cert_chain: []
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
requirement: &2156937040 !ruby/object:Gem::Requirement
|
20
|
-
none: false
|
21
|
-
requirements:
|
22
|
-
- - ! '>='
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: 2.0.2
|
25
|
-
type: :development
|
26
|
-
prerelease: false
|
27
|
-
version_requirements: *2156937040
|
28
|
-
- !ruby/object:Gem::Dependency
|
20
|
+
|
21
|
+
date: 2011-06-27 00:00:00 Z
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
29
24
|
name: hoe
|
30
|
-
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
31
27
|
none: false
|
32
|
-
requirements:
|
33
|
-
- -
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 17
|
32
|
+
segments:
|
33
|
+
- 2
|
34
|
+
- 9
|
35
|
+
version: "2.9"
|
36
36
|
type: :development
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
version_requirements: *id001
|
38
|
+
description: |-
|
39
|
+
Arel is a SQL AST manager for Ruby. It
|
40
|
+
|
42
41
|
1. Simplifies the generation complex of SQL queries
|
43
|
-
|
44
42
|
2. Adapts to various RDBMS systems
|
45
|
-
|
46
|
-
|
43
|
+
|
47
44
|
It is intended to be a framework framework; that is, you can build your own ORM
|
48
|
-
|
49
45
|
with it, focusing on innovative object and collection modeling as opposed to
|
50
|
-
|
51
|
-
|
52
|
-
email:
|
46
|
+
database compatibility and query generation.
|
47
|
+
email:
|
53
48
|
- aaron@tenderlovemaking.com
|
54
49
|
- bryan@brynary.com
|
55
50
|
- miloops@gmail.com
|
56
51
|
- nick@example.org
|
57
52
|
executables: []
|
53
|
+
|
58
54
|
extensions: []
|
59
|
-
|
55
|
+
|
56
|
+
extra_rdoc_files:
|
60
57
|
- History.txt
|
61
58
|
- MIT-LICENSE.txt
|
62
59
|
- Manifest.txt
|
63
60
|
- README.markdown
|
64
|
-
files:
|
61
|
+
files:
|
65
62
|
- .autotest
|
66
63
|
- .gemtest
|
67
64
|
- History.txt
|
@@ -170,39 +167,52 @@ files:
|
|
170
167
|
- test/visitors/test_postgres.rb
|
171
168
|
- test/visitors/test_sqlite.rb
|
172
169
|
- test/visitors/test_to_sql.rb
|
170
|
+
- test/nodes/test_ascending.rb
|
171
|
+
- test/nodes/test_descending.rb
|
173
172
|
- test/nodes/test_infix_operation.rb
|
173
|
+
- test/visitors/test_informix.rb
|
174
174
|
homepage: http://github.com/rails/arel
|
175
175
|
licenses: []
|
176
|
+
|
176
177
|
post_install_message:
|
177
|
-
rdoc_options:
|
178
|
+
rdoc_options:
|
178
179
|
- --main
|
179
180
|
- README.markdown
|
180
|
-
require_paths:
|
181
|
+
require_paths:
|
181
182
|
- lib
|
182
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
183
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
183
184
|
none: false
|
184
|
-
requirements:
|
185
|
-
- -
|
186
|
-
- !ruby/object:Gem::Version
|
187
|
-
|
188
|
-
|
185
|
+
requirements:
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
hash: 3
|
189
|
+
segments:
|
190
|
+
- 0
|
191
|
+
version: "0"
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
193
|
none: false
|
190
|
-
requirements:
|
191
|
-
- -
|
192
|
-
- !ruby/object:Gem::Version
|
193
|
-
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
hash: 3
|
198
|
+
segments:
|
199
|
+
- 0
|
200
|
+
version: "0"
|
194
201
|
requirements: []
|
202
|
+
|
195
203
|
rubyforge_project: arel
|
196
204
|
rubygems_version: 1.8.2
|
197
205
|
signing_key:
|
198
206
|
specification_version: 3
|
199
207
|
summary: Arel is a SQL AST manager for Ruby
|
200
|
-
test_files:
|
208
|
+
test_files:
|
201
209
|
- test/attributes/test_attribute.rb
|
202
210
|
- test/nodes/test_as.rb
|
211
|
+
- test/nodes/test_ascending.rb
|
203
212
|
- test/nodes/test_bin.rb
|
204
213
|
- test/nodes/test_count.rb
|
205
214
|
- test/nodes/test_delete_statement.rb
|
215
|
+
- test/nodes/test_descending.rb
|
206
216
|
- test/nodes/test_equality.rb
|
207
217
|
- test/nodes/test_infix_operation.rb
|
208
218
|
- test/nodes/test_insert_statement.rb
|
@@ -227,6 +237,7 @@ test_files:
|
|
227
237
|
- test/visitors/test_depth_first.rb
|
228
238
|
- test/visitors/test_dot.rb
|
229
239
|
- test/visitors/test_ibm_db.rb
|
240
|
+
- test/visitors/test_informix.rb
|
230
241
|
- test/visitors/test_join_sql.rb
|
231
242
|
- test/visitors/test_mssql.rb
|
232
243
|
- test/visitors/test_mysql.rb
|