arel 2.0.6 → 2.0.7.beta.20110110114925

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ == 2.0.7 (unreleased)
2
+
3
+ * Bug Fixes
4
+
5
+ * Limit members are visited
6
+ * Fixing MSSQL TOP support
7
+
1
8
  == 2.0.6 12/01/2010
2
9
 
3
10
  * Bug Fixes
@@ -39,6 +39,7 @@ lib/arel/nodes/insert_statement.rb
39
39
  lib/arel/nodes/join.rb
40
40
  lib/arel/nodes/less_than.rb
41
41
  lib/arel/nodes/less_than_or_equal.rb
42
+ lib/arel/nodes/limit.rb
42
43
  lib/arel/nodes/lock.rb
43
44
  lib/arel/nodes/matches.rb
44
45
  lib/arel/nodes/max.rb
@@ -58,6 +59,7 @@ lib/arel/nodes/sql_literal.rb
58
59
  lib/arel/nodes/string_join.rb
59
60
  lib/arel/nodes/sum.rb
60
61
  lib/arel/nodes/table_alias.rb
62
+ lib/arel/nodes/top.rb
61
63
  lib/arel/nodes/unary.rb
62
64
  lib/arel/nodes/unqualified_column.rb
63
65
  lib/arel/nodes/update_statement.rb
@@ -74,6 +76,7 @@ lib/arel/visitors.rb
74
76
  lib/arel/visitors/depth_first.rb
75
77
  lib/arel/visitors/dot.rb
76
78
  lib/arel/visitors/join_sql.rb
79
+ lib/arel/visitors/mssql.rb
77
80
  lib/arel/visitors/mysql.rb
78
81
  lib/arel/visitors/oracle.rb
79
82
  lib/arel/visitors/order_clauses.rb
@@ -107,7 +110,9 @@ test/test_select_manager.rb
107
110
  test/test_table.rb
108
111
  test/test_update_manager.rb
109
112
  test/visitors/test_depth_first.rb
113
+ test/visitors/test_dot.rb
110
114
  test/visitors/test_join_sql.rb
115
+ test/visitors/test_mssql.rb
111
116
  test/visitors/test_mysql.rb
112
117
  test/visitors/test_oracle.rb
113
118
  test/visitors/test_postgres.rb
@@ -2,22 +2,22 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{arel}
5
- s.version = "2.0.5.20101130111154"
5
+ s.version = "2.0.7.beta.20110110114925"
6
6
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
7
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Aaron Patterson", "Bryan Halmkamp", "Emilio Tagua", "Nick Kallen"]
9
- s.date = %q{2010-11-30}
9
+ s.date = %q{2011-01-10}
10
10
  s.description = %q{Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex of SQL queries and it 2) adapts to various RDBMS systems. It is intended to be a framework framework; that is, you can build your own ORM with it, focusing on innovative object and collection modeling as opposed to database compatibility and query generation.}
11
11
  s.email = ["aaron@tenderlovemaking.com", "bryan@brynary.com", "miloops@gmail.com", "nick@example.org"]
12
12
  s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown"]
