arel 2.1.1 → 2.1.2
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/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
|