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.
@@ -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
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{arel}
5
- s.version = "2.1.0.20110430172428"
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 = ["Aaron Patterson", "Bryan Halmkamp", "Emilio Tagua", "Nick Kallen"]
9
- s.date = %q{2011-04-30}
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 = ["aaron@tenderlovemaking.com", "bryan@brynary.com", "miloops@gmail.com", "nick@example.org"]
19
- s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown"]
20
- s.files = [".autotest", ".gemtest", "History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown", "Rakefile", "arel.gemspec", "lib/arel.rb", "lib/arel/alias_predication.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/factory_methods.rb", "lib/arel/insert_manager.rb", "lib/arel/math.rb", "lib/arel/nodes.rb", "lib/arel/nodes/and.rb", "lib/arel/nodes/binary.rb", "lib/arel/nodes/count.rb", "lib/arel/nodes/delete_statement.rb", "lib/arel/nodes/equality.rb", "lib/arel/nodes/function.rb", "lib/arel/nodes/in.rb", "lib/arel/nodes/infix_operation.rb", "lib/arel/nodes/inner_join.rb", "lib/arel/nodes/insert_statement.rb", "lib/arel/nodes/join_source.rb", "lib/arel/nodes/named_function.rb", "lib/arel/nodes/node.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/table_alias.rb", "lib/arel/nodes/terminal.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/nodes/with.rb", "lib/arel/order_predications.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/ibm_db.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_bin.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_named_function.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_factory_methods.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_ibm_db.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"]
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 = ["--main", "README.markdown"]
23
- s.require_paths = ["lib"]
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.6.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 = ["test/attributes/test_attribute.rb", "test/nodes/test_as.rb", "test/nodes/test_bin.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_named_function.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_factory_methods.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_ibm_db.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"]
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.0.2"])
34
- s.add_development_dependency(%q<hoe>, [">= 2.9.1"])
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.0.2"])
37
- s.add_dependency(%q<hoe>, [">= 2.9.1"])
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.0.2"])
41
- s.add_dependency(%q<hoe>, [">= 2.9.1"])
40
+ s.add_dependency(%q<minitest>, [">= 2.2.2"])
41
+ s.add_dependency(%q<hoe>, [">= 2.9.4"])
42
42
  end
43
43
  end
@@ -33,7 +33,7 @@ require 'arel/sql_literal'
33
33
  ####
34
34
 
35
35
  module Arel
36
- VERSION = '2.1.1'
36
+ VERSION = '2.1.2'
37
37
 
38
38
  def self.sql raw_sql
39
39
  Arel::Nodes::SqlLiteral.new raw_sql
@@ -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'
@@ -2,6 +2,7 @@ module Arel
2
2
  module Nodes
3
3
  class Function < Arel::Nodes::Node
4
4
  include Arel::Expression
5
+ include Arel::Predications
5
6
  attr_accessor :expressions, :alias, :distinct
6
7
 
7
8
  def initialize expr, aliaz = nil
@@ -3,8 +3,6 @@ module Arel
3
3
  class NamedFunction < Arel::Nodes::Function
4
4
  attr_accessor :name
5
5
 
6
- include Arel::Predications
7
-
8
6
  def initialize name, expr, aliaz = nil
9
7
  super(expr, aliaz)
10
8
  @name = name
@@ -1,20 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Ordering < Arel::Nodes::Binary
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
@@ -18,6 +18,7 @@ module Arel
18
18
  Not
19
19
  Offset
20
20
  On
21
+ Ordering
21
22
  Top
22
23
  Lock
23
24
  DistinctOn
@@ -2,11 +2,11 @@ module Arel
2
2
  module OrderPredications
3
3
 
4
4
  def asc
5
- Nodes::Ordering.new self, :asc
5
+ Nodes::Ascending.new self
6
6
  end
7
7
 
8
8
  def desc
9
- Nodes::Ordering.new self, :desc
9
+ Nodes::Descending.new self
10
10
  end