13
- s.files = [".autotest", "History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown", "Rakefile", "arel.gemspec", "lib/arel.rb", "lib/arel/attributes.rb", "lib/arel/attributes/attribute.rb", "lib/arel/compatibility/wheres.rb", "lib/arel/crud.rb", "lib/arel/delete_manager.rb", "lib/arel/deprecated.rb", "lib/arel/expression.rb", "lib/arel/expressions.rb", "lib/arel/insert_manager.rb", "lib/arel/nodes.rb", "lib/arel/nodes/and.rb", "lib/arel/nodes/as.rb", "lib/arel/nodes/assignment.rb", "lib/arel/nodes/avg.rb", "lib/arel/nodes/between.rb", "lib/arel/nodes/binary.rb", "lib/arel/nodes/count.rb", "lib/arel/nodes/delete_statement.rb", "lib/arel/nodes/does_not_match.rb", "lib/arel/nodes/equality.rb", "lib/arel/nodes/exists.rb", "lib/arel/nodes/function.rb", "lib/arel/nodes/greater_than.rb", "lib/arel/nodes/greater_than_or_equal.rb", "lib/arel/nodes/group.rb", "lib/arel/nodes/grouping.rb", "lib/arel/nodes/having.rb", "lib/arel/nodes/in.rb", "lib/arel/nodes/inner_join.rb", "lib/arel/nodes/insert_statement.rb", "lib/arel/nodes/join.rb", "lib/arel/nodes/less_than.rb", "lib/arel/nodes/less_than_or_equal.rb", "lib/arel/nodes/lock.rb", "lib/arel/nodes/matches.rb", "lib/arel/nodes/max.rb", "lib/arel/nodes/min.rb", "lib/arel/nodes/node.rb", "lib/arel/nodes/not.rb", "lib/arel/nodes/not_equal.rb", "lib/arel/nodes/not_in.rb", "lib/arel/nodes/offset.rb", "lib/arel/nodes/on.rb", "lib/arel/nodes/or.rb", "lib/arel/nodes/ordering.rb", "lib/arel/nodes/outer_join.rb", "lib/arel/nodes/select_core.rb", "lib/arel/nodes/select_statement.rb", "lib/arel/nodes/sql_literal.rb", "lib/arel/nodes/string_join.rb", "lib/arel/nodes/sum.rb", "lib/arel/nodes/table_alias.rb", "lib/arel/nodes/unary.rb", "lib/arel/nodes/unqualified_column.rb", "lib/arel/nodes/update_statement.rb", "lib/arel/nodes/values.rb", "lib/arel/predications.rb", "lib/arel/relation.rb", "lib/arel/select_manager.rb", "lib/arel/sql/engine.rb", "lib/arel/sql_literal.rb", "lib/arel/table.rb", "lib/arel/tree_manager.rb", "lib/arel/update_manager.rb", "lib/arel/visitors.rb", "lib/arel/visitors/depth_first.rb", "lib/arel/visitors/dot.rb", "lib/arel/visitors/join_sql.rb", "lib/arel/visitors/mysql.rb", "lib/arel/visitors/oracle.rb", "lib/arel/visitors/order_clauses.rb", "lib/arel/visitors/postgresql.rb", "lib/arel/visitors/sqlite.rb", "lib/arel/visitors/to_sql.rb", "lib/arel/visitors/visitor.rb", "lib/arel/visitors/where_sql.rb", "test/attributes/test_attribute.rb", "test/helper.rb", "test/nodes/test_as.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_equality.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/support/fake_record.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
13
+ s.files = [".autotest", "History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown", "Rakefile", "arel.gemspec", "lib/arel.rb", "lib/arel/attributes.rb", "lib/arel/attributes/attribute.rb", "lib/arel/compatibility/wheres.rb", "lib/arel/crud.rb", "lib/arel/delete_manager.rb", "lib/arel/deprecated.rb", "lib/arel/expression.rb", "lib/arel/expressions.rb", "lib/arel/insert_manager.rb", "lib/arel/nodes.rb", "lib/arel/nodes/and.rb", "lib/arel/nodes/as.rb", "lib/arel/nodes/assignment.rb", "lib/arel/nodes/avg.rb", "lib/arel/nodes/between.rb", "lib/arel/nodes/binary.rb", "lib/arel/nodes/count.rb", "lib/arel/nodes/delete_statement.rb", "lib/arel/nodes/does_not_match.rb", "lib/arel/nodes/equality.rb", "lib/arel/nodes/exists.rb", "lib/arel/nodes/function.rb", "lib/arel/nodes/greater_than.rb", "lib/arel/nodes/greater_than_or_equal.rb", "lib/arel/nodes/group.rb", "lib/arel/nodes/grouping.rb", "lib/arel/nodes/having.rb", "lib/arel/nodes/in.rb", "lib/arel/nodes/inner_join.rb", "lib/arel/nodes/insert_statement.rb", "lib/arel/nodes/join.rb", "lib/arel/nodes/less_than.rb", "lib/arel/nodes/less_than_or_equal.rb", "lib/arel/nodes/limit.rb", "lib/arel/nodes/lock.rb", "lib/arel/nodes/matches.rb", "lib/arel/nodes/max.rb", "lib/arel/nodes/min.rb", "lib/arel/nodes/node.rb", "lib/arel/nodes/not.rb", "lib/arel/nodes/not_equal.rb", "lib/arel/nodes/not_in.rb", "lib/arel/nodes/offset.rb", "lib/arel/nodes/on.rb", "lib/arel/nodes/or.rb", "lib/arel/nodes/ordering.rb", "lib/arel/nodes/outer_join.rb", "lib/arel/nodes/select_core.rb", "lib/arel/nodes/select_statement.rb", "lib/arel/nodes/sql_literal.rb", "lib/arel/nodes/string_join.rb", "lib/arel/nodes/sum.rb", "lib/arel/nodes/table_alias.rb", "lib/arel/nodes/top.rb", "lib/arel/nodes/unary.rb", "lib/arel/nodes/unqualified_column.rb", "lib/arel/nodes/update_statement.rb", "lib/arel/nodes/values.rb", "lib/arel/predications.rb", "lib/arel/relation.rb", "lib/arel/select_manager.rb", "lib/arel/sql/engine.rb", "lib/arel/sql_literal.rb", "lib/arel/table.rb", "lib/arel/tree_manager.rb", "lib/arel/update_manager.rb", "lib/arel/visitors.rb", "lib/arel/visitors/depth_first.rb", "lib/arel/visitors/dot.rb", "lib/arel/visitors/join_sql.rb", "lib/arel/visitors/mssql.rb", "lib/arel/visitors/mysql.rb", "lib/arel/visitors/oracle.rb", "lib/arel/visitors/order_clauses.rb", "lib/arel/visitors/postgresql.rb", "lib/arel/visitors/sqlite.rb", "lib/arel/visitors/to_sql.rb", "lib/arel/visitors/visitor.rb", "lib/arel/visitors/where_sql.rb", "test/attributes/test_attribute.rb", "test/helper.rb", "test/nodes/test_as.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_equality.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/support/fake_record.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
14
14
  s.homepage = %q{http://github.com/rails/arel}
15
15
  s.rdoc_options = ["--main", "README.markdown"]
16
16
  s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{arel}
18
18
  s.rubygems_version = %q{1.3.7}
19
19
  s.summary = %q{Arel is a Relational Algebra for Ruby}
20
- s.test_files = ["test/attributes/test_attribute.rb", "test/nodes/test_as.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_equality.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
20
+ s.test_files = ["test/attributes/test_attribute.rb", "test/nodes/test_as.rb", "test/nodes/test_count.rb", "test/nodes/test_delete_statement.rb", "test/nodes/test_equality.rb", "test/nodes/test_insert_statement.rb", "test/nodes/test_node.rb", "test/nodes/test_not.rb", "test/nodes/test_or.rb", "test/nodes/test_select_core.rb", "test/nodes/test_select_statement.rb", "test/nodes/test_sql_literal.rb", "test/nodes/test_sum.rb", "test/nodes/test_update_statement.rb", "test/test_activerecord_compat.rb", "test/test_attributes.rb", "test/test_crud.rb", "test/test_delete_manager.rb", "test/test_insert_manager.rb", "test/test_select_manager.rb", "test/test_table.rb", "test/test_update_manager.rb", "test/visitors/test_depth_first.rb", "test/visitors/test_dot.rb", "test/visitors/test_join_sql.rb", "test/visitors/test_mssql.rb", "test/visitors/test_mysql.rb", "test/visitors/test_oracle.rb", "test/visitors/test_postgres.rb", "test/visitors/test_sqlite.rb", "test/visitors/test_to_sql.rb"]
21
21
 
22
22
  if s.respond_to? :specification_version then
23
23
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -27,17 +27,17 @@ Gem::Specification.new do |s|
27
27
  s.add_development_dependency(%q<minitest>, [">= 2.0.0"])
28
28
  s.add_development_dependency(%q<hoe>, [">= 2.1.0"])
29
29
  s.add_development_dependency(%q<minitest>, [">= 1.6.0"])
30
- s.add_development_dependency(%q<hoe>, [">= 2.6.2"])
30
+ s.add_development_dependency(%q<hoe>, [">= 2.8.0"])
31
31
  else
32
32
  s.add_dependency(%q<minitest>, [">= 2.0.0"])
33
33
  s.add_dependency(%q<hoe>, [">= 2.1.0"])
34
34
  s.add_dependency(%q<minitest>, [">= 1.6.0"])
35
- s.add_dependency(%q<hoe>, [">= 2.6.2"])
35
+ s.add_dependency(%q<hoe>, [">= 2.8.0"])
36
36
  end
37
37
  else
38
38
  s.add_dependency(%q<minitest>, [">= 2.0.0"])
39
39
  s.add_dependency(%q<hoe>, [">= 2.1.0"])
40
40
  s.add_dependency(%q<minitest>, [">= 1.6.0"])
41
- s.add_dependency(%q<hoe>, [">= 2.6.2"])
41
+ s.add_dependency(%q<hoe>, [">= 2.8.0"])
42
42
  end
43
43
  end
@@ -29,7 +29,7 @@ require 'arel/sql_literal'
29
29
  ####
30
30
 
31
31
  module Arel
32
- VERSION = '2.0.6'
32
+ VERSION = '2.0.7.beta'
33
33
 
34
34
  def self.sql raw_sql
35
35
  Arel::Nodes::SqlLiteral.new raw_sql
@@ -13,7 +13,7 @@ module Arel
13
13
  end
14
14
  um.table relation
15
15
  um.set values
16
- um.take @ast.limit
16
+ um.take @ast.limit.expr if @ast.limit
17
17
  um.order(*@ast.orders)
18
18
  um.wheres = @ctx.wheres
19
19
 
@@ -3,6 +3,7 @@ module Arel
3
3
  def initialize engine
4
4
  super
5
5
  @ast = Nodes::DeleteStatement.new
6
+ @ctx = @ast
6
7
  end
7
8
 
8
9
  def from relation
@@ -10,11 +11,6 @@ module Arel
10
11
  self
11
12
  end
12
13
 
13
- def where expression
14
- @ast.wheres << expression
15
- self
16
- end
17
-
18
14
  def wheres= list
19
15
  @ast.wheres = list
20
16
  end
@@ -24,6 +24,8 @@ require 'arel/nodes/function'
24
24
  require 'arel/nodes/count'
25
25
  require 'arel/nodes/values'
26
26
  require 'arel/nodes/offset'
27
+ require 'arel/nodes/limit'
28
+ require 'arel/nodes/top'
27
29
  require 'arel/nodes/sum'
28
30
  require 'arel/nodes/exists'
29
31
  require 'arel/nodes/max'
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Nodes
3
+ class Limit < Arel::Nodes::Unary
4
+ end
5
+ end
6
+ end
7
+
@@ -7,7 +7,7 @@ module Arel
7
7
  # Factory method to create a Nodes::Not node that has the recipient of
8
8
  # the caller as a child.
9
9
  def not
10
- Nodes::Not.new self
10
+ Nodes::Not.new Nodes::Grouping.new self
11
11
  end
12
12
 
13
13
  ###
@@ -1,10 +1,11 @@
1
1
  module Arel
2
2
  module Nodes
3
3
  class SelectCore < Arel::Nodes::Node
4
- attr_accessor :froms, :projections, :wheres, :groups
4
+ attr_accessor :top, :froms, :projections, :wheres, :groups
5
5
  attr_accessor :having
6
6
 
7
7
  def initialize
8
+ @top = nil
8
9
  @froms = nil
9
10
  @projections = []
10
11
  @wheres = []
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module Nodes
3
+ class Top < Arel::Nodes::Unary
4
+ end
5
+ end
6
+ end
@@ -31,7 +31,7 @@ module Arel
31
31
  def in other
32
32
  case other
33
33
  when Arel::SelectManager
34
- Nodes::In.new self, other.to_a.map { |x| x.id }
34
+ Arel::Nodes::In.new(self, other.ast)
35
35
  when Range
36
36
  if other.exclude_end?
37
37
  left = Nodes::GreaterThanOrEqual.new(self, other.begin)
@@ -56,7 +56,7 @@ module Arel
56
56
  def not_in other
57
57
  case other
58
58
  when Arel::SelectManager
59
- Nodes::NotIn.new self, other.to_a.map { |x| x.id }
59
+ Arel::Nodes::NotIn.new(self, other.ast)
60
60
  when Range
61
61
  if other.exclude_end?
62
62
  left = Nodes::LessThan.new(self, other.begin)
@@ -10,7 +10,7 @@ module Arel
10
10
  end
11
11
 
12
12
  def taken
13
- @ast.limit
13
+ @ast.limit && @ast.limit.expr
14
14
  end
15
15
 
16
16
  def constraints
@@ -107,11 +107,6 @@ module Arel
107
107
  self
108
108
  end
109
109
 
110
- def where expr
111
- @ctx.wheres << expr
112
- self
113
- end
114
-
115
110
  def order *expr
116
111
  # FIXME: We SHOULD NOT be converting these to SqlLiteral automatically
117
112
  @ast.orders.concat expr.map { |x|
@@ -136,7 +131,8 @@ module Arel
136
131
  end
137
132
 
138
133
  def take limit
139
- @ast.limit = limit
134
+ @ast.limit = Nodes::Limit.new(limit)
135
+ @ctx.top = Nodes::Top.new(limit)
140
136
  self
141
137
  end
142
138
 
@@ -9,6 +9,7 @@ module Arel
9
9
  def initialize engine
10
10
  @engine = engine
11
11
  @visitor = Visitors.visitor_for @engine
12
+ @ctx = nil
12
13
  end
13
14
 
14
15
  def to_dot
@@ -23,5 +24,13 @@ module Arel
23
24
  super
24
25
  @ast = @ast.clone
25
26
  end
27
+
28
+ def where expr
29
+ if Arel::TreeManager === expr
30
+ expr = expr.ast
31
+ end
32
+ @ctx.wheres << expr
33
+ self
34
+ end
26
35
  end
27
36
  end
@@ -3,10 +3,11 @@ module Arel
3
3
  def initialize engine
4
4
  super
5
5
  @ast = Nodes::UpdateStatement.new
6
+ @ctx = @ast
6
7
  end
7
8
 
8
9
  def take limit
9
- @ast.limit = limit
10
+ @ast.limit = Nodes::Limit.new(limit) if limit
10
11
  self
11
12
  end
12
13
 
@@ -4,6 +4,7 @@ require 'arel/visitors/to_sql'
4
4
  require 'arel/visitors/sqlite'
5
5
  require 'arel/visitors/postgresql'
6
6
  require 'arel/visitors/mysql'
7
+ require 'arel/visitors/mssql'
7
8
  require 'arel/visitors/oracle'
8
9
  require 'arel/visitors/join_sql'
9
10
  require 'arel/visitors/where_sql'
@@ -16,6 +17,8 @@ module Arel
16
17
  'postgresql' => Arel::Visitors::PostgreSQL,
17
18
  'mysql' => Arel::Visitors::MySQL,
18
19
  'mysql2' => Arel::Visitors::MySQL,
20
+ 'mssql' => Arel::Visitors::MSSQL,
21
+ 'sqlserver' => Arel::Visitors::MSSQL,
19
22
  'oracle_enhanced' => Arel::Visitors::Oracle,
20
23
  'sqlite' => Arel::Visitors::SQLite,
21
24
  'sqlite3' => Arel::Visitors::SQLite,
@@ -18,9 +18,11 @@ module Arel
18
18
  alias :visit_Arel_Nodes_Group :unary
19
19
  alias :visit_Arel_Nodes_Grouping :unary
20
20
  alias :visit_Arel_Nodes_Having :unary
21
+ alias :visit_Arel_Nodes_Limit :unary
21
22
  alias :visit_Arel_Nodes_Not :unary
22
23
  alias :visit_Arel_Nodes_Offset :unary
23
24
  alias :visit_Arel_Nodes_On :unary
25
+ alias :visit_Arel_Nodes_Top :unary
24
26
  alias :visit_Arel_Nodes_UnqualifiedColumn :unary
25
27
 
26
28
  def function o
@@ -28,10 +28,6 @@ module Arel
28
28
  end
29
29
 
30
30
  private
31
- def visit_Arel_Nodes_Grouping o
32
- visit_edge o, "expr"
33
- end
34
-
35
31
  def visit_Arel_Nodes_Ordering o
36
32
  visit_edge o, "expr"
37
33
  visit_edge o, "direction"
@@ -55,10 +51,6 @@ module Arel
55
51
  visit_edge o, "distinct"
56
52
  end
57
53
 
58
- def visit_Arel_Nodes_On o
59
- visit_edge o, "expr"
60
- end
61
-
62
54
  def visit_Arel_Nodes_Values o
63
55
  visit_edge o, "expressions"
64
56
  end
@@ -80,13 +72,18 @@ module Arel
80
72
  visit_edge o, "wheres"
81
73
  end
82
74
 
83
- def visit_Arel_Nodes_UnqualifiedColumn o
84
- visit_edge o, "attribute"
85
- end
86
-
87
- def visit_Arel_Nodes_Offset o
88
- visit_edge o, "value"
75
+ def unary o
76
+ visit_edge o, "expr"
89
77
  end
78
+ alias :visit_Arel_Nodes_Group :unary
79
+ alias :visit_Arel_Nodes_Grouping :unary
80
+ alias :visit_Arel_Nodes_Having :unary
81
+ alias :visit_Arel_Nodes_Limit :unary
82
+ alias :visit_Arel_Nodes_Not :unary
83
+ alias :visit_Arel_Nodes_Offset :unary
84
+ alias :visit_Arel_Nodes_On :unary
85
+ alias :visit_Arel_Nodes_Top :unary
86
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
90
87
 
91
88
  def visit_Arel_Nodes_InsertStatement o
92
89
  visit_edge o, "relation"
@@ -0,0 +1,16 @@
1
+ module Arel
2
+ module Visitors
3
+ class MSSQL < Arel::Visitors::ToSql
4
+ private
5
+
6
+ def visit_Arel_Nodes_Limit o
7
+ ""
8
+ end
9
+
10
+ def visit_Arel_Nodes_Top o
11
+ "TOP #{visit o.expr}"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -10,7 +10,7 @@ module Arel
10
10
  # :'(
11
11
  # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
12
12
  def visit_Arel_Nodes_SelectStatement o
13
- o.limit = 18446744073709551615 if o.offset && !o.limit
13
+ o.limit = Arel::Nodes::Limit.new(18446744073709551615) if o.offset && !o.limit
14
14
  super
15
15
  end
16
16
 
@@ -25,7 +25,7 @@ module Arel
25
25
  ("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
26
26
  ("WHERE #{o.wheres.map { |x| visit x }.join ' AND '}" unless o.wheres.empty?),
27
27
  ("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
28
- ("LIMIT #{o.limit}" if o.limit),
28
+ (visit(o.limit) if o.limit),
29
29
  ].compact.join ' '
30
30
  end
31
31
 
@@ -10,17 +10,15 @@ module Arel
10
10
  # then can use simple ROWNUM in WHERE clause
11
11
  if o.limit && o.orders.empty? && !o.offset && o.cores.first.projections.first !~ /^DISTINCT /
12
12
  o.cores.last.wheres.push Nodes::LessThanOrEqual.new(
13
- Nodes::SqlLiteral.new('ROWNUM'), o.limit
13
+ Nodes::SqlLiteral.new('ROWNUM'), o.limit.expr
14
14
  )
15
- o.limit = nil
16
15
  return super
17
16
  end
18
17
 
19
18
  if o.limit && o.offset
20
19
  o = o.dup
21
- limit = o.limit.to_i
20
+ limit = o.limit.expr.to_i
22
21
  offset = o.offset
23
- o.limit = nil
24
22
  o.offset = nil
25
23
  sql = super(o)
26
24
  return <<-eosql
@@ -35,9 +33,8 @@ module Arel
35
33
 
36
34
  if o.limit
37
35
  o = o.dup
38
- limit = o.limit
39
- o.limit = nil
40
- return "SELECT * FROM (#{super(o)}) WHERE ROWNUM <= #{limit}"
36
+ limit = o.limit.expr
37
+ return "SELECT * FROM (#{super(o)}) WHERE ROWNUM <= #{visit limit}"
41
38
  end
42
39
 
43
40
  if o.offset
@@ -57,6 +54,9 @@ module Arel
57
54
  super
58
55
  end
59
56
 
57
+ def visit_Arel_Nodes_Limit o
58
+ end
59
+
60
60
  def visit_Arel_Nodes_Offset o
61
61
  "raw_rnum_ > #{visit o.value}"
62
62
  end
@@ -17,7 +17,7 @@ module Arel
17
17
  [
18
18
  "SELECT * FROM (#{sql}) AS id_list",
19
19
  "ORDER BY #{aliased_orders(o.orders).join(', ')}",
20
- ("LIMIT #{o.limit}" if o.limit),
20
+ (visit(o.limit) if o.limit),
21
21
  (visit(o.offset) if o.offset),
22
22
  ].compact.join ' '
23
23
  else
@@ -3,7 +3,7 @@ module Arel
3
3
  class SQLite < Arel::Visitors::ToSql
4
4
  private
5
5
  def visit_Arel_Nodes_SelectStatement o
6
- o.limit = -1 if o.offset && !o.limit
6
+ o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
7
7
  super
8
8
  end
9
9
  end
@@ -76,7 +76,7 @@ module Arel
76
76
  [
77
77
  o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
78
78
  ("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
79
- ("LIMIT #{o.limit}" if o.limit),
79
+ (visit(o.limit) if o.limit),
80
80
  (visit(o.offset) if o.offset),
81
81
  (visit(o.lock) if o.lock),
82
82
  ].compact.join ' '
@@ -84,7 +84,9 @@ module Arel
84
84
 
85
85
  def visit_Arel_Nodes_SelectCore o
86
86
  [
87
- "SELECT #{o.projections.map { |x| visit x }.join ', '}",
87
+ "SELECT",
88
+ (visit(o.top) if o.top),
89
+ "#{o.projections.map { |x| visit x }.join ', '}",
88
90
  ("FROM #{visit o.froms}" if o.froms),
89
91
  ("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
90
92
  ("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
@@ -100,6 +102,15 @@ module Arel
100
102
  "OFFSET #{visit o.expr}"
101
103
  end
102
104
 
105
+ def visit_Arel_Nodes_Limit o
106
+ "LIMIT #{visit o.expr}"
107
+ end
108
+
109
+ # FIXME: this does nothing on most databases, but does on MSSQL
110
+ def visit_Arel_Nodes_Top o
111
+ ""
112
+ end
113
+
103
114
  # FIXME: this does nothing on SQLLite3, but should do things on other
104
115
  # databases.
105
116
  def visit_Arel_Nodes_Lock o
@@ -192,7 +203,7 @@ module Arel
192
203
  end
193
204
 
194
205
  def visit_Arel_Nodes_Not o
195
- "NOT #{visit o.expr}"
206
+ "NOT (#{visit o.expr})"
196
207
  end
197
208
 
198
209
  def visit_Arel_Table o
@@ -204,17 +215,11 @@ module Arel
204
215
  end
205
216
 
206
217
  def visit_Arel_Nodes_In o
207
- right = o.right
208
- "#{visit o.left} IN (#{
209
- right.empty? ? 'NULL' : right.map { |x| visit x }.join(', ')
210
- })"
218
+ "#{visit o.left} IN (#{visit o.right})"
211
219
  end
212
220
 
213
221
  def visit_Arel_Nodes_NotIn o
214
- right = o.right
215
- "#{visit o.left} NOT IN (#{
216
- right.empty? ? 'NULL' : right.map { |x| visit x }.join(', ')
217
- })"
222
+ "#{visit o.left} NOT IN (#{visit o.right})"
218
223
  end
219
224
 
220
225
  def visit_Arel_Nodes_And o
@@ -291,6 +296,10 @@ module Arel
291
296
  alias :visit_ActiveSupport_StringInquirer :visit_String
292
297
  alias :visit_Class :visit_String
293
298
 
299
+ def visit_Array o
300
+ o.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
301
+ end
302
+
294
303
  def quote value, column = nil
295
304
  @connection.quote value, column
296
305
  end
@@ -13,8 +13,8 @@ module Arel
13
13
 
14
14
  def visit object
15
15
  send DISPATCH[object.class], object
16
- rescue NoMethodError
17
- warn "visiting #{object.class} via superclass, this will be removed in arel 2.2.0" if $VERBOSE
16
+ rescue NoMethodError => e
17
+ raise e if respond_to?(DISPATCH[object.class], true)
18
18
  superklass = object.class.ancestors.find { |klass|
19
19
  respond_to?(DISPATCH[klass], true)
20
20
  }
@@ -8,6 +8,15 @@ module Arel
8
8
  end
9
9
  end
10
10
 
11
+ it 'handles limit properly' do
12
+ table = Table.new(:users)
13
+ um = Arel::UpdateManager.new Table.engine
14
+ um.take 10
15
+ um.table table
16
+ um.set [[table[:name], nil]]
17
+ assert_match(/LIMIT 10/, um.to_sql)
18
+ end
19
+
11
20
  describe 'set' do
12
21
  it "updates with null" do
13
22
  table = Table.new(:users)
@@ -30,6 +30,8 @@ module Arel
30
30
  Arel::Nodes::Offset,
31
31
  Arel::Nodes::Having,
32
32
  Arel::Nodes::UnqualifiedColumn,
33
+ Arel::Nodes::Top,
34
+ Arel::Nodes::Limit,
33
35
  ].each do |klass|
34
36
  define_method("test_#{klass.name.gsub('::', '_')}") do
35
37
  op = klass.new(:a)
@@ -0,0 +1,29 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Visitors
5
+ class TestDot < MiniTest::Unit::TestCase
6
+ def setup
7
+ @visitor = Visitors::Dot.new
8
+ end
9
+
10
+ # unary ops
11
+ [
12
+ Arel::Nodes::Not,
13
+ Arel::Nodes::Group,
14
+ Arel::Nodes::On,
15
+ Arel::Nodes::Grouping,
16
+ Arel::Nodes::Offset,
17
+ Arel::Nodes::Having,
18
+ Arel::Nodes::UnqualifiedColumn,
19
+ Arel::Nodes::Top,
20
+ Arel::Nodes::Limit,
21
+ ].each do |klass|
22
+ define_method("test_#{klass.name.gsub('::', '_')}") do
23
+ op = klass.new(:a)
24
+ @visitor.accept op
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Visitors
5
+ describe 'the mssql visitor' do
6
+ before do
7
+ @visitor = MSSQL.new Table.engine
8
+ end
9
+
10
+ it 'uses TOP to limit results' do
11
+ stmt = Nodes::SelectStatement.new
12
+ stmt.cores.last.top = Nodes::Top.new(1)
13
+ sql = @visitor.accept(stmt)
14
+ sql.must_be_like "SELECT TOP 1"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -17,6 +17,12 @@ module Arel
17
17
  sql.must_be_like "SELECT FROM DUAL LIMIT 18446744073709551615 OFFSET 1"
18
18
  end
19
19
 
20
+ it "should escape LIMIT" do
21
+ sc = Arel::Nodes::UpdateStatement.new
22
+ sc.limit = Nodes::Limit.new("omg")
23
+ assert_equal("UPDATE NULL LIMIT 'omg'", @visitor.accept(sc))
24
+ end
25
+
20
26
  it 'uses DUAL for empty from' do
21
27
  stmt = Nodes::SelectStatement.new
22
28
  sql = @visitor.accept(stmt)
@@ -59,7 +59,7 @@ module Arel
59
59
  describe 'limit' do
60
60
  it 'adds a rownum clause' do
61
61
  stmt = Nodes::SelectStatement.new
62
- stmt.limit = 10
62
+ stmt.limit = Nodes::Limit.new(10)
63
63
  sql = @visitor.accept stmt
64
64
  sql.must_be_like %{ SELECT WHERE ROWNUM <= 10 }
65
65
  end
@@ -67,7 +67,7 @@ module Arel
67
67
  it 'is idempotent' do
68
68
  stmt = Nodes::SelectStatement.new
69
69
  stmt.orders << Nodes::SqlLiteral.new('foo')
70
- stmt.limit = 10
70
+ stmt.limit = Nodes::Limit.new(10)
71
71
  sql = @visitor.accept stmt
72
72
  sql2 = @visitor.accept stmt
73
73
  sql.must_equal sql2
@@ -76,7 +76,7 @@ module Arel
76
76
  it 'creates a subquery when there is order_by' do
77
77
  stmt = Nodes::SelectStatement.new
78
78
  stmt.orders << Nodes::SqlLiteral.new('foo')
79
- stmt.limit = 10
79
+ stmt.limit = Nodes::Limit.new(10)
80
80
  sql = @visitor.accept stmt
81
81
  sql.must_be_like %{
82
82
  SELECT * FROM (SELECT ORDER BY foo) WHERE ROWNUM <= 10
@@ -86,7 +86,7 @@ module Arel
86
86
  it 'creates a subquery when there is DISTINCT' do
87
87
  stmt = Nodes::SelectStatement.new
88
88
  stmt.cores.first.projections << Nodes::SqlLiteral.new('DISTINCT id')
89
- stmt.limit = 10
89
+ stmt.limit = Arel::Nodes::Limit.new(10)
90
90
  sql = @visitor.accept stmt
91
91
  sql.must_be_like %{
92
92
  SELECT * FROM (SELECT DISTINCT id) WHERE ROWNUM <= 10
@@ -95,7 +95,7 @@ module Arel
95
95
 
96
96
  it 'creates a different subquery when there is an offset' do
97
97
  stmt = Nodes::SelectStatement.new
98
- stmt.limit = 10
98
+ stmt.limit = Nodes::Limit.new(10)
99
99
  stmt.offset = Nodes::Offset.new(10)
100
100
  sql = @visitor.accept stmt
101
101
  sql.must_be_like %{
@@ -110,7 +110,7 @@ module Arel
110
110
 
111
111
  it 'is idempotent with different subquery' do
112
112
  stmt = Nodes::SelectStatement.new
113
- stmt.limit = 10
113
+ stmt.limit = Nodes::Limit.new(10)
114
114
  stmt.offset = Nodes::Offset.new(10)
115
115
  sql = @visitor.accept stmt
116
116
  sql2 = @visitor.accept stmt
@@ -12,6 +12,16 @@ module Arel
12
12
  FOR UPDATE
13
13
  }
14
14
  end
15
+
16
+ it "should escape LIMIT" do
17
+ sc = Arel::Nodes::SelectStatement.new
18
+ sc.limit = Nodes::Limit.new("omg")
19
+ sc.cores.first.projections << 'DISTINCT ON'
20
+ sc.orders << "xyz"
21
+ sql = @visitor.accept(sc)
22
+ assert_match(/LIMIT 'omg'/, sql)
23
+ assert_equal 1, sql.scan(/LIMIT/).length, 'should have one limit'
24
+ end
15
25
  end
16
26
  end
17
27
  end
@@ -30,6 +30,12 @@ module Arel
30
30
  @visitor.accept(DateTime).must_equal "'DateTime'"
31
31
  end
32
32
 
33
+ it "should escape LIMIT" do
34
+ sc = Arel::Nodes::SelectStatement.new
35
+ sc.limit = Arel::Nodes::Limit.new("omg")
36
+ assert_match(/LIMIT 'omg'/, @visitor.accept(sc))
37
+ end
38
+
33
39
  it "should visit_DateTime" do
34
40
  @visitor.accept DateTime.now
35
41
  end
@@ -40,7 +46,13 @@ module Arel
40
46
 
41
47
  it "should visit_Not" do
42
48
  sql = @visitor.accept Nodes::Not.new(Arel.sql("foo"))
43
- sql.must_be_like "NOT foo"
49
+ sql.must_be_like "NOT (foo)"
50
+ end
51
+
52
+ it "should apply Not to the whole expression" do
53
+ node = Nodes::And.new @attr.eq(10), @attr.eq(11)
54
+ sql = @visitor.accept Nodes::Not.new(node)
55
+ sql.must_be_like %{NOT ("users"."id" = 10 AND "users"."id" = 11)}
44
56
  end
45
57
 
46
58
  it "should visit_As" do
@@ -131,6 +143,15 @@ module Arel
131
143
  }
132
144
  end
133
145
 
146
+ it 'can handle subqueries' do
147
+ table = Table.new(:users)
148
+ subquery = table.project(:id).where(table[:name].eq('Aaron'))
149
+ node = @attr.in subquery
150
+ @visitor.accept(node).must_be_like %{
151
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" = 'Aaron')
152
+ }
153
+ end
154
+
134
155
  it 'uses the same column for escaping values' do
135
156
  @attr = Table.new(:users)[:name]
136
157
  visitor = Class.new(ToSql) do
@@ -177,6 +198,15 @@ module Arel
177
198
  }
178
199
  end
179
200
 
201
+ it 'can handle subqueries' do
202
+ table = Table.new(:users)
203
+ subquery = table.project(:id).where(table[:name].eq('Aaron'))
204
+ node = @attr.not_in subquery
205
+ @visitor.accept(node).must_be_like %{
206
+ "users"."id" NOT IN (SELECT id FROM "users" WHERE "users"."name" = 'Aaron')
207
+ }
208
+ end
209
+
180
210
  it 'uses the same column for escaping values' do
181
211
  @attr = Table.new(:users)[:name]
182
212
  visitor = Class.new(ToSql) do
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 3
5
- prerelease: false
4
+ hash: 40220158689793
5
+ prerelease: true
6
6
  segments:
7
7
  - 2
8
8
  - 0
9
- - 6
10
- version: 2.0.6
9
+ - 7
10
+ - beta
11
+ - 20110110114925
12
+ version: 2.0.7.beta.20110110114925
11
13
  platform: ruby
12
14
  authors:
13
15
  - Aaron Patterson
@@ -18,7 +20,7 @@ autorequire:
18
20
  bindir: bin
19
21
  cert_chain: []
20
22
 
21
- date: 2010-12-01 00:00:00 -08:00
23
+ date: 2011-01-10 00:00:00 -08:00
22
24
  default_executable:
23
25
  dependencies:
24
26
  - !ruby/object:Gem::Dependency
@@ -77,12 +79,12 @@ dependencies:
77
79
  requirements:
78
80
  - - ">="
79
81
  - !ruby/object:Gem::Version
80
- hash: 19
82
+ hash: 47
81
83
  segments:
82
84
  - 2
83
- - 6
84
- - 2
85
- version: 2.6.2
85
+ - 8
86
+ - 0
87
+ version: 2.8.0
86
88
  type: :development
87
89
  version_requirements: *id004
88
90
  description: Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex of SQL queries and it 2) adapts to various RDBMS systems. It is intended to be a framework framework; that is, you can build your own ORM with it, focusing on innovative object and collection modeling as opposed to database compatibility and query generation.
@@ -142,6 +144,7 @@ files:
142
144
  - lib/arel/nodes/join.rb
143
145
  - lib/arel/nodes/less_than.rb
144
146
  - lib/arel/nodes/less_than_or_equal.rb
147
+ - lib/arel/nodes/limit.rb
145
148
  - lib/arel/nodes/lock.rb
146
149
  - lib/arel/nodes/matches.rb
147
150
  - lib/arel/nodes/max.rb
@@ -161,6 +164,7 @@ files:
161
164
  - lib/arel/nodes/string_join.rb
162
165
  - lib/arel/nodes/sum.rb
163
166
  - lib/arel/nodes/table_alias.rb
167
+ - lib/arel/nodes/top.rb
164
168
  - lib/arel/nodes/unary.rb
165
169
  - lib/arel/nodes/unqualified_column.rb
166
170
  - lib/arel/nodes/update_statement.rb
@@ -177,6 +181,7 @@ files:
177
181
  - lib/arel/visitors/depth_first.rb
178
182
  - lib/arel/visitors/dot.rb
179
183
  - lib/arel/visitors/join_sql.rb
184
+ - lib/arel/visitors/mssql.rb
180
185
  - lib/arel/visitors/mysql.rb
181
186
  - lib/arel/visitors/oracle.rb
182
187
  - lib/arel/visitors/order_clauses.rb
@@ -210,7 +215,9 @@ files:
210
215
  - test/test_table.rb
211
216
  - test/test_update_manager.rb
212
217
  - test/visitors/test_depth_first.rb
218
+ - test/visitors/test_dot.rb
213
219
  - test/visitors/test_join_sql.rb
220
+ - test/visitors/test_mssql.rb
214
221
  - test/visitors/test_mysql.rb
215
222
  - test/visitors/test_oracle.rb
216
223
  - test/visitors/test_postgres.rb
@@ -238,12 +245,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
245
  required_rubygems_version: !ruby/object:Gem::Requirement
239
246
  none: false
240
247
  requirements:
241
- - - ">="
248
+ - - ">"
242
249
  - !ruby/object:Gem::Version
243
- hash: 3
250
+ hash: 25
244
251
  segments:
245
- - 0
246
- version: "0"
252
+ - 1
253
+ - 3
254
+ - 1
255
+ version: 1.3.1
247
256
  requirements: []
248
257
 
249
258
  rubyforge_project: arel
@@ -275,7 +284,9 @@ test_files:
275
284
  - test/test_table.rb
276
285
  - test/test_update_manager.rb
277
286
  - test/visitors/test_depth_first.rb
287
+ - test/visitors/test_dot.rb
278
288
  - test/visitors/test_join_sql.rb
289
+ - test/visitors/test_mssql.rb
279
290
  - test/visitors/test_mysql.rb
280
291
  - test/visitors/test_oracle.rb
281
292
  - test/visitors/test_postgres.rb