aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--History.txt36
-rw-r--r--Manifest.txt27
-rw-r--r--arel.gemspec6
-rw-r--r--lib/arel.rb7
-rw-r--r--lib/arel/attributes/attribute.rb2
-rw-r--r--lib/arel/crud.rb47
-rw-r--r--lib/arel/factory_methods.rb25
-rw-r--r--lib/arel/nodes.rb62
-rw-r--r--lib/arel/nodes/and.rb19
-rw-r--r--lib/arel/nodes/as.rb6
-rw-r--r--lib/arel/nodes/assignment.rb6
-rw-r--r--lib/arel/nodes/avg.rb6
-rw-r--r--lib/arel/nodes/between.rb6
-rw-r--r--lib/arel/nodes/binary.rb24
-rw-r--r--lib/arel/nodes/does_not_match.rb6
-rw-r--r--lib/arel/nodes/exists.rb7
-rw-r--r--lib/arel/nodes/function.rb10
-rw-r--r--lib/arel/nodes/greater_than.rb6
-rw-r--r--lib/arel/nodes/greater_than_or_equal.rb6
-rw-r--r--lib/arel/nodes/group.rb6
-rw-r--r--lib/arel/nodes/grouping.rb6
-rw-r--r--lib/arel/nodes/having.rb6
-rw-r--r--lib/arel/nodes/join.rb13
-rw-r--r--lib/arel/nodes/join_source.rb14
-rw-r--r--lib/arel/nodes/less_than.rb6
-rw-r--r--lib/arel/nodes/less_than_or_equal.rb6
-rw-r--r--lib/arel/nodes/limit.rb7
-rw-r--r--lib/arel/nodes/matches.rb6
-rw-r--r--lib/arel/nodes/max.rb6
-rw-r--r--lib/arel/nodes/min.rb6
-rw-r--r--lib/arel/nodes/node.rb5
-rw-r--r--lib/arel/nodes/not.rb6
-rw-r--r--lib/arel/nodes/not_equal.rb6
-rw-r--r--lib/arel/nodes/not_in.rb6
-rw-r--r--lib/arel/nodes/offset.rb7
-rw-r--r--lib/arel/nodes/on.rb6
-rw-r--r--lib/arel/nodes/or.rb6
-rw-r--r--lib/arel/nodes/select_core.rb21
-rw-r--r--lib/arel/nodes/select_statement.rb1
-rw-r--r--lib/arel/nodes/string_join.rb6
-rw-r--r--lib/arel/nodes/sum.rb6
-rw-r--r--lib/arel/nodes/table_alias.rb2
-rw-r--r--lib/arel/nodes/top.rb6
-rw-r--r--lib/arel/nodes/unary.rb14
-rw-r--r--lib/arel/nodes/unqualified_column.rb4
-rw-r--r--lib/arel/nodes/update_statement.rb6
-rw-r--r--lib/arel/predications.rb6
-rw-r--r--lib/arel/select_manager.rb91
-rw-r--r--lib/arel/table.rb46
-rw-r--r--lib/arel/tree_manager.rb1
-rw-r--r--lib/arel/update_manager.rb4
-rw-r--r--lib/arel/visitors/depth_first.rb22
-rw-r--r--lib/arel/visitors/dot.rb44
-rw-r--r--lib/arel/visitors/join_sql.rb25
-rw-r--r--lib/arel/visitors/oracle.rb4
-rw-r--r--lib/arel/visitors/to_sql.rb138
-rw-r--r--test/attributes/test_attribute.rb6
-rw-r--r--test/helper.rb2
-rw-r--r--test/nodes/test_node.rb4
-rw-r--r--test/test_crud.rb18
-rw-r--r--test/test_factory_methods.rb27
-rw-r--r--test/test_select_manager.rb102
-rw-r--r--test/test_table.rb77
-rw-r--r--test/visitors/test_depth_first.rb28
-rw-r--r--test/visitors/test_dot.rb30
-rw-r--r--test/visitors/test_join_sql.rb21
-rw-r--r--test/visitors/test_to_sql.rb23
67 files changed, 724 insertions, 499 deletions
diff --git a/History.txt b/History.txt
index b604fcfc00..d301854236 100644
--- a/History.txt
+++ b/History.txt
@@ -1,3 +1,39 @@
+== 2.1.0 (unreleased)
+
+* Enhancements
+
+ * AST is now Enumerable
+ * AND nodes are now n-ary nodes
+ * SQL Literals may be used as Attribute names
+
+* Deprecations
+
+ * Calls to `insert` are deprecated. Please use `compile_insert` then call
+ `to_sql` on the resulting object and execute that SQL.
+
+ * Calls to `update` are deprecated. Please use `compile_update` then call
+ `to_sql` on the resulting object and execute that SQL.
+
+ * Calls to `delete` are deprecated. Please use `compile_delete` then call
+ `to_sql` on the resulting object and execute that SQL.
+
+ * Arel::Table#joins is deprecated and will be removed in 3.0.0 with no
+ replacement.
+
+ * Arel::Table#columns is deprecated and will be removed in 3.0.0 with no
+ replacement.
+
+ * Arel::Table.table_cache is deprecated and will be removed in 3.0.0 with no
+ replacement.
+
+ * Arel::Nodes::And.new takes a single list instead of left and right.
+
+ * Arel::Table#primary_key is deprecated and will be removed in 3.0.0 with no
+ replacement.
+
+ * Arel::SelectManager#where_clauses is deprecated and will be removed in
+ 3.0.0 with no replacement.
+
== 2.0.7 (unreleased)
* Bug Fixes
diff --git a/Manifest.txt b/Manifest.txt
index 095d3c276e..4b6e08319f 100644
--- a/Manifest.txt
+++ b/Manifest.txt
@@ -14,49 +14,27 @@ 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/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/join_source.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
@@ -102,6 +80,7 @@ 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
diff --git a/arel.gemspec b/arel.gemspec
index 2e52ae4a19..c7ec979042 100644
--- a/arel.gemspec
+++ b/arel.gemspec
@@ -2,11 +2,11 @@
Gem::Specification.new do |s|
s.name = %q{arel}
- s.version = "2.0.5.20101130111154"
+ s.version = "2.0.7.beta.20101201093009"
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
s.authors = ["Aaron Patterson", "Bryan Halmkamp", "Emilio Tagua", "Nick Kallen"]
- s.date = %q{2010-11-30}
+ s.date = %q{2010-12-01}
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.}
s.email = ["aaron@tenderlovemaking.com", "bryan@brynary.com", "miloops@gmail.com", "nick@example.org"]
s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown"]
diff --git a/lib/arel.rb b/lib/arel.rb
index 6c9f51d03a..32fc8d9bc0 100644
--- a/lib/arel.rb
+++ b/lib/arel.rb
@@ -1,4 +1,5 @@
require 'arel/crud'
+require 'arel/factory_methods'
require 'arel/expressions'
require 'arel/predications'
@@ -29,11 +30,15 @@ require 'arel/sql_literal'
####
module Arel
- VERSION = '2.0.6'
+ VERSION = '2.0.7.beta'
def self.sql raw_sql
Arel::Nodes::SqlLiteral.new raw_sql
end
+
+ def self.star
+ sql '*'
+ end
## Convenience Alias
Node = Arel::Nodes::Node
end
diff --git a/lib/arel/attributes/attribute.rb b/lib/arel/attributes/attribute.rb
index 5cbe194b41..9a42e5a4da 100644
--- a/lib/arel/attributes/attribute.rb
+++ b/lib/arel/attributes/attribute.rb
@@ -1,6 +1,6 @@
module Arel
module Attributes
- class Attribute < Struct.new :relation, :name, :column
+ class Attribute < Struct.new :relation, :name
include Arel::Expressions
include Arel::Predications
end
diff --git a/lib/arel/crud.rb b/lib/arel/crud.rb
index 50d6f72773..bedfb8c30c 100644
--- a/lib/arel/crud.rb
+++ b/lib/arel/crud.rb
@@ -2,12 +2,11 @@ module Arel
###
# FIXME hopefully we can remove this
module Crud
- # FIXME: this method should go away
- def update values
+ def compile_update values
um = UpdateManager.new @engine
if Nodes::SqlLiteral === values
- relation = @ctx.froms
+ relation = @ctx.from
else
relation = values.first.first.relation
end
@@ -16,22 +15,54 @@ module Arel
um.take @ast.limit.expr if @ast.limit
um.order(*@ast.orders)
um.wheres = @ctx.wheres
+ um
+ end
+
+ # FIXME: this method should go away
+ def update values
+ if $VERBOSE
+ warn <<-eowarn
+update (#{caller.first}) is deprecated and will be removed in ARel 3.0.0. Please
+switch to `compile_update`
+ eowarn
+ end
+ um = compile_update values
@engine.connection.update um.to_sql, 'AREL'
end
- # FIXME: this method should go away
- def insert values
+ def compile_insert values
im = InsertManager.new @engine
im.insert values
- @engine.connection.insert im.to_sql
+ im
end
- def delete
+ # FIXME: this method should go away
+ def insert values
+ if $VERBOSE
+ warn <<-eowarn
+insert (#{caller.first}) is deprecated and will be removed in ARel 3.0.0. Please
+switch to `compile_insert`
+ eowarn
+ end
+ @engine.connection.insert compile_insert(values).to_sql
+ end
+
+ def compile_delete
dm = DeleteManager.new @engine
dm.wheres = @ctx.wheres
dm.from @ctx.froms
- @engine.connection.delete dm.to_sql, 'AREL'
+ dm
+ end
+
+ def delete
+ if $VERBOSE
+ warn <<-eowarn
+delete (#{caller.first}) is deprecated and will be removed in ARel 3.0.0. Please
+switch to `compile_delete`
+ eowarn
+ end
+ @engine.connection.delete compile_delete.to_sql, 'AREL'
end
end
end
diff --git a/lib/arel/factory_methods.rb b/lib/arel/factory_methods.rb
new file mode 100644
index 0000000000..09b82c0555
--- /dev/null
+++ b/lib/arel/factory_methods.rb
@@ -0,0 +1,25 @@
+module Arel
+ ###
+ # Methods for creating various nodes
+ module FactoryMethods
+ def create_join to, constraint = nil, klass = Nodes::InnerJoin
+ klass.new(to, constraint)
+ end
+
+ def create_string_join to
+ create_join to, nil, Nodes::StringJoin
+ end
+
+ def create_and clauses
+ Nodes::And.new clauses
+ end
+
+ def create_on expr
+ Nodes::On.new expr
+ end
+
+ def grouping expr
+ Nodes::Grouping.new expr
+ end
+ end
+end
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb
index db2f22750a..c43134bb50 100644
--- a/lib/arel/nodes.rb
+++ b/lib/arel/nodes.rb
@@ -1,49 +1,37 @@
+# node
require 'arel/nodes/node'
+require 'arel/nodes/lock'
+require 'arel/nodes/select_statement'
+require 'arel/nodes/select_core'
+require 'arel/nodes/insert_statement'
+require 'arel/nodes/update_statement'
+
+# unary
require 'arel/nodes/unary'
+require 'arel/nodes/unqualified_column'
+
+# binary
require 'arel/nodes/binary'
require 'arel/nodes/equality'
-require 'arel/nodes/between'
-require 'arel/nodes/not_equal'
-require 'arel/nodes/assignment'
-require 'arel/nodes/or'
+require 'arel/nodes/in' # Why is this subclassed from equality?
+require 'arel/nodes/join_source'
+require 'arel/nodes/ordering'
+require 'arel/nodes/delete_statement'
+require 'arel/nodes/table_alias'
+
+# nary
require 'arel/nodes/and'
-require 'arel/nodes/as'
-require 'arel/nodes/not'
-require 'arel/nodes/greater_than'
-require 'arel/nodes/greater_than_or_equal'
-require 'arel/nodes/less_than'
-require 'arel/nodes/less_than_or_equal'
-require 'arel/nodes/matches'
-require 'arel/nodes/does_not_match'
-require 'arel/nodes/in'
-require 'arel/nodes/not_in'
-require 'arel/nodes/ordering'
-require 'arel/nodes/lock'
+# function
+# FIXME: Function + Alias can be rewritten as a Function and Alias node.
+# We should make Function a Unary node and deprecate the use of "aliaz"
require 'arel/nodes/function'
require 'arel/nodes/count'
require 'arel/nodes/values'
-require 'arel/nodes/offset'
-require 'arel/nodes/limit'
-require 'arel/nodes/top'
-require 'arel/nodes/sum'
-require 'arel/nodes/exists'
-require 'arel/nodes/max'
-require 'arel/nodes/min'
-require 'arel/nodes/avg'
-require 'arel/nodes/having'
-require 'arel/nodes/sql_literal'
-require 'arel/nodes/select_core'
-require 'arel/nodes/select_statement'
-require 'arel/nodes/insert_statement'
-require 'arel/nodes/update_statement'
-require 'arel/nodes/delete_statement'
-require 'arel/nodes/unqualified_column'
-require 'arel/nodes/table_alias'
-require 'arel/nodes/join'
-require 'arel/nodes/group'
-require 'arel/nodes/grouping'
+
+# joins
require 'arel/nodes/inner_join'
require 'arel/nodes/outer_join'
require 'arel/nodes/string_join'
-require 'arel/nodes/on'
+
+require 'arel/nodes/sql_literal'
diff --git a/lib/arel/nodes/and.rb b/lib/arel/nodes/and.rb
index 80f420b4f1..b4443c3d27 100644
--- a/lib/arel/nodes/and.rb
+++ b/lib/arel/nodes/and.rb
@@ -1,6 +1,23 @@
module Arel
module Nodes
- class And < Arel::Nodes::Binary
+ class And < Arel::Nodes::Node
+ attr_reader :children
+
+ def initialize children, right = nil
+ unless Array === children
+ warn "(#{caller.first}) AND nodes should be created with a list"
+ children = [children, right]
+ end
+ @children = children
+ end
+
+ def left
+ children.first
+ end
+
+ def right
+ children[1]
+ end
end
end
end
diff --git a/lib/arel/nodes/as.rb b/lib/arel/nodes/as.rb
deleted file mode 100644
index 9009fe12f4..0000000000
--- a/lib/arel/nodes/as.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class As < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/assignment.rb b/lib/arel/nodes/assignment.rb
deleted file mode 100644
index 693bd5afe6..0000000000
--- a/lib/arel/nodes/assignment.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Assignment < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/avg.rb b/lib/arel/nodes/avg.rb
deleted file mode 100644
index 8fc86fc21e..0000000000
--- a/lib/arel/nodes/avg.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Avg < Arel::Nodes::Function
- end
- end
-end
diff --git a/lib/arel/nodes/between.rb b/lib/arel/nodes/between.rb
deleted file mode 100644
index 2e7596cdae..0000000000
--- a/lib/arel/nodes/between.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Between < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/binary.rb b/lib/arel/nodes/binary.rb
index cfa75909c5..0d02554199 100644
--- a/lib/arel/nodes/binary.rb
+++ b/lib/arel/nodes/binary.rb
@@ -7,6 +7,30 @@ module Arel
@left = left
@right = right
end
+
+ def initialize_copy other
+ super
+ @left = @left.clone if @left
+ @right = @right.clone if @right
+ end
+ end
+
+ %w{
+ As
+ Assignment
+ Between
+ DoesNotMatch
+ GreaterThan
+ GreaterThanOrEqual
+ Join
+ LessThan
+ LessThanOrEqual
+ Matches
+ NotEqual
+ NotIn
+ Or
+ }.each do |name|
+ const_set name, Class.new(Binary)
end
end
end
diff --git a/lib/arel/nodes/does_not_match.rb b/lib/arel/nodes/does_not_match.rb
deleted file mode 100644
index 33bdeab005..0000000000
--- a/lib/arel/nodes/does_not_match.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class DoesNotMatch < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/exists.rb b/lib/arel/nodes/exists.rb
deleted file mode 100644
index 18ba8403b4..0000000000
--- a/lib/arel/nodes/exists.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module Arel
- module Nodes
- class Exists < Arel::Nodes::Function
- alias :select_stmt :expressions
- end
- end
-end
diff --git a/lib/arel/nodes/function.rb b/lib/arel/nodes/function.rb
index 133dd66019..e4e45bff31 100644
--- a/lib/arel/nodes/function.rb
+++ b/lib/arel/nodes/function.rb
@@ -14,5 +14,15 @@ module Arel
self
end
end
+
+ %w{
+ Sum
+ Exists
+ Max
+ Min
+ Avg
+ }.each do |name|
+ const_set(name, Class.new(Function))
+ end
end
end
diff --git a/lib/arel/nodes/greater_than.rb b/lib/arel/nodes/greater_than.rb
deleted file mode 100644
index 2e03cc2e18..0000000000
--- a/lib/arel/nodes/greater_than.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class GreaterThan < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/greater_than_or_equal.rb b/lib/arel/nodes/greater_than_or_equal.rb
deleted file mode 100644
index a8cfaab04e..0000000000
--- a/lib/arel/nodes/greater_than_or_equal.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class GreaterThanOrEqual < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/group.rb b/lib/arel/nodes/group.rb
deleted file mode 100644
index a7fa6f170d..0000000000
--- a/lib/arel/nodes/group.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Group < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/grouping.rb b/lib/arel/nodes/grouping.rb
deleted file mode 100644
index 18adeae97f..0000000000
--- a/lib/arel/nodes/grouping.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Grouping < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/having.rb b/lib/arel/nodes/having.rb
deleted file mode 100644
index 6972c58dda..0000000000
--- a/lib/arel/nodes/having.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Having < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/join.rb b/lib/arel/nodes/join.rb
deleted file mode 100644
index 07f8c98e85..0000000000
--- a/lib/arel/nodes/join.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module Arel
- module Nodes
- class Join < Arel::Nodes::Node
- attr_accessor :left, :right, :constraint
-
- def initialize left, right, constraint
- @left = left
- @right = right
- @constraint = constraint
- end
- end
- end
-end
diff --git a/lib/arel/nodes/join_source.rb b/lib/arel/nodes/join_source.rb
new file mode 100644
index 0000000000..c57ad0e930
--- /dev/null
+++ b/lib/arel/nodes/join_source.rb
@@ -0,0 +1,14 @@
+module Arel
+ module Nodes
+ ###
+ # Class that represents a join source
+ #
+ # http://www.sqlite.org/syntaxdiagrams.html#join-source
+
+ class JoinSource < Arel::Nodes::Binary
+ def initialize single_source, joinop = []
+ super
+ end
+ end
+ end
+end
diff --git a/lib/arel/nodes/less_than.rb b/lib/arel/nodes/less_than.rb
deleted file mode 100644
index cfaf716c42..0000000000
--- a/lib/arel/nodes/less_than.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class LessThan < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/less_than_or_equal.rb b/lib/arel/nodes/less_than_or_equal.rb
deleted file mode 100644
index 55449d12f1..0000000000
--- a/lib/arel/nodes/less_than_or_equal.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class LessThanOrEqual < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/limit.rb b/lib/arel/nodes/limit.rb
deleted file mode 100644
index 68ea95daf5..0000000000
--- a/lib/arel/nodes/limit.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module Arel
- module Nodes
- class Limit < Arel::Nodes::Unary
- end
- end
-end
-
diff --git a/lib/arel/nodes/matches.rb b/lib/arel/nodes/matches.rb
deleted file mode 100644
index 5ef8ac8302..0000000000
--- a/lib/arel/nodes/matches.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Matches < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/max.rb b/lib/arel/nodes/max.rb
deleted file mode 100644
index 5af611b0d6..0000000000
--- a/lib/arel/nodes/max.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Max < Arel::Nodes::Function
- end
- end
-end
diff --git a/lib/arel/nodes/min.rb b/lib/arel/nodes/min.rb
deleted file mode 100644
index bdc1371858..0000000000
--- a/lib/arel/nodes/min.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Min < Arel::Nodes::Function
- end
- end
-end
diff --git a/lib/arel/nodes/node.rb b/lib/arel/nodes/node.rb
index 404ad22ece..711fa34b6d 100644
--- a/lib/arel/nodes/node.rb
+++ b/lib/arel/nodes/node.rb
@@ -3,6 +3,9 @@ module Arel
###
# Abstract base class for all AST nodes
class Node
+ include Arel::FactoryMethods
+ include Enumerable
+
###
# Factory method to create a Nodes::Not node that has the recipient of
# the caller as a child.
@@ -20,7 +23,7 @@ module Arel
###
# Factory method to create an Nodes::And node.
def and right
- Nodes::And.new self, right
+ Nodes::And.new [self, right]
end
# FIXME: this method should go away. I don't like people calling
diff --git a/lib/arel/nodes/not.rb b/lib/arel/nodes/not.rb
deleted file mode 100644
index de138435bb..0000000000
--- a/lib/arel/nodes/not.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Not < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/not_equal.rb b/lib/arel/nodes/not_equal.rb
deleted file mode 100644
index 7f892940cb..0000000000
--- a/lib/arel/nodes/not_equal.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class NotEqual < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/not_in.rb b/lib/arel/nodes/not_in.rb
deleted file mode 100644
index 6c01921a46..0000000000
--- a/lib/arel/nodes/not_in.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class NotIn < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/offset.rb b/lib/arel/nodes/offset.rb
deleted file mode 100644
index d93e46aa1f..0000000000
--- a/lib/arel/nodes/offset.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module Arel
- module Nodes
- class Offset < Arel::Nodes::Unary
- alias :value :expr
- end
- end
-end
diff --git a/lib/arel/nodes/on.rb b/lib/arel/nodes/on.rb
deleted file mode 100644
index 953d64f9f1..0000000000
--- a/lib/arel/nodes/on.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class On < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/or.rb b/lib/arel/nodes/or.rb
deleted file mode 100644
index bdf7f6d9b3..0000000000
--- a/lib/arel/nodes/or.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Or < Arel::Nodes::Binary
- end
- end
-end
diff --git a/lib/arel/nodes/select_core.rb b/lib/arel/nodes/select_core.rb
index 501a2aaf7c..7f577e0a05 100644
--- a/lib/arel/nodes/select_core.rb
+++ b/lib/arel/nodes/select_core.rb
@@ -1,24 +1,35 @@
module Arel
module Nodes
class SelectCore < Arel::Nodes::Node
- attr_accessor :top, :froms, :projections, :wheres, :groups
- attr_accessor :having
+ attr_accessor :top, :projections, :wheres, :groups
+ attr_accessor :having, :source
def initialize
+ @source = JoinSource.new nil
@top = nil
- @froms = nil
@projections = []
@wheres = []
@groups = []
@having = nil
end
+ def from
+ @source.left
+ end
+
+ def from= value
+ @source.left = value
+ end
+
+ alias :froms= :from=
+ alias :froms :from
+
def initialize_copy other
super
- @froms = @froms.clone if @froms
+ @source = @source.clone if @source
@projections = @projections.clone
@wheres = @wheres.clone
- @group = @groups.clone
+ @groups = @groups.clone
@having = @having.clone if @having
end
end
diff --git a/lib/arel/nodes/select_statement.rb b/lib/arel/nodes/select_statement.rb
index 6881a66747..c9a0cde4e0 100644
--- a/lib/arel/nodes/select_statement.rb
+++ b/lib/arel/nodes/select_statement.rb
@@ -5,6 +5,7 @@ module Arel
attr_accessor :limit, :orders, :lock, :offset
def initialize cores = [SelectCore.new]
+ #puts caller
@cores = cores
@orders = []
@limit = nil
diff --git a/lib/arel/nodes/string_join.rb b/lib/arel/nodes/string_join.rb
index ea7912f92b..7fb0033c0f 100644
--- a/lib/arel/nodes/string_join.rb
+++ b/lib/arel/nodes/string_join.rb
@@ -1,10 +1,8 @@
module Arel
module Nodes
class StringJoin < Arel::Nodes::Join
- undef :constraint
-
- def initialize left, right
- super(left, right, nil)
+ def initialize left, right = nil
+ super
end
end
end
diff --git a/lib/arel/nodes/sum.rb b/lib/arel/nodes/sum.rb
deleted file mode 100644
index 3e043b7330..0000000000
--- a/lib/arel/nodes/sum.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Sum < Arel::Nodes::Function
- end
- end
-end
diff --git a/lib/arel/nodes/table_alias.rb b/lib/arel/nodes/table_alias.rb
index 723b025883..4f4d5e29e9 100644
--- a/lib/arel/nodes/table_alias.rb
+++ b/lib/arel/nodes/table_alias.rb
@@ -6,7 +6,7 @@ module Arel
alias :table_alias :name
def [] name
- Attribute.new self, name
+ Attribute.new(self, name)
end
end
end
diff --git a/lib/arel/nodes/top.rb b/lib/arel/nodes/top.rb
deleted file mode 100644
index 56e2e97e8d..0000000000
--- a/lib/arel/nodes/top.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Arel
- module Nodes
- class Top < Arel::Nodes::Unary
- end
- end
-end
diff --git a/lib/arel/nodes/unary.rb b/lib/arel/nodes/unary.rb
index edda89e1f0..e1576b9c99 100644
--- a/lib/arel/nodes/unary.rb
+++ b/lib/arel/nodes/unary.rb
@@ -2,10 +2,24 @@ module Arel
module Nodes
class Unary < Arel::Nodes::Node
attr_accessor :expr
+ alias :value :expr
def initialize expr
@expr = expr
end
end
+
+ %w{
+ Group
+ Grouping
+ Having
+ Limit
+ Not
+ Offset
+ On
+ Top
+ }.each do |name|
+ const_set(name, Class.new(Unary))
+ end
end
end
diff --git a/lib/arel/nodes/unqualified_column.rb b/lib/arel/nodes/unqualified_column.rb
index f7ba653c11..2820dba9d2 100644
--- a/lib/arel/nodes/unqualified_column.rb
+++ b/lib/arel/nodes/unqualified_column.rb
@@ -4,6 +4,10 @@ module Arel
alias :attribute :expr
alias :attribute= :expr=
+ def relation
+ @expr.relation
+ end
+
def column
@expr.column
end
diff --git a/lib/arel/nodes/update_statement.rb b/lib/arel/nodes/update_statement.rb
index 288e9f4676..c08f1b2c5e 100644
--- a/lib/arel/nodes/update_statement.rb
+++ b/lib/arel/nodes/update_statement.rb
@@ -2,13 +2,15 @@ module Arel
module Nodes
class UpdateStatement < Arel::Nodes::Node
attr_accessor :relation, :wheres, :values, :orders, :limit
+ attr_accessor :key
def initialize
@relation = nil
@wheres = []
@values = []
- @orders = []
- @limit = nil
+ @orders = []
+ @limit = nil
+ @key = nil
end
def initialize_copy other
diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb
index 23e68e99f1..58f02a2b53 100644
--- a/lib/arel/predications.rb
+++ b/lib/arel/predications.rb
@@ -36,9 +36,9 @@ module Arel
if other.exclude_end?
left = Nodes::GreaterThanOrEqual.new(self, other.begin)
right = Nodes::LessThan.new(self, other.end)
- Nodes::And.new left, right
+ Nodes::And.new [left, right]
else
- Nodes::Between.new(self, Nodes::And.new(other.begin, other.end))
+ Nodes::Between.new(self, Nodes::And.new([other.begin, other.end]))
end
else
Nodes::In.new self, other
@@ -174,7 +174,7 @@ module Arel
first = send method_id, others.shift
Nodes::Grouping.new others.inject(first) { |memo,expr|
- Nodes::And.new(memo, send(method_id, expr))
+ Nodes::And.new([memo, send(method_id, expr)])
}
end
end
diff --git a/lib/arel/select_manager.rb b/lib/arel/select_manager.rb
index cb656d5340..b4103144fe 100644
--- a/lib/arel/select_manager.rb
+++ b/lib/arel/select_manager.rb
@@ -9,9 +9,10 @@ module Arel
from table
end
- def taken
+ def limit
@ast.limit && @ast.limit.expr
end
+ alias :taken :limit
def constraints
@ctx.wheres
@@ -29,7 +30,9 @@ module Arel
end
def where_clauses
- #warn "where_clauses is deprecated" if $VERBOSE
+ if $VERBOSE
+ warn "(#{caller.first}) where_clauses is deprecated and will be removed in arel 3.0.0 with no replacement"
+ end
to_sql = Visitors::ToSql.new @engine
@ctx.wheres.map { |c| to_sql.accept c }
end
@@ -46,7 +49,7 @@ module Arel
end
def on *exprs
- @ctx.froms.constraint = Nodes::On.new(collapse(exprs))
+ @ctx.source.right.last.right = Nodes::On.new(collapse(exprs))
self
end
@@ -66,35 +69,36 @@ module Arel
# FIXME: this is a hack to support
# test_with_two_tables_in_from_without_getting_double_quoted
# from the AR tests.
- if @ctx.froms
- source = @ctx.froms
- if Nodes::SqlLiteral === table && Nodes::Join === source
- source.left = table
- table = source
- end
+ case table
+ when Nodes::SqlLiteral, Arel::Table
+ @ctx.source.left = table
+ when Nodes::Join
+ @ctx.source.right << table
end
- @ctx.froms = table
self
end
+ def froms
+ @ast.cores.map { |x| x.from }.compact
+ end
+
def join relation, klass = Nodes::InnerJoin
return self unless relation
case relation
when String, Nodes::SqlLiteral
raise if relation.blank?
- from Nodes::StringJoin.new(@ctx.froms, relation)
- else
- from klass.new(@ctx.froms, relation, nil)
+ klass = Nodes::StringJoin
end
- end
- def having expr
- expr = Nodes::SqlLiteral.new(expr) if String === expr
+ @ctx.source.right << create_join(relation, nil, klass)
+ self
+ end
- @ctx.having = Nodes::Having.new(expr)
+ def having *exprs
+ @ctx.having = Nodes::Having.new(collapse(exprs, @ctx.having))
self
end
@@ -137,10 +141,10 @@ module Arel
end
def join_sql
- return nil unless @ctx.froms
+ return nil if @ctx.source.right.empty?
- viz = Visitors::JoinSql.new @engine
- Nodes::SqlLiteral.new viz.accept @ctx
+ sql = @visitor.dup.extend(Visitors::JoinSql).accept @ctx
+ Nodes::SqlLiteral.new sql
end
def order_clauses
@@ -149,9 +153,13 @@ module Arel
}
end
+ def join_sources
+ @ctx.source.right
+ end
+
def joins manager
if $VERBOSE
- warn "joins is deprecated and will be removed in 2.2"
+ warn "joins is deprecated and will be removed in 3.0.0"
warn "please remove your call to joins from #{caller.first}"
end
manager.join_sql
@@ -177,13 +185,22 @@ module Arel
# FIXME: this method should go away
def insert values
- im = InsertManager.new @engine
+ if $VERBOSE
+ warn <<-eowarn
+insert (#{caller.first}) is deprecated and will be removed in ARel 3.0.0. Please
+switch to `compile_insert`
+ eowarn
+ end
+
+ im = compile_insert(values)
table = @ctx.froms
- primary_key_name = (primary_key = table.primary_key) && primary_key.name
+
+ primary_key = table.primary_key
+ primary_key_name = primary_key.name if primary_key
+
# FIXME: in AR tests values sometimes were Array and not Hash therefore is_a?(Hash) check is added
primary_key_value = primary_key && values.is_a?(Hash) && values[primary_key]
im.into table
- im.insert values
# Oracle adapter needs primary key name to generate RETURNING ... INTO ... clause
# for tables which assign primary key value using trigger.
# RETURNING ... INTO ... clause will be added only if primary_key_value is nil
@@ -192,18 +209,22 @@ module Arel
end
private
- def collapse exprs
- return exprs.first if exprs.length == 1
-
- right = exprs.pop
- left = exprs.pop
-
- right = Nodes::SqlLiteral.new(right) if String === right
-
- right = Nodes::And.new left, right
- exprs.reverse.inject(right) { |memo,expr|
- Nodes::And.new(expr, memo)
+ def collapse exprs, existing = nil
+ exprs = exprs.unshift(existing.expr) if existing
+ exprs = exprs.compact.map { |expr|
+ if String === expr
+ # FIXME: Don't do this automatically
+ Arel.sql(expr)
+ else
+ expr
+ end
}
+
+ if exprs.length == 1
+ exprs.first
+ else
+ create_and exprs
+ end
end
end
end
diff --git a/lib/arel/table.rb b/lib/arel/table.rb
index aa23a7d601..d1d1e40e11 100644
--- a/lib/arel/table.rb
+++ b/lib/arel/table.rb
@@ -1,6 +1,7 @@
module Arel
class Table
include Arel::Crud
+ include Arel::FactoryMethods
@engine = nil
class << self; attr_accessor :engine; end
@@ -17,7 +18,6 @@ module Arel
if Hash === engine
@engine = engine[:engine] || Table.engine
- @columns = attributes_for engine[:columns]
# Sometime AR sends an :as parameter to table, to let the table know
# that it is an Alias. We may want to override new, and return a
@@ -27,6 +27,11 @@ module Arel
end
def primary_key
+ if $VERBOSE
+ warn <<-eowarn
+primary_key (#{caller.first}) is deprecated and will be removed in ARel 3.0.0
+ eowarn
+ end
@primary_key ||= begin
primary_key_name = @engine.connection.primary_key(name)
# some tables might be without primary key
@@ -46,7 +51,7 @@ module Arel
def joins manager
if $VERBOSE
- warn "joins is deprecated and will be removed in 2.2"
+ warn "joins is deprecated and will be removed in 3.0.0"
warn "please remove your call to joins from #{caller.first}"
end
nil
@@ -58,10 +63,10 @@ module Arel
case relation
when String, Nodes::SqlLiteral
raise if relation.blank?
- from Nodes::StringJoin.new(self, relation)
- else
- from klass.new(self, relation, nil)
+ klass = Nodes::StringJoin
end
+
+ from(self).join(relation, klass)
end
def group *columns
@@ -93,41 +98,46 @@ module Arel
end
def columns
+ if $VERBOSE
+ warn <<-eowarn
+(#{caller.first}) Arel::Table#columns is deprecated and will be removed in
+Arel 3.0.0 with no replacement. PEW PEW PEW!!!
+ eowarn
+ end
@columns ||=
attributes_for @engine.connection.columns(@name, "#{@name} Columns")
end
def [] name
- return nil unless table_exists?
-
- name = name.to_sym
- columns.find { |column| column.name == name }
+ ::Arel::Attribute.new self, name
end
def select_manager
SelectManager.new(@engine)
end
+ def insert_manager
+ InsertManager.new(@engine)
+ end
+
private
def attributes_for columns
return nil unless columns
columns.map do |column|
- Attributes.for(column).new self, column.name.to_sym, column
+ Attributes.for(column).new self, column.name.to_sym
end
end
- def table_exists?
- @table_exists ||= tables.key?(@name) || engine.connection.table_exists?(name)
- end
-
- def tables
- self.class.table_cache(@engine)
- end
-
@@table_cache = nil
def self.table_cache engine # :nodoc:
+ if $VERBOSE
+ warn <<-eowarn
+(#{caller.first}) Arel::Table.table_cache is deprecated and will be removed in
+Arel 3.0.0 with no replacement. PEW PEW PEW!!!
+ eowarn
+ end
@@table_cache ||= Hash[engine.connection.tables.map { |x| [x,true] }]
end
end
diff --git a/lib/arel/tree_manager.rb b/lib/arel/tree_manager.rb
index 2fa770a0e3..5722baca77 100644
--- a/lib/arel/tree_manager.rb
+++ b/lib/arel/tree_manager.rb
@@ -2,6 +2,7 @@ module Arel
class TreeManager
# FIXME: Remove this.
include Arel::Relation
+ include Arel::FactoryMethods
attr_accessor :visitor
attr_reader :ast, :engine
diff --git a/lib/arel/update_manager.rb b/lib/arel/update_manager.rb
index d92c8b9a03..f13aeb0a8c 100644
--- a/lib/arel/update_manager.rb
+++ b/lib/arel/update_manager.rb
@@ -11,6 +11,10 @@ module Arel
self
end
+ def key= key
+ @ast.key = key
+ end
+
def order *expr
@ast.orders = expr
self
diff --git a/lib/arel/visitors/depth_first.rb b/lib/arel/visitors/depth_first.rb
index 00f18727f0..ed95cad472 100644
--- a/lib/arel/visitors/depth_first.rb
+++ b/lib/arel/visitors/depth_first.rb
@@ -18,9 +18,11 @@ module Arel
alias :visit_Arel_Nodes_Group :unary
alias :visit_Arel_Nodes_Grouping :unary
alias :visit_Arel_Nodes_Having :unary
+ alias :visit_Arel_Nodes_Limit :unary
alias :visit_Arel_Nodes_Not :unary
alias :visit_Arel_Nodes_Offset :unary
alias :visit_Arel_Nodes_On :unary
+ alias :visit_Arel_Nodes_Top :unary
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
def function o
@@ -39,19 +41,15 @@ module Arel
visit o.distinct
end
- def join o
- visit o.left
- visit o.right
- visit o.constraint
+ def nary o
+ o.children.each { |child| visit child }
end
- alias :visit_Arel_Nodes_InnerJoin :join
- alias :visit_Arel_Nodes_OuterJoin :join
+ alias :visit_Arel_Nodes_And :nary
def binary o
visit o.left
visit o.right
end
- alias :visit_Arel_Nodes_And :binary
alias :visit_Arel_Nodes_As :binary
alias :visit_Arel_Nodes_Assignment :binary
alias :visit_Arel_Nodes_Between :binary
@@ -61,6 +59,8 @@ module Arel
alias :visit_Arel_Nodes_GreaterThan :binary
alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
alias :visit_Arel_Nodes_In :binary
+ alias :visit_Arel_Nodes_JoinSource :binary
+ alias :visit_Arel_Nodes_InnerJoin :binary
alias :visit_Arel_Nodes_LessThan :binary
alias :visit_Arel_Nodes_LessThanOrEqual :binary
alias :visit_Arel_Nodes_Matches :binary
@@ -68,10 +68,14 @@ module Arel
alias :visit_Arel_Nodes_NotIn :binary
alias :visit_Arel_Nodes_Or :binary
alias :visit_Arel_Nodes_Ordering :binary
- alias :visit_Arel_Nodes_StringJoin :binary
+ alias :visit_Arel_Nodes_OuterJoin :binary
alias :visit_Arel_Nodes_TableAlias :binary
alias :visit_Arel_Nodes_Values :binary
+ def visit_Arel_Nodes_StringJoin o
+ visit o.left
+ end
+
def visit_Arel_Attribute o
visit o.relation
visit o.name
@@ -118,7 +122,7 @@ module Arel
def visit_Arel_Nodes_SelectCore o
visit o.projections
- visit o.froms
+ visit o.source
visit o.wheres
visit o.groups
visit o.having
diff --git a/lib/arel/visitors/dot.rb b/lib/arel/visitors/dot.rb
index eab5e4afdc..3c4fe12d1f 100644
--- a/lib/arel/visitors/dot.rb
+++ b/lib/arel/visitors/dot.rb
@@ -36,7 +36,6 @@ module Arel
def visit_Arel_Nodes_TableAlias o
visit_edge o, "name"
visit_edge o, "relation"
- visit_edge o, "columns"
end
def visit_Arel_Nodes_Sum o
@@ -57,13 +56,11 @@ module Arel
def visit_Arel_Nodes_StringJoin o
visit_edge o, "left"
- visit_edge o, "right"
end
def visit_Arel_Nodes_InnerJoin o
visit_edge o, "left"
visit_edge o, "right"
- visit_edge o, "constraint"
end
alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin
@@ -78,9 +75,11 @@ module Arel
alias :visit_Arel_Nodes_Group :unary
alias :visit_Arel_Nodes_Grouping :unary
alias :visit_Arel_Nodes_Having :unary
+ alias :visit_Arel_Nodes_Limit :unary
alias :visit_Arel_Nodes_Not :unary
alias :visit_Arel_Nodes_Offset :unary
alias :visit_Arel_Nodes_On :unary
+ alias :visit_Arel_Nodes_Top :unary
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
def visit_Arel_Nodes_InsertStatement o
@@ -90,7 +89,7 @@ module Arel
end
def visit_Arel_Nodes_SelectCore o
- visit_edge o, "froms"
+ visit_edge o, "source"
visit_edge o, "projections"
visit_edge o, "wheres"
end
@@ -123,23 +122,32 @@ module Arel
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
- def visit_Arel_Nodes_Equality o
+ def nary o
+ o.children.each_with_index do |x,i|
+ edge(i) { visit x }
+ end
+ end
+ alias :visit_Arel_Nodes_And :nary
+
+ def binary o
visit_edge o, "left"
visit_edge o, "right"
end
- alias :visit_Arel_Nodes_And :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_Or :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_NotEqual :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_GreaterThan :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_GreaterThanOrEqual :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_Assignment :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_In :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_LessThan :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_LessThanOrEqual :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_Between :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_NotIn :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_DoesNotMatch :visit_Arel_Nodes_Equality
- alias :visit_Arel_Nodes_Matches :visit_Arel_Nodes_Equality
+ alias :visit_Arel_Nodes_As :binary
+ alias :visit_Arel_Nodes_Assignment :binary
+ alias :visit_Arel_Nodes_Between :binary
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
+ alias :visit_Arel_Nodes_Equality :binary
+ alias :visit_Arel_Nodes_GreaterThan :binary
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
+ alias :visit_Arel_Nodes_In :binary
+ alias :visit_Arel_Nodes_JoinSource :binary
+ alias :visit_Arel_Nodes_LessThan :binary
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
+ alias :visit_Arel_Nodes_Matches :binary
+ alias :visit_Arel_Nodes_NotEqual :binary
+ alias :visit_Arel_Nodes_NotIn :binary
+ alias :visit_Arel_Nodes_Or :binary
def visit_String o
@node_stack.last.fields << o
diff --git a/lib/arel/visitors/join_sql.rb b/lib/arel/visitors/join_sql.rb
index d3fb18d3c6..1cdd7eb5ca 100644
--- a/lib/arel/visitors/join_sql.rb
+++ b/lib/arel/visitors/join_sql.rb
@@ -8,32 +8,11 @@ module Arel
#
# This visitor is used in SelectManager#join_sql and is for backwards
# compatibility with Arel V1.0
- class JoinSql < Arel::Visitors::ToSql
+ module JoinSql
private
def visit_Arel_Nodes_SelectCore o
- [o.froms].grep(Nodes::Join).map { |x| visit x }.join ', '
- end
-
- def visit_Arel_Nodes_StringJoin o
- [
- (visit o.left if Nodes::Join === o.left),
- visit(o.right)
- ].compact.join ' '
- end
-
- def visit_Arel_Nodes_OuterJoin o
- [
- (visit o.left if Nodes::Join === o.left),
- "LEFT OUTER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
- ].compact.join ' '
- end
-
- def visit_Arel_Nodes_InnerJoin o
- [
- (visit o.left if Nodes::Join === o.left),
- "INNER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
- ].compact.join ' '
+ o.source.right.map { |j| visit j }.join ' '
end
end
end
diff --git a/lib/arel/visitors/oracle.rb b/lib/arel/visitors/oracle.rb
index 3c8c816feb..aaf0324fd7 100644
--- a/lib/arel/visitors/oracle.rb
+++ b/lib/arel/visitors/oracle.rb
@@ -25,7 +25,7 @@ module Arel
SELECT * FROM (
SELECT raw_sql_.*, rownum raw_rnum_
FROM (#{sql}) raw_sql_
- WHERE rownum <= #{offset.value.to_i + limit}
+ WHERE rownum <= #{offset.expr.to_i + limit}
)
WHERE #{visit offset}
eosql
@@ -58,7 +58,7 @@ module Arel
end
def visit_Arel_Nodes_Offset o
- "raw_rnum_ > #{visit o.value}"
+ "raw_rnum_ > #{visit o.expr}"
end
###
diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb
index 7435e41561..4eae5a9ae5 100644
--- a/lib/arel/visitors/to_sql.rb
+++ b/lib/arel/visitors/to_sql.rb
@@ -7,14 +7,24 @@ module Arel
def initialize engine
@engine = engine
@connection = nil
+ @pool = nil
@last_column = nil
@quoted_tables = {}
@quoted_columns = {}
+ @column_cache = Hash.new { |h,pool|
+ h[pool] = Hash.new { |conn_h,column|
+ conn_h[column] = {}
+ }
+ }
+ @table_exists = Hash.new { |h,pool|
+ h[pool] = {}
+ }
end
def accept object
@last_column = nil
- @engine.connection_pool.with_connection do |conn|
+ @pool = @engine.connection_pool
+ @pool.with_connection do |conn|
@connection = conn
super
end
@@ -32,20 +42,31 @@ module Arel
if o.orders.empty? && o.limit.nil?
wheres = o.wheres
else
+ key = o.key
+ unless key
+ warn(<<-eowarn) if $VERBOSE
+(#{caller.first}) Using UpdateManager without setting UpdateManager#key is
+deprecated and support will be removed in ARel 3.0.0. Please set the primary
+key on UpdateManager using UpdateManager#key=
+eowarn
+ key = o.relation.primary_key
+ end
+
+ wheres = o.wheres
stmt = Nodes::SelectStatement.new
core = stmt.cores.first
core.froms = o.relation
- core.projections = [o.relation.primary_key]
+ core.projections = [key]
stmt.limit = o.limit
stmt.orders = o.orders
- wheres = [Nodes::In.new(o.relation.primary_key, [stmt])]
+ wheres = [Nodes::In.new(key, [stmt])]
end
[
"UPDATE #{visit o.relation}",
("SET #{o.values.map { |value| visit value }.join ', '}" unless o.values.empty?),
- ("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?)
+ ("WHERE #{wheres.map { |x| visit x }.join ' AND '}" unless wheres.empty?),
].compact.join ' '
end
@@ -62,13 +83,47 @@ module Arel
end
def visit_Arel_Nodes_Exists o
- "EXISTS (#{visit o.select_stmt})#{
+ "EXISTS (#{visit o.expressions})#{
o.alias ? " AS #{visit o.alias}" : ''}"
end
+ def table_exists? name
+ return true if table_exists.key? name
+
+ @connection.tables.each do |table|
+ table_exists[table] = true
+ end
+
+ table_exists.key? name
+ end
+
+ def table_exists
+ @table_exists[@pool]
+ end
+
+ def column_for attr
+ name = attr.name.to_sym
+ table = attr.relation.name
+
+ return nil unless table_exists? table
+
+ # If we don't have this column cached, get a list of columns and
+ # cache them for this table
+ unless column_cache.key? table
+ columns = @connection.columns(table, "#{table}(#{name}) Columns")
+ column_cache[table] = Hash[columns.map { |c| [c.name.to_sym, c] }]
+ end
+
+ column_cache[table][name]
+ end
+
+ def column_cache
+ @column_cache[@pool]
+ end
+
def visit_Arel_Nodes_Values o
- "VALUES (#{o.expressions.zip(o.columns).map { |value, column|
- quote(value, column && column.column)
+ "VALUES (#{o.expressions.zip(o.columns).map { |value, attr|
+ quote(value, attr && column_for(attr))
}.join ', '})"
end
@@ -87,7 +142,7 @@ module Arel
"SELECT",
(visit(o.top) if o.top),
"#{o.projections.map { |x| visit x }.join ', '}",
- ("FROM #{visit o.froms}" if o.froms),
+ visit(o.source),
("WHERE #{o.wheres.map { |x| visit x }.join ' AND ' }" unless o.wheres.empty?),
("GROUP BY #{o.groups.map { |x| visit x }.join ', ' }" unless o.groups.empty?),
(visit(o.having) if o.having),
@@ -186,16 +241,26 @@ module Arel
"#{visit o.left} NOT LIKE #{visit o.right}"
end
+ def visit_Arel_Nodes_JoinSource o
+ return unless o.left || !o.right.empty?
+
+ [
+ "FROM",
+ (visit(o.left) if o.left),
+ o.right.map { |j| visit j }.join(' ')
+ ].compact.join ' '
+ end
+
def visit_Arel_Nodes_StringJoin o
- "#{visit o.left} #{visit o.right}"
+ visit o.left
end
def visit_Arel_Nodes_OuterJoin o
- "#{visit o.left} LEFT OUTER JOIN #{visit o.right} #{visit o.constraint}"
+ "LEFT OUTER JOIN #{visit o.left} #{visit o.right}"
end
def visit_Arel_Nodes_InnerJoin o
- "#{visit o.left} INNER JOIN #{visit o.right} #{visit o.constraint if o.constraint}"
+ "INNER JOIN #{visit o.left} #{visit o.right if o.right}"
end
def visit_Arel_Nodes_On o
@@ -223,7 +288,7 @@ module Arel
end
def visit_Arel_Nodes_And o
- "#{visit o.left} AND #{visit o.right}"
+ o.children.map { |x| visit x }.join ' AND '
end
def visit_Arel_Nodes_Or o
@@ -231,7 +296,7 @@ module Arel
end
def visit_Arel_Nodes_Assignment o
- right = quote(o.right, o.left.column)
+ right = quote(o.right, column_for(o.left))
"#{visit o.left} = #{right}"
end
@@ -264,7 +329,7 @@ module Arel
end
def visit_Arel_Attributes_Attribute o
- @last_column = o.column
+ @last_column = column_for o
join_name = o.relation.table_alias || o.relation.name
"#{quote_table_name join_name}.#{quote_column_name o.name}"
end
@@ -275,26 +340,29 @@ module Arel
alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
- def visit_Fixnum o; o end
- alias :visit_Arel_Nodes_SqlLiteral :visit_Fixnum
- alias :visit_Arel_SqlLiteral :visit_Fixnum # This is deprecated
- alias :visit_Bignum :visit_Fixnum
-
- def visit_String o; quote(o, @last_column) end
-
- alias :visit_ActiveSupport_Multibyte_Chars :visit_String
- alias :visit_BigDecimal :visit_String
- alias :visit_Date :visit_String
- alias :visit_DateTime :visit_String
- alias :visit_FalseClass :visit_String
- alias :visit_Float :visit_String
- alias :visit_Hash :visit_String
- alias :visit_Symbol :visit_String
- alias :visit_Time :visit_String
- alias :visit_TrueClass :visit_String
- alias :visit_NilClass :visit_String
- alias :visit_ActiveSupport_StringInquirer :visit_String
- alias :visit_Class :visit_String
+ def literal o; o end
+
+ alias :visit_Arel_Nodes_SqlLiteral :literal
+ alias :visit_Arel_SqlLiteral :literal # This is deprecated
+ alias :visit_Bignum :literal
+ alias :visit_Fixnum :literal
+
+ def quoted o; quote(o, @last_column) end
+
+ alias :visit_ActiveSupport_Multibyte_Chars :quoted
+ alias :visit_ActiveSupport_StringInquirer :quoted
+ alias :visit_BigDecimal :quoted
+ alias :visit_Class :quoted
+ alias :visit_Date :quoted
+ alias :visit_DateTime :quoted
+ alias :visit_FalseClass :quoted
+ alias :visit_Float :quoted
+ alias :visit_Hash :quoted
+ alias :visit_NilClass :quoted
+ alias :visit_String :quoted
+ alias :visit_Symbol :quoted
+ alias :visit_Time :quoted
+ alias :visit_TrueClass :quoted
def visit_Array o
o.empty? ? 'NULL' : o.map { |x| visit x }.join(', ')
@@ -309,7 +377,7 @@ module Arel
end
def quote_column_name name
- @quoted_columns[name] ||= @connection.quote_column_name(name)
+ @quoted_columns[name] ||= Arel::Nodes::SqlLiteral === name ? name : @connection.quote_column_name(name)
end
end
end
diff --git a/test/attributes/test_attribute.rb b/test/attributes/test_attribute.rb
index 06954c242b..df7dc69621 100644
--- a/test/attributes/test_attribute.rb
+++ b/test/attributes/test_attribute.rb
@@ -326,7 +326,7 @@ module Arel
describe '#eq' do
it 'should return an equality node' do
- attribute = Attribute.new nil, nil, nil
+ attribute = Attribute.new nil, nil
equality = attribute.eq 1
equality.left.must_equal attribute
equality.right.must_equal 1
@@ -485,7 +485,7 @@ module Arel
end
it 'should return an in node' do
- attribute = Attribute.new nil, nil, nil
+ attribute = Attribute.new nil, nil
node = Nodes::In.new attribute, [1,2,3]
node.left.must_equal attribute
node.right.must_equal [1, 2, 3]
@@ -538,7 +538,7 @@ module Arel
end
it 'should return a NotIn node' do
- attribute = Attribute.new nil, nil, nil
+ attribute = Attribute.new nil, nil
node = Nodes::NotIn.new attribute, [1,2,3]
node.left.must_equal attribute
node.right.must_equal [1, 2, 3]
diff --git a/test/helper.rb b/test/helper.rb
index 3f9ac22447..f13596f9ec 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -8,6 +8,6 @@ Arel::Table.engine = Arel::Sql::Engine.new(FakeRecord::Base.new)
class Object
def must_be_like other
- self.gsub(/\s+/, ' ').strip.must_equal other.gsub(/\s+/, ' ').strip
+ gsub(/\s+/, ' ').strip.must_equal other.gsub(/\s+/, ' ').strip
end
end
diff --git a/test/nodes/test_node.rb b/test/nodes/test_node.rb
index 71d2098a60..ffa3f273ea 100644
--- a/test/nodes/test_node.rb
+++ b/test/nodes/test_node.rb
@@ -2,6 +2,10 @@ require 'helper'
module Arel
class TestNode < MiniTest::Unit::TestCase
+ def test_includes_factory_methods
+ assert Node.new.respond_to?(:create_join)
+ end
+
def test_all_nodes_are_nodes
Nodes.constants.map { |k|
Nodes.const_get(k)
diff --git a/test/test_crud.rb b/test/test_crud.rb
index 582f0ec072..fe3e4f2e02 100644
--- a/test/test_crud.rb
+++ b/test/test_crud.rb
@@ -35,10 +35,8 @@ module Arel
table = Table.new :users
fc = FakeCrudder.new
fc.from table
- fc.insert [[table[:id], 'foo']]
- fc.engine.calls.find { |method, _|
- method == :insert
- }.wont_be_nil
+ im = fc.compile_insert [[table[:id], 'foo']]
+ assert_instance_of Arel::InsertManager, im
end
end
@@ -47,10 +45,8 @@ module Arel
table = Table.new :users
fc = FakeCrudder.new
fc.from table
- fc.update [[table[:id], 'foo']]
- fc.engine.calls.find { |method, _|
- method == :update
- }.wont_be_nil
+ stmt = fc.compile_update [[table[:id], 'foo']]
+ assert_instance_of Arel::UpdateManager, stmt
end
end
@@ -59,10 +55,8 @@ module Arel
table = Table.new :users
fc = FakeCrudder.new
fc.from table
- fc.delete
- fc.engine.calls.find { |method, _|
- method == :delete
- }.wont_be_nil
+ stmt = fc.compile_delete
+ assert_instance_of Arel::DeleteManager, stmt
end
end
end
diff --git a/test/test_factory_methods.rb b/test/test_factory_methods.rb
new file mode 100644
index 0000000000..6506d3c472
--- /dev/null
+++ b/test/test_factory_methods.rb
@@ -0,0 +1,27 @@
+require 'helper'
+
+module Arel
+ module FactoryMethods
+ class TestFactoryMethods < MiniTest::Unit::TestCase
+ class Factory
+ include Arel::FactoryMethods
+ end
+
+ def setup
+ @factory = Factory.new
+ end
+
+ def test_create_join
+ join = @factory.create_join :one, :two
+ assert_kind_of Nodes::Join, join
+ assert_equal :two, join.right
+ end
+
+ def test_create_on
+ on = @factory.create_on :one
+ assert_instance_of Nodes::On, on
+ assert_equal :one, on.expr
+ end
+ end
+ end
+end
diff --git a/test/test_select_manager.rb b/test/test_select_manager.rb
index d63bec0093..271a8ae0b0 100644
--- a/test/test_select_manager.rb
+++ b/test/test_select_manager.rb
@@ -26,6 +26,17 @@ module Arel
def quote_table_name thing; @engine.connection.quote_table_name thing end
def quote_column_name thing; @engine.connection.quote_column_name thing end
def quote thing, column; @engine.connection.quote thing, column end
+ def columns table, message = nil
+ @engine.connection.columns table, message
+ end
+
+ def table_exists? name
+ @engine.connection.table_exists? name
+ end
+
+ def tables
+ @engine.connection.tables
+ end
def execute sql, name = nil, *args
@executed << sql
@@ -36,6 +47,12 @@ module Arel
end
describe 'select manager' do
+ def test_join_sources
+ manager = Arel::SelectManager.new Table.engine
+ manager.join_sources << Arel::Nodes::StringJoin.new('foo')
+ assert_equal "SELECT FROM 'foo'", manager.to_sql
+ end
+
describe 'backwards compatibility' do
describe 'project' do
it 'accepts symbols as sql literals' do
@@ -82,13 +99,28 @@ module Arel
end
end
- describe '#having' do
+ describe 'having' do
it 'converts strings to SQLLiterals' do
table = Table.new :users
mgr = table.from table
mgr.having 'foo'
mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo }
end
+
+ it 'can have multiple items specified separately' do
+ table = Table.new :users
+ mgr = table.from table
+ mgr.having 'foo'
+ mgr.having 'bar'
+ mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo AND bar }
+ end
+
+ it 'can have multiple items specified together' do
+ table = Table.new :users
+ mgr = table.from table
+ mgr.having 'foo', 'bar'
+ mgr.to_sql.must_be_like %{ SELECT FROM "users" HAVING foo AND bar }
+ end
end
end
@@ -266,6 +298,35 @@ module Arel
end
end
+ it 'should hand back froms' do
+ relation = Arel::SelectManager.new Table.engine
+ assert_equal [], relation.froms
+ end
+
+ it 'should create and nodes' do
+ relation = Arel::SelectManager.new Table.engine
+ children = ['foo', 'bar', 'baz']
+ clause = relation.create_and children
+ assert_kind_of Arel::Nodes::And, clause
+ assert_equal children, clause.children
+ end
+
+ it 'should create join nodes' do
+ relation = Arel::SelectManager.new Table.engine
+ join = relation.create_join 'foo', 'bar'
+ assert_kind_of Arel::Nodes::InnerJoin, join
+ assert_equal 'foo', join.left
+ assert_equal 'bar', join.right
+ end
+
+ it 'should create join nodes with a klass' do
+ relation = Arel::SelectManager.new Table.engine
+ join = relation.create_join 'foo', 'bar', Arel::Nodes::OuterJoin
+ assert_kind_of Arel::Nodes::OuterJoin, join
+ assert_equal 'foo', join.left
+ assert_equal 'bar', join.right
+ end
+
describe 'join' do
it 'responds to join' do
left = Table.new :users
@@ -308,30 +369,27 @@ module Arel
table = Table.new :users
aliaz = table.alias
manager = Arel::SelectManager.new Table.engine
- manager.from Nodes::InnerJoin.new(table, aliaz, table[:id].eq(aliaz[:id]))
+ manager.from Nodes::InnerJoin.new(aliaz, table[:id].eq(aliaz[:id]))
manager.join_sql.must_be_like %{
INNER JOIN "users" "users_2" "users"."id" = "users_2"."id"
}
- manager.joins(manager).must_equal manager.join_sql
end
it 'returns outer join sql' do
table = Table.new :users
aliaz = table.alias
manager = Arel::SelectManager.new Table.engine
- manager.from Nodes::OuterJoin.new(table, aliaz, table[:id].eq(aliaz[:id]))
+ manager.from Nodes::OuterJoin.new(aliaz, table[:id].eq(aliaz[:id]))
manager.join_sql.must_be_like %{
LEFT OUTER JOIN "users" "users_2" "users"."id" = "users_2"."id"
}
- manager.joins(manager).must_equal manager.join_sql
end
it 'returns string join sql' do
table = Table.new :users
manager = Arel::SelectManager.new Table.engine
- manager.from Nodes::StringJoin.new(table, 'hello')
+ manager.from Nodes::StringJoin.new('hello')
manager.join_sql.must_be_like %{ 'hello' }
- manager.joins(manager).must_equal manager.join_sql
end
it 'returns nil join sql' do
@@ -393,9 +451,9 @@ module Arel
table = Table.new :users
manager = Arel::SelectManager.new engine
manager.from table
- manager.delete
+ stmt = manager.compile_delete
- engine.executed.last.must_be_like %{ DELETE FROM "users" }
+ stmt.to_sql.must_be_like %{ DELETE FROM "users" }
end
it "copies where" do
@@ -404,9 +462,9 @@ module Arel
manager = Arel::SelectManager.new engine
manager.from table
manager.where table[:id].eq 10
- manager.delete
+ stmt = manager.compile_delete
- engine.executed.last.must_be_like %{
+ stmt.to_sql.must_be_like %{
DELETE FROM "users" WHERE "users"."id" = 10
}
end
@@ -436,9 +494,10 @@ module Arel
manager = Arel::SelectManager.new engine
manager.from table
manager.take 1
- manager.update(SqlLiteral.new('foo = bar'))
+ stmt = manager.compile_update(SqlLiteral.new('foo = bar'))
+ stmt.key = table['id']
- engine.executed.last.must_be_like %{
+ stmt.to_sql.must_be_like %{
UPDATE "users" SET foo = bar
WHERE "users"."id" IN (SELECT "users"."id" FROM "users" LIMIT 1)
}
@@ -450,9 +509,10 @@ module Arel
manager = Arel::SelectManager.new engine
manager.from table
manager.order :foo
- manager.update(SqlLiteral.new('foo = bar'))
+ stmt = manager.compile_update(SqlLiteral.new('foo = bar'))
+ stmt.key = table['id']
- engine.executed.last.must_be_like %{
+ stmt.to_sql.must_be_like %{
UPDATE "users" SET foo = bar
WHERE "users"."id" IN (SELECT "users"."id" FROM "users" ORDER BY foo)
}
@@ -463,9 +523,9 @@ module Arel
table = Table.new :users
manager = Arel::SelectManager.new engine
manager.from table
- manager.update(SqlLiteral.new('foo = bar'))
+ stmt = manager.compile_update(SqlLiteral.new('foo = bar'))
- engine.executed.last.must_be_like %{ UPDATE "users" SET foo = bar }
+ stmt.to_sql.must_be_like %{ UPDATE "users" SET foo = bar }
end
it 'copies where clauses' do
@@ -474,9 +534,9 @@ module Arel
manager = Arel::SelectManager.new engine
manager.where table[:id].eq 10
manager.from table
- manager.update(table[:id] => 1)
+ stmt = manager.compile_update(table[:id] => 1)
- engine.executed.last.must_be_like %{
+ stmt.to_sql.must_be_like %{
UPDATE "users" SET "id" = 1 WHERE "users"."id" = 10
}
end
@@ -486,9 +546,9 @@ module Arel
table = Table.new :users
manager = Arel::SelectManager.new engine
manager.from table
- manager.update(table[:id] => 1)
+ stmt = manager.compile_update(table[:id] => 1)
- engine.executed.last.must_be_like %{
+ stmt.to_sql.must_be_like %{
UPDATE "users" SET "id" = 1
}
end
diff --git a/test/test_table.rb b/test/test_table.rb
index 8d37a8eaff..129d7ba736 100644
--- a/test/test_table.rb
+++ b/test/test_table.rb
@@ -6,6 +6,38 @@ module Arel
@relation = Table.new(:users)
end
+ it 'should create join nodes' do
+ join = @relation.create_string_join 'foo'
+ assert_kind_of Arel::Nodes::StringJoin, join
+ assert_equal 'foo', join.left
+ end
+
+ it 'should create join nodes' do
+ join = @relation.create_join 'foo', 'bar'
+ assert_kind_of Arel::Nodes::InnerJoin, join
+ assert_equal 'foo', join.left
+ assert_equal 'bar', join.right
+ end
+
+ it 'should create join nodes with a klass' do
+ join = @relation.create_join 'foo', 'bar', Arel::Nodes::OuterJoin
+ assert_kind_of Arel::Nodes::OuterJoin, join
+ assert_equal 'foo', join.left
+ assert_equal 'bar', join.right
+ end
+
+ it 'should return an insert manager' do
+ im = @relation.compile_insert 'VALUES(NULL)'
+ assert_kind_of Arel::InsertManager, im
+ assert_equal 'INSERT INTO NULL VALUES(NULL)', im.to_sql
+ end
+
+ it 'should return IM from insert_manager' do
+ im = @relation.insert_manager
+ assert_kind_of Arel::InsertManager, im
+ assert_equal im.engine, @relation.engine
+ end
+
describe 'skip' do
it 'should add an offset' do
sm = @relation.skip 2
@@ -13,12 +45,6 @@ module Arel
end
end
- describe 'primary_key' do
- it 'should return an attribute' do
- @relation.primary_key.name.must_equal :id
- end
- end
-
describe 'select_manager' do
it 'should return an empty select manager' do
sm = @relation.select_manager
@@ -36,12 +62,6 @@ module Arel
end
describe 'backwards compat' do
- describe 'joins' do
- it 'returns nil' do
- @relation.joins(nil).must_equal nil
- end
- end
-
describe 'join' do
it 'noops on nil' do
mgr = @relation.join nil
@@ -84,13 +104,6 @@ module Arel
end
describe 'new' do
- it 'takes :columns' do
- columns = Table.engine.connection.columns("users")
- @relation = Table.new(:users, :columns => columns)
- @relation.columns.first.name.must_equal :id
- @relation.engine.must_equal Table.engine
- end
-
it 'should accept an engine' do
rel = Table.new :users, 'foo'
rel.engine.must_equal 'foo'
@@ -147,14 +160,6 @@ module Arel
end
end
- describe 'columns' do
- it 'returns a list of columns' do
- columns = @relation.columns
- columns.length.must_equal 4
- columns.map { |x| x.name.to_s }.sort.must_equal %w{ created_at bool name id }.sort
- end
- end
-
it "should have a name" do
@relation.name.must_equal 'users'
end
@@ -168,24 +173,6 @@ module Arel
it "manufactures an attribute if the symbol names an attribute within the relation" do
column = @relation[:id]
column.name.must_equal :id
- column.must_be_kind_of Attributes::Integer
- end
- end
-
- describe 'when table does not exist' do
- it 'returns nil' do
- @relation[:foooo].must_be_nil
- end
- end
- end
- end
-
- describe Table do
- describe 'when checking the existence of a table' do
- it 'should be present in the table cache despite the class of its name' do
- [ 'users', :users ].each do |name|
- relation = Table.new name
- Table.table_cache(relation.engine).key?(relation.name).must_equal true
end
end
end
diff --git a/test/visitors/test_depth_first.rb b/test/visitors/test_depth_first.rb
index 1bee0328cf..306605b7c6 100644
--- a/test/visitors/test_depth_first.rb
+++ b/test/visitors/test_depth_first.rb
@@ -29,7 +29,10 @@ module Arel
Arel::Nodes::Grouping,
Arel::Nodes::Offset,
Arel::Nodes::Having,
+ Arel::Nodes::StringJoin,
Arel::Nodes::UnqualifiedColumn,
+ Arel::Nodes::Top,
+ Arel::Nodes::Limit,
].each do |klass|
define_method("test_#{klass.name.gsub('::', '_')}") do
op = klass.new(:a)
@@ -66,19 +69,18 @@ module Arel
end
def test_inner_join
- join = Nodes::InnerJoin.new :a, :b, :c
+ join = Nodes::InnerJoin.new :a, :b
@visitor.accept join
- assert_equal [:a, :b, :c, join], @collector.calls
+ assert_equal [:a, :b, join], @collector.calls
end
def test_outer_join
- join = Nodes::OuterJoin.new :a, :b, :c
+ join = Nodes::OuterJoin.new :a, :b
@visitor.accept join
- assert_equal [:a, :b, :c, join], @collector.calls
+ assert_equal [:a, :b, join], @collector.calls
end
[
- Arel::Nodes::And,
Arel::Nodes::Assignment,
Arel::Nodes::Between,
Arel::Nodes::DoesNotMatch,
@@ -92,12 +94,12 @@ module Arel
Arel::Nodes::NotEqual,
Arel::Nodes::NotIn,
Arel::Nodes::Or,
- Arel::Nodes::StringJoin,
Arel::Nodes::TableAlias,
Arel::Nodes::Values,
Arel::Nodes::As,
Arel::Nodes::DeleteStatement,
Arel::Nodes::Ordering,
+ Arel::Nodes::JoinSource,
].each do |klass|
define_method("test_#{klass.name.gsub('::', '_')}") do
binary = klass.new(:a, :b)
@@ -106,6 +108,17 @@ module Arel
end
end
+ # N-ary
+ [
+ Arel::Nodes::And,
+ ].each do |klass|
+ define_method("test_#{klass.name.gsub('::', '_')}") do
+ binary = klass.new([:a, :b, :c])
+ @visitor.accept binary
+ assert_equal [:a, :b, :c, binary], @collector.calls
+ end
+ end
+
[
Arel::Attributes::Integer,
Arel::Attributes::Float,
@@ -165,7 +178,8 @@ module Arel
@visitor.accept core
assert_equal [
:a, core.projections,
- :b,
+ :b, [],
+ core.source,
:c, core.wheres,
:d, core.groups,
:e,
diff --git a/test/visitors/test_dot.rb b/test/visitors/test_dot.rb
index 19a554ce42..3c7da8958a 100644
--- a/test/visitors/test_dot.rb
+++ b/test/visitors/test_dot.rb
@@ -16,12 +16,42 @@ module Arel
Arel::Nodes::Offset,
Arel::Nodes::Having,
Arel::Nodes::UnqualifiedColumn,
+ Arel::Nodes::Top,
+ Arel::Nodes::Limit,
].each do |klass|
define_method("test_#{klass.name.gsub('::', '_')}") do
op = klass.new(:a)
@visitor.accept op
end
end
+
+ # binary ops
+ [
+ Arel::Nodes::Assignment,
+ Arel::Nodes::Between,
+ Arel::Nodes::DoesNotMatch,
+ Arel::Nodes::Equality,
+ Arel::Nodes::GreaterThan,
+ Arel::Nodes::GreaterThanOrEqual,
+ Arel::Nodes::In,
+ Arel::Nodes::LessThan,
+ Arel::Nodes::LessThanOrEqual,
+ Arel::Nodes::Matches,
+ Arel::Nodes::NotEqual,
+ Arel::Nodes::NotIn,
+ Arel::Nodes::Or,
+ Arel::Nodes::TableAlias,
+ Arel::Nodes::Values,
+ Arel::Nodes::As,
+ Arel::Nodes::DeleteStatement,
+ Arel::Nodes::Ordering,
+ Arel::Nodes::JoinSource,
+ ].each do |klass|
+ define_method("test_#{klass.name.gsub('::', '_')}") do
+ binary = klass.new(:a, :b)
+ @visitor.accept binary
+ end
+ end
end
end
end
diff --git a/test/visitors/test_join_sql.rb b/test/visitors/test_join_sql.rb
index 8253fe5ab4..b672f88ecf 100644
--- a/test/visitors/test_join_sql.rb
+++ b/test/visitors/test_join_sql.rb
@@ -4,15 +4,21 @@ module Arel
module Visitors
describe 'the join_sql visitor' do
before do
- @visitor = JoinSql.new Table.engine
+ @visitor = ToSql.new Table.engine
+ @visitor.extend(JoinSql)
+ end
+
+ it 'should visit string join' do
+ sql = @visitor.accept Nodes::StringJoin.new('omg')
+ sql.must_be_like "'omg'"
end
describe 'inner join' do
it 'should visit left if left is a join' do
t = Table.new :users
- join = Nodes::InnerJoin.new t, t, Nodes::On.new(t[:id])
- j2 = Nodes::InnerJoin.new join, t, Nodes::On.new(t[:id])
- @visitor.accept(j2).must_be_like %{
+ sm = t.select_manager
+ sm.join(t).on(t[:id]).join(t).on(t[:id])
+ sm.join_sql.must_be_like %{
INNER JOIN "users" ON "users"."id"
INNER JOIN "users" ON "users"."id"
}
@@ -22,9 +28,10 @@ module Arel
describe 'outer join' do
it 'should visit left if left is a join' do
t = Table.new :users
- join = Nodes::OuterJoin.new t, t, Nodes::On.new(t[:id])
- j2 = Nodes::OuterJoin.new join, t, Nodes::On.new(t[:id])
- @visitor.accept(j2).must_be_like %{
+ sm = t.select_manager
+ sm.join(t, Nodes::OuterJoin).on(t[:id]).join(
+ t, Nodes::OuterJoin).on(t[:id])
+ sm.join_sql.must_be_like %{
LEFT OUTER JOIN "users" ON "users"."id"
LEFT OUTER JOIN "users" ON "users"."id"
}
diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb
index 33783f7d23..34ebb2b278 100644
--- a/test/visitors/test_to_sql.rb
+++ b/test/visitors/test_to_sql.rb
@@ -5,7 +5,14 @@ module Arel
describe 'the to_sql visitor' do
before do
@visitor = ToSql.new Table.engine
- @attr = Table.new(:users)[:id]
+ @table = Table.new(:users)
+ @attr = @table[:id]
+ end
+
+ it 'should not quote sql literals' do
+ node = @table[Arel.star]
+ sql = @visitor.accept node
+ sql.must_be_like '"users".*'
end
describe 'equality' do
@@ -50,7 +57,7 @@ module Arel
end
it "should apply Not to the whole expression" do
- node = Nodes::And.new @attr.eq(10), @attr.eq(11)
+ node = Nodes::And.new [@attr.eq(10), @attr.eq(11)]
sql = @visitor.accept Nodes::Not.new(node)
sql.must_be_like %{NOT ("users"."id" = 10 AND "users"."id" = 11)}
end
@@ -82,7 +89,7 @@ module Arel
end
it "should visit_Arel_Nodes_And" do
- node = Nodes::And.new @attr.eq(10), @attr.eq(11)
+ node = Nodes::And.new [@attr.eq(10), @attr.eq(11)]
@visitor.accept(node).must_be_like %{
"users"."id" = 10 AND "users"."id" = 11
}
@@ -96,7 +103,7 @@ module Arel
end
it "should visit visit_Arel_Attributes_Time" do
- attr = Attributes::Time.new(@attr.relation, @attr.name, @attr.column)
+ attr = Attributes::Time.new(@attr.relation, @attr.name)
@visitor.accept attr
end
@@ -164,7 +171,9 @@ module Arel
end
in_node = Nodes::In.new @attr, %w{ a b c }
visitor = visitor.new(Table.engine)
- visitor.expected = @attr.column
+ visitor.expected = Table.engine.connection.columns(:users).find { |x|
+ x.name == 'name'
+ }
visitor.accept(in_node).must_equal %("users"."name" IN ('a', 'b', 'c'))
end
end
@@ -219,7 +228,9 @@ module Arel
end
in_node = Nodes::NotIn.new @attr, %w{ a b c }
visitor = visitor.new(Table.engine)
- visitor.expected = @attr.column
+ visitor.expected = Table.engine.connection.columns(:users).find { |x|
+ x.name == 'name'
+ }
visitor.accept(in_node).must_equal %("users"."name" NOT IN ('a', 'b', 'c'))
end
end