11
11
 
12
12
  end
@@ -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
@@ -30,7 +30,6 @@ module Arel
30
30
  private
31
31
  def visit_Arel_Nodes_Ordering o
32
32
  visit_edge o, "expr"
33
- visit_edge o, "direction"
34
33
  end
35
34
 
36
35
  def visit_Arel_Nodes_TableAlias o
@@ -3,21 +3,71 @@ module Arel
3
3
  class MSSQL < Arel::Visitors::ToSql
4
4
  private
5
5
 
6
- def build_subselect key, o
7
- stmt = super
8
- core = stmt.cores.first
9
- core.top = Nodes::Top.new(o.limit.expr) if o.limit
10
- stmt
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 visit_Arel_Nodes_Limit o
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 visit_Arel_Nodes_Top o
18
- "TOP #{visit o.expr}"
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
@@ -203,8 +203,12 @@ key on UpdateManager using UpdateManager#key=
203
203
  "(#{visit o.expr})"
204
204
  end
205
205
 
206
- def visit_Arel_Nodes_Ordering o
207
- "#{visit o.expr} #{o.descending? ? 'DESC' : 'ASC'}"
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 DISPATCH[object.class], object
19
+ send dispatch[object.class], object
16
20
  rescue NoMethodError => e
17
- raise e if respond_to?(DISPATCH[object.class], true)
21
+ raise e if respond_to?(dispatch[object.class], true)
18
22
  superklass = object.class.ancestors.find { |klass|
19
- respond_to?(DISPATCH[klass], true)
23
+ respond_to?(dispatch[klass], true)
20
24
  }
21
25
  raise(TypeError, "Cannot visit #{object.class}") unless superklass
22
- DISPATCH[object.class] = DISPATCH[superklass]
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 Ordering node' do
622
+ it 'should create an Ascending node' do
623
623
  relation = Table.new(:users)
624
- relation[:id].asc.must_be_kind_of Nodes::Ordering
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 an Ordering node' do
638
+ it 'should create a Descending node' do
639
639
  relation = Table.new(:users)
640
- relation[:id].desc.must_be_kind_of Nodes::Ordering
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
@@ -15,4 +15,13 @@ describe Arel::Nodes::Count do
15
15
  }
16
16
  end
17
17
  end
18
+
19
+ describe "eq" do
20
+ it "should compare the count" do
21
+ table = Arel::Table.new :users
22
+ table[:id].count.eq(2).to_sql.must_be_like %{
23
+ COUNT("users"."id") = 2
24
+ }
25
+ end
26
+ end
18
27
  end
@@ -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 Ordering, ordering
24
+ assert_kind_of Descending, ordering
25
25
  assert_equal operation, ordering.expr
26
- assert_equal :desc, ordering.direction
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
@@ -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
@@ -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 'uses TOP to limit results' do
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 TOP 1"
14
+ sql.must_be_like "SELECT"
15
15
  end
16
16
 
17
- it 'uses TOP in updates with a limit' do
18
- stmt = Nodes::UpdateStatement.new
19
- stmt.limit = Nodes::Limit.new(1)
20
- stmt.key = 'id'
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 "UPDATE NULL WHERE 'id' IN (SELECT TOP 1 'id' )"
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
- version: 2.1.1
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
- date: 2011-05-17 00:00:00.000000000 Z
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
18
- name: minitest
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
- requirement: &2156936540 !ruby/object:Gem::Requirement
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
31
27
  none: false
32
- requirements:
33
- - - ! '>='
34
- - !ruby/object:Gem::Version
35
- version: 2.9.1
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
- prerelease: false
38
- version_requirements: *2156936540
39
- description: ! 'Arel is a SQL AST manager for Ruby. It
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
- database compatibility and query generation.'
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
- extra_rdoc_files:
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
- version: '0'
188
- required_rubygems_version: !ruby/object:Gem::Requirement
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
- version: '0'
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