arel 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,21 @@
1
+ == 2.0.5 11/30/2010
2
+
3
+ * Enhancements
4
+
5
+ * Arel::Visitors::DepthFirst can walk your AST depth first
6
+ * Arel::Nodes::Node is enumerable, depth first
7
+
8
+ * Bug fixes
9
+
10
+ * #lock will lock SELECT statements "FOR UPDATE" on mysql
11
+ * Nodes::Node#not factory method added for creating Nodes::Not nodes
12
+ * Added an As node
13
+
14
+ * Deprecations
15
+
16
+ * Support for Subclasses of core classes will be removed in ARel version
17
+ 2.2.0
18
+
1
19
  == 2.0.4
2
20
 
3
21
  * Bug fixes
@@ -17,6 +17,7 @@ lib/arel/expressions.rb
17
17
  lib/arel/insert_manager.rb
18
18
  lib/arel/nodes.rb
19
19
  lib/arel/nodes/and.rb
20
+ lib/arel/nodes/as.rb
20
21
  lib/arel/nodes/assignment.rb
21
22
  lib/arel/nodes/avg.rb
22
23
  lib/arel/nodes/between.rb
@@ -43,6 +44,7 @@ lib/arel/nodes/matches.rb
43
44
  lib/arel/nodes/max.rb
44
45
  lib/arel/nodes/min.rb
45
46
  lib/arel/nodes/node.rb
47
+ lib/arel/nodes/not.rb
46
48
  lib/arel/nodes/not_equal.rb
47
49
  lib/arel/nodes/not_in.rb
48
50
  lib/arel/nodes/offset.rb
@@ -56,6 +58,7 @@ lib/arel/nodes/sql_literal.rb
56
58
  lib/arel/nodes/string_join.rb
57
59
  lib/arel/nodes/sum.rb
58
60
  lib/arel/nodes/table_alias.rb
61
+ lib/arel/nodes/unary.rb
59
62
  lib/arel/nodes/unqualified_column.rb
60
63
  lib/arel/nodes/update_statement.rb
61
64
  lib/arel/nodes/values.rb
@@ -68,6 +71,7 @@ lib/arel/table.rb
68
71
  lib/arel/tree_manager.rb
69
72
  lib/arel/update_manager.rb
70
73
  lib/arel/visitors.rb
74
+ lib/arel/visitors/depth_first.rb
71
75
  lib/arel/visitors/dot.rb
72
76
  lib/arel/visitors/join_sql.rb
73
77
  lib/arel/visitors/mysql.rb
@@ -80,10 +84,13 @@ lib/arel/visitors/visitor.rb
80
84
  lib/arel/visitors/where_sql.rb
81
85
  test/attributes/test_attribute.rb
82
86
  test/helper.rb
87
+ test/nodes/test_as.rb
83
88
  test/nodes/test_count.rb
84
89
  test/nodes/test_delete_statement.rb
85
90
  test/nodes/test_equality.rb
86
91
  test/nodes/test_insert_statement.rb
92
+ test/nodes/test_node.rb
93
+ test/nodes/test_not.rb
87
94
  test/nodes/test_or.rb
88
95
  test/nodes/test_select_core.rb
89
96
  test/nodes/test_select_statement.rb
@@ -99,6 +106,7 @@ test/test_insert_manager.rb
99
106
  test/test_select_manager.rb
100
107
  test/test_table.rb
101
108
  test/test_update_manager.rb
109
+ test/visitors/test_depth_first.rb
102
110
  test/visitors/test_join_sql.rb
103
111
  test/visitors/test_mysql.rb
104
112
  test/visitors/test_oracle.rb
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require "rubygems"
2
2
  gem 'hoe', '>= 2.1.0'
3
3
  require 'hoe'
4
4
 
5
+ Hoe.plugins.delete :rubyforge
5
6
  Hoe.plugin :minitest
6
7
  Hoe.plugin :gemspec # `gem install hoe-gemspec`
7
8
  Hoe.plugin :git # `gem install hoe-git`
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{arel}
5
- s.version = "2.0.2.20101111111102"
5
+ s.version = "2.0.4.20101119081136"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Aaron Patterson", "Bryan Halmkamp", "Emilio Tagua", "Nick Kallen"]
9
- s.date = %q{2010-11-11}
9
+ s.date = %q{2010-11-19}
10
10
  s.description = %q{Arel is a Relational Algebra for Ruby. It 1) simplifies the generation complex of SQL queries and it 2) adapts to various RDBMS systems. It is intended to be a framework framework; that is, you can build your own ORM with it, focusing on innovative object and collection modeling as opposed to database compatibility and query generation.}
11
11
  s.email = ["aaron@tenderlovemaking.com", "bryan@brynary.com", "miloops@gmail.com", "nick@example.org"]
12
12
  s.extra_rdoc_files = ["History.txt", "MIT-LICENSE.txt", "Manifest.txt", "README.markdown"]
@@ -21,6 +21,7 @@ require 'arel/update_manager'
21
21
  require 'arel/delete_manager'
22
22
  require 'arel/nodes'
23
23
 
24
+
24
25
  #### these are deprecated
25
26
  require 'arel/deprecated'
26
27
  require 'arel/sql/engine'
@@ -28,9 +29,11 @@ require 'arel/sql_literal'
28
29
  ####
29
30
 
30
31
  module Arel
31
- VERSION = '2.0.4'
32
+ VERSION = '2.0.5'
32
33
 
33
34
  def self.sql raw_sql
34
35
  Arel::Nodes::SqlLiteral.new raw_sql
35
36
  end
37
+ ## Convenience Alias
38
+ Node = Arel::Nodes::Node
36
39
  end
@@ -1,4 +1,5 @@
1
1
  require 'arel/nodes/node'
2
+ require 'arel/nodes/unary'
2
3
  require 'arel/nodes/binary'
3
4
  require 'arel/nodes/equality'
4
5
  require 'arel/nodes/between'
@@ -6,6 +7,8 @@ require 'arel/nodes/not_equal'
6
7
  require 'arel/nodes/assignment'
7
8
  require 'arel/nodes/or'
8
9
  require 'arel/nodes/and'
10
+ require 'arel/nodes/as'
11
+ require 'arel/nodes/not'
9
12
  require 'arel/nodes/greater_than'
10
13
  require 'arel/nodes/greater_than_or_equal'
11
14
  require 'arel/nodes/less_than'
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module Nodes
3
+ class As < Arel::Nodes::Binary
4
+ end
5
+ end
6
+ end
@@ -1,16 +1,18 @@
1
1
  module Arel
2
2
  module Nodes
3
- class DeleteStatement
4
- attr_accessor :relation, :wheres
3
+ class DeleteStatement < Arel::Nodes::Binary
4
+ alias :relation :left
5
+ alias :relation= :left=
6
+ alias :wheres :right
7
+ alias :wheres= :right=
5
8
 
6
- def initialize
7
- @from = nil
8
- @wheres = []
9
+ def initialize relation = nil, wheres = []
10
+ super
9
11
  end
10
12
 
11
13
  def initialize_copy other
12
14
  super
13
- @wheres = @wheres.clone
15
+ @right = @right.clone
14
16
  end
15
17
  end
16
18
  end
@@ -1,11 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Group
4
- attr_accessor :expr
5
-
6
- def initialize expr
7
- @expr = expr
8
- end
3
+ class Group < Arel::Nodes::Unary
9
4
  end
10
5
  end
11
6
  end
@@ -1,11 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Grouping < Arel::Nodes::Node
4
- attr_accessor :expr
5
-
6
- def initialize expression
7
- @expr = expression
8
- end
3
+ class Grouping < Arel::Nodes::Unary
9
4
  end
10
5
  end
11
6
  end
@@ -1,11 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Having
4
- attr_accessor :expr
5
-
6
- def initialize expr
7
- @expr = expr
8
- end
3
+ class Having < Arel::Nodes::Unary
9
4
  end
10
5
  end
11
6
  end
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class InsertStatement
3
+ class InsertStatement < Arel::Nodes::Node
4
4
  attr_accessor :relation, :columns, :values
5
5
 
6
6
  def initialize
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Join
3
+ class Join < Arel::Nodes::Node
4
4
  attr_accessor :left, :right, :constraint
5
5
 
6
6
  def initialize left, right, constraint
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Lock
3
+ class Lock < Arel::Nodes::Node
4
4
  end
5
5
  end
6
6
  end
@@ -3,6 +3,15 @@ module Arel
3
3
  ###
4
4
  # Abstract base class for all AST nodes
5
5
  class Node
6
+ include Enumerable
7
+
8
+ ###
9
+ # Factory method to create a Nodes::Not node that has the recipient of
10
+ # the caller as a child.
11
+ def not
12
+ Nodes::Not.new self
13
+ end
14
+
6
15
  ###
7
16
  # Factory method to create a Nodes::Grouping node that has an Nodes::Or
8
17
  # node as a child.
@@ -25,6 +34,13 @@ module Arel
25
34
  viz = Visitors.for engine
26
35
  viz.accept self
27
36
  end
37
+
38
+ # Iterate through AST, nodes will be yielded depth-first
39
+ def each &block
40
+ return enum_for(:each) unless block_given?
41
+
42
+ Visitors::DepthFirst.new(block).accept self
43
+ end
28
44
  end
29
45
  end
30
46
  end
@@ -0,0 +1,6 @@
1
+ module Arel
2
+ module Nodes
3
+ class Not < Arel::Nodes::Unary
4
+ end
5
+ end
6
+ end
@@ -1,11 +1,7 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Offset
4
- attr_accessor :value
5
-
6
- def initialize value
7
- @value = value
8
- end
3
+ class Offset < Arel::Nodes::Unary
4
+ alias :value :expr
9
5
  end
10
6
  end
11
7
  end
@@ -1,11 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class On
4
- attr_accessor :expr
5
-
6
- def initialize expr
7
- @expr = expr
8
- end
3
+ class On < Arel::Nodes::Unary
9
4
  end
10
5
  end
11
6
  end
@@ -1,10 +1,11 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Ordering < Arel::Nodes::Node
4
- attr_accessor :expr, :direction
3
+ class Ordering < Arel::Nodes::Binary
4
+ alias :expr :left
5
+ alias :direction :right
5
6
 
6
- def initialize expression, direction = :asc
7
- @expr, @direction = expression, direction
7
+ def initialize expr, direction = :asc
8
+ super
8
9
  end
9
10
 
10
11
  def ascending?
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class SelectCore
3
+ class SelectCore < Arel::Nodes::Node
4
4
  attr_accessor :froms, :projections, :wheres, :groups
5
5
  attr_accessor :having
6
6
 
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class SelectStatement
3
+ class SelectStatement < Arel::Nodes::Node
4
4
  attr_reader :cores
5
5
  attr_accessor :limit, :orders, :lock, :offset
6
6
 
@@ -1,20 +1,12 @@
1
1
  module Arel
2
2
  module Nodes
3
- class TableAlias
4
- attr_reader :name, :relation, :columns
3
+ class TableAlias < Arel::Nodes::Binary
4
+ alias :name :left
5
+ alias :relation :right
5
6
  alias :table_alias :name
6
7
 
7
- def initialize name, relation
8
- @name = name
9
- @relation = relation
10
- @columns = relation.columns.map { |column|
11
- column.dup.tap { |col| col.relation = self }
12
- }
13
- end
14
-
15
8
  def [] name
16
- name = name.to_sym
17
- columns.find { |column| column.name == name }
9
+ Attribute.new self, name
18
10
  end
19
11
  end
20
12
  end
@@ -0,0 +1,11 @@
1
+ module Arel
2
+ module Nodes
3
+ class Unary < Arel::Nodes::Node
4
+ attr_accessor :expr
5
+
6
+ def initialize expr
7
+ @expr = expr
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,18 +1,15 @@
1
1
  module Arel
2
2
  module Nodes
3
- class UnqualifiedColumn
4
- attr_accessor :attribute
5
-
6
- def initialize attribute
7
- @attribute = attribute
8
- end
3
+ class UnqualifiedColumn < Arel::Nodes::Unary
4
+ alias :attribute :expr
5
+ alias :attribute= :expr=
9
6
 
10
7
  def column
11
- @attribute.column
8
+ @expr.column
12
9
  end
13
10
 
14
11
  def name
15
- @attribute.name
12
+ @expr.name
16
13
  end
17
14
  end
18
15
  end
@@ -1,6 +1,6 @@
1
1
  module Arel
2
2
  module Nodes
3
- class UpdateStatement
3
+ class UpdateStatement < Arel::Nodes::Node
4
4
  attr_accessor :relation, :wheres, :values, :orders, :limit
5
5
 
6
6
  def initialize
@@ -1,11 +1,13 @@
1
1
  module Arel
2
2
  module Nodes
3
- class Values
4
- attr_accessor :expressions, :columns
3
+ class Values < Arel::Nodes::Binary
4
+ alias :expressions :left
5
+ alias :expressions= :left=
6
+ alias :columns :right
7
+ alias :columns= :right=
5
8
 
6
9
  def initialize exprs, columns = []
7
- @expressions = exprs
8
- @columns = columns
10
+ super
9
11
  end
10
12
  end
11
13
  end
@@ -1,5 +1,9 @@
1
1
  module Arel
2
2
  module Predications
3
+ def as other
4
+ Nodes::As.new self, other
5
+ end
6
+
3
7
  def not_eq other
4
8
  Nodes::NotEqual.new self, other
5
9
  end
@@ -174,4 +178,4 @@ module Arel
174
178
  }
175
179
  end
176
180
  end
177
- end
181
+ end
@@ -34,8 +34,8 @@ module Arel
34
34
  end
35
35
  end
36
36
 
37
- def alias
38
- Nodes::TableAlias.new("#{name}_2", self).tap do |node|
37
+ def alias name = "#{self.name}_2"
38
+ Nodes::TableAlias.new(name, self).tap do |node|
39
39
  @aliases << node
40
40
  end
41
41
  end
@@ -1,4 +1,5 @@
1
1
  require 'arel/visitors/visitor'
2
+ require 'arel/visitors/depth_first'
2
3
  require 'arel/visitors/to_sql'
3
4
  require 'arel/visitors/sqlite'
4
5
  require 'arel/visitors/postgresql'
@@ -0,0 +1,152 @@
1
+ module Arel
2
+ module Visitors
3
+ class DepthFirst < Arel::Visitors::Visitor
4
+ def initialize block = nil
5
+ @block = block || Proc.new
6
+ end
7
+
8
+ private
9
+
10
+ def visit o
11
+ super
12
+ @block.call o
13
+ end
14
+
15
+ def unary o
16
+ visit o.expr
17
+ end
18
+ alias :visit_Arel_Nodes_Group :unary
19
+ alias :visit_Arel_Nodes_Grouping :unary
20
+ alias :visit_Arel_Nodes_Having :unary
21
+ alias :visit_Arel_Nodes_Not :unary
22
+ alias :visit_Arel_Nodes_Offset :unary
23
+ alias :visit_Arel_Nodes_On :unary
24
+ alias :visit_Arel_Nodes_UnqualifiedColumn :unary
25
+
26
+ def function o
27
+ visit o.expressions
28
+ visit o.alias
29
+ end
30
+ alias :visit_Arel_Nodes_Avg :function
31
+ alias :visit_Arel_Nodes_Exists :function
32
+ alias :visit_Arel_Nodes_Max :function
33
+ alias :visit_Arel_Nodes_Min :function
34
+ alias :visit_Arel_Nodes_Sum :function
35
+
36
+ def visit_Arel_Nodes_Count o
37
+ visit o.expressions
38
+ visit o.alias
39
+ visit o.distinct
40
+ end
41
+
42
+ def join o
43
+ visit o.left
44
+ visit o.right
45
+ visit o.constraint
46
+ end
47
+ alias :visit_Arel_Nodes_InnerJoin :join
48
+ alias :visit_Arel_Nodes_OuterJoin :join
49
+
50
+ def binary o
51
+ visit o.left
52
+ visit o.right
53
+ end
54
+ alias :visit_Arel_Nodes_And :binary
55
+ alias :visit_Arel_Nodes_As :binary
56
+ alias :visit_Arel_Nodes_Assignment :binary
57
+ alias :visit_Arel_Nodes_Between :binary
58
+ alias :visit_Arel_Nodes_DeleteStatement :binary
59
+ alias :visit_Arel_Nodes_DoesNotMatch :binary
60
+ alias :visit_Arel_Nodes_Equality :binary
61
+ alias :visit_Arel_Nodes_GreaterThan :binary
62
+ alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
63
+ alias :visit_Arel_Nodes_In :binary
64
+ alias :visit_Arel_Nodes_LessThan :binary
65
+ alias :visit_Arel_Nodes_LessThanOrEqual :binary
66
+ alias :visit_Arel_Nodes_Matches :binary
67
+ alias :visit_Arel_Nodes_NotEqual :binary
68
+ alias :visit_Arel_Nodes_NotIn :binary
69
+ alias :visit_Arel_Nodes_Or :binary
70
+ alias :visit_Arel_Nodes_Ordering :binary
71
+ alias :visit_Arel_Nodes_StringJoin :binary
72
+ alias :visit_Arel_Nodes_TableAlias :binary
73
+ alias :visit_Arel_Nodes_Values :binary
74
+
75
+ def visit_Arel_Attribute o
76
+ visit o.relation
77
+ visit o.name
78
+ end
79
+ alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
80
+ alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
81
+ alias :visit_Arel_Attributes_String :visit_Arel_Attribute
82
+ alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
83
+ alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
84
+ alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
85
+ alias :visit_Arel_Attributes_Decimal :visit_Arel_Attribute
86
+
87
+ def visit_Arel_Table o
88
+ visit o.name
89
+ end
90
+
91
+ def terminal o
92
+ end
93
+ alias :visit_ActiveSupport_Multibyte_Chars :terminal
94
+ alias :visit_ActiveSupport_StringInquirer :terminal
95
+ alias :visit_Arel_Nodes_Lock :terminal
96
+ alias :visit_Arel_Nodes_Node :terminal
97
+ alias :visit_Arel_Nodes_SqlLiteral :terminal
98
+ alias :visit_Arel_SqlLiteral :terminal
99
+ alias :visit_BigDecimal :terminal
100
+ alias :visit_Bignum :terminal
101
+ alias :visit_Class :terminal
102
+ alias :visit_Date :terminal
103
+ alias :visit_DateTime :terminal
104
+ alias :visit_FalseClass :terminal
105
+ alias :visit_Fixnum :terminal
106
+ alias :visit_Float :terminal
107
+ alias :visit_NilClass :terminal
108
+ alias :visit_String :terminal
109
+ alias :visit_Symbol :terminal
110
+ alias :visit_Time :terminal
111
+ alias :visit_TrueClass :terminal
112
+
113
+ def visit_Arel_Nodes_InsertStatement o
114
+ visit o.relation
115
+ visit o.columns
116
+ visit o.values
117
+ end
118
+
119
+ def visit_Arel_Nodes_SelectCore o
120
+ visit o.projections
121
+ visit o.froms
122
+ visit o.wheres
123
+ visit o.groups
124
+ visit o.having
125
+ end
126
+
127
+ def visit_Arel_Nodes_SelectStatement o
128
+ visit o.cores
129
+ visit o.orders
130
+ visit o.limit
131
+ visit o.lock
132
+ visit o.offset
133
+ end
134
+
135
+ def visit_Arel_Nodes_UpdateStatement o
136
+ visit o.relation
137
+ visit o.values
138
+ visit o.wheres
139
+ visit o.orders
140
+ visit o.limit
141
+ end
142
+
143
+ def visit_Array o
144
+ o.each { |i| visit i }
145
+ end
146
+
147
+ def visit_Hash o
148
+ o.each { |k,v| visit(k); visit(v) }
149
+ end
150
+ end
151
+ end
152
+ end
@@ -2,6 +2,10 @@ module Arel
2
2
  module Visitors
3
3
  class MySQL < Arel::Visitors::ToSql
4
4
  private
5
+ def visit_Arel_Nodes_Lock o
6
+ "FOR UPDATE"
7
+ end
8
+
5
9
  ###
6
10
  # :'(
7
11
  # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
@@ -97,7 +97,7 @@ module Arel
97
97
  end
98
98
 
99
99
  def visit_Arel_Nodes_Offset o
100
- "OFFSET #{visit o.value}"
100
+ "OFFSET #{visit o.expr}"
101
101
  end
102
102
 
103
103
  # FIXME: this does nothing on SQLLite3, but should do things on other
@@ -191,6 +191,10 @@ module Arel
191
191
  "ON #{visit o.expr}"
192
192
  end
193
193
 
194
+ def visit_Arel_Nodes_Not o
195
+ "NOT #{visit o.expr}"
196
+ end
197
+
194
198
  def visit_Arel_Table o
195
199
  if o.table_alias
196
200
  "#{quote_table_name o.name} #{quote_table_name o.table_alias}"
@@ -246,6 +250,10 @@ module Arel
246
250
  end
247
251
  end
248
252
 
253
+ def visit_Arel_Nodes_As o
254
+ "#{visit o.left} AS #{visit o.right}"
255
+ end
256
+
249
257
  def visit_Arel_Nodes_UnqualifiedColumn o
250
258
  "#{quote_column_name o.name}"
251
259
  end
@@ -8,11 +8,18 @@ module Arel
8
8
  private
9
9
 
10
10
  DISPATCH = Hash.new do |hash, klass|
11
- hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
11
+ hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}"
12
12
  end
13
13
 
14
14
  def visit object
15
15
  send DISPATCH[object.class], object
16
+ rescue NoMethodError
17
+ warn "visiting #{object.class} via superclass, this will be removed in arel 2.2.0" if $VERBOSE
18
+ superklass = object.class.ancestors.find { |klass|
19
+ respond_to?(DISPATCH[klass], true)
20
+ }
21
+ DISPATCH[object.class] = DISPATCH[superklass]
22
+ retry
16
23
  end
17
24
  end
18
25
  end
@@ -0,0 +1,16 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'As' do
6
+ describe '#as' do
7
+ it 'makes an AS node' do
8
+ attr = Table.new(:users)[:id]
9
+ as = attr.as(Arel.sql('foo'))
10
+ assert_equal attr, as.left
11
+ assert_equal 'foo', as.right
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ class TestNode < MiniTest::Unit::TestCase
5
+ def test_all_nodes_are_nodes
6
+ Nodes.constants.map { |k|
7
+ Nodes.const_get(k)
8
+ }.grep(Class).each do |klass|
9
+ next if Nodes::SqlLiteral == klass
10
+ assert klass.ancestors.include?(Nodes::Node), klass.name
11
+ end
12
+ end
13
+
14
+ def test_each
15
+ list = []
16
+ node = Nodes::Node.new
17
+ node.each { |n| list << n }
18
+ assert_equal [node], list
19
+ end
20
+
21
+ def test_generator
22
+ list = []
23
+ node = Nodes::Node.new
24
+ node.each.each { |n| list << n }
25
+ assert_equal [node], list
26
+ end
27
+
28
+ def test_enumerable
29
+ node = Nodes::Node.new
30
+ assert_kind_of Enumerable, node
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+ describe 'not' do
6
+ describe '#not' do
7
+ it 'makes a NOT node' do
8
+ attr = Table.new(:users)[:id]
9
+ left = attr.eq(10)
10
+ right = attr.eq(11)
11
+ node = left.or right
12
+ node.expr.left.must_equal left
13
+ node.expr.right.must_equal right
14
+
15
+ node.or(right).not
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,203 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Visitors
5
+ class TestDepthFirst < MiniTest::Unit::TestCase
6
+ Collector = Struct.new(:calls) do
7
+ def call object
8
+ calls << object
9
+ end
10
+ end
11
+
12
+ def setup
13
+ @collector = Collector.new []
14
+ @visitor = Visitors::DepthFirst.new @collector
15
+ end
16
+
17
+ # unary ops
18
+ [
19
+ Arel::Nodes::Not,
20
+ Arel::Nodes::Group,
21
+ Arel::Nodes::On,
22
+ Arel::Nodes::Grouping,
23
+ Arel::Nodes::Offset,
24
+ Arel::Nodes::Having,
25
+ Arel::Nodes::UnqualifiedColumn,
26
+ ].each do |klass|
27
+ define_method("test_#{klass.name.gsub('::', '_')}") do
28
+ op = klass.new(:a)
29
+ @visitor.accept op
30
+ assert_equal [:a, op], @collector.calls
31
+ end
32
+ end
33
+
34
+ # functions
35
+ [
36
+ Arel::Nodes::Exists,
37
+ Arel::Nodes::Avg,
38
+ Arel::Nodes::Min,
39
+ Arel::Nodes::Max,
40
+ Arel::Nodes::Sum,
41
+ ].each do |klass|
42
+ define_method("test_#{klass.name.gsub('::', '_')}") do
43
+ func = klass.new(:a, :b)
44
+ @visitor.accept func
45
+ assert_equal [:a, :b, func], @collector.calls
46
+ end
47
+ end
48
+
49
+ def test_lock
50
+ lock = Nodes::Lock.new
51
+ @visitor.accept lock
52
+ assert_equal [lock], @collector.calls
53
+ end
54
+
55
+ def test_count
56
+ count = Nodes::Count.new :a, :b, :c
57
+ @visitor.accept count
58
+ assert_equal [:a, :c, :b, count], @collector.calls
59
+ end
60
+
61
+ def test_inner_join
62
+ join = Nodes::InnerJoin.new :a, :b, :c
63
+ @visitor.accept join
64
+ assert_equal [:a, :b, :c, join], @collector.calls
65
+ end
66
+
67
+ def test_outer_join
68
+ join = Nodes::OuterJoin.new :a, :b, :c
69
+ @visitor.accept join
70
+ assert_equal [:a, :b, :c, join], @collector.calls
71
+ end
72
+
73
+ [
74
+ Arel::Nodes::And,
75
+ Arel::Nodes::Assignment,
76
+ Arel::Nodes::Between,
77
+ Arel::Nodes::DoesNotMatch,
78
+ Arel::Nodes::Equality,
79
+ Arel::Nodes::GreaterThan,
80
+ Arel::Nodes::GreaterThanOrEqual,
81
+ Arel::Nodes::In,
82
+ Arel::Nodes::LessThan,
83
+ Arel::Nodes::LessThanOrEqual,
84
+ Arel::Nodes::Matches,
85
+ Arel::Nodes::NotEqual,
86
+ Arel::Nodes::NotIn,
87
+ Arel::Nodes::Or,
88
+ Arel::Nodes::StringJoin,
89
+ Arel::Nodes::TableAlias,
90
+ Arel::Nodes::Values,
91
+ Arel::Nodes::As,
92
+ Arel::Nodes::DeleteStatement,
93
+ Arel::Nodes::Ordering,
94
+ ].each do |klass|
95
+ define_method("test_#{klass.name.gsub('::', '_')}") do
96
+ binary = klass.new(:a, :b)
97
+ @visitor.accept binary
98
+ assert_equal [:a, :b, binary], @collector.calls
99
+ end
100
+ end
101
+
102
+ [
103
+ Arel::Attributes::Integer,
104
+ Arel::Attributes::Float,
105
+ Arel::Attributes::String,
106
+ Arel::Attributes::Time,
107
+ Arel::Attributes::Boolean,
108
+ Arel::Attributes::Attribute
109
+ ].each do |klass|
110
+ define_method("test_#{klass.name.gsub('::', '_')}") do
111
+ binary = klass.new(:a, :b)
112
+ @visitor.accept binary
113
+ assert_equal [:a, :b, binary], @collector.calls
114
+ end
115
+ end
116
+
117
+ def test_table
118
+ relation = Arel::Table.new(:users)
119
+ @visitor.accept relation
120
+ assert_equal ['users', relation], @collector.calls
121
+ end
122
+
123
+ def test_array
124
+ node = Nodes::Or.new(:a, :b)
125
+ list = [node]
126
+ @visitor.accept list
127
+ assert_equal [:a, :b, node, list], @collector.calls
128
+ end
129
+
130
+ def test_hash
131
+ node = Nodes::Or.new(:a, :b)
132
+ hash = { node => node }
133
+ @visitor.accept hash
134
+ assert_equal [:a, :b, node, :a, :b, node, hash], @collector.calls
135
+ end
136
+
137
+ def test_update_statement
138
+ stmt = Nodes::UpdateStatement.new
139
+ stmt.relation = :a
140
+ stmt.values << :b
141
+ stmt.wheres << :c
142
+ stmt.orders << :d
143
+ stmt.limit = :e
144
+
145
+ @visitor.accept stmt
146
+ assert_equal [:a, :b, stmt.values, :c, stmt.wheres, :d, stmt.orders,
147
+ :e, stmt], @collector.calls
148
+ end
149
+
150
+ def test_select_core
151
+ core = Nodes::SelectCore.new
152
+ core.projections << :a
153
+ core.froms = :b
154
+ core.wheres << :c
155
+ core.groups << :d
156
+ core.having = :e
157
+
158
+ @visitor.accept core
159
+ assert_equal [
160
+ :a, core.projections,
161
+ :b,
162
+ :c, core.wheres,
163
+ :d, core.groups,
164
+ :e,
165
+ core], @collector.calls
166
+ end
167
+
168
+ def test_select_statement
169
+ ss = Nodes::SelectStatement.new
170
+ ss.cores.replace [:a]
171
+ ss.orders << :b
172
+ ss.limit = :c
173
+ ss.lock = :d
174
+ ss.offset = :e
175
+
176
+ @visitor.accept ss
177
+ assert_equal [
178
+ :a, ss.cores,
179
+ :b, ss.orders,
180
+ :c,
181
+ :d,
182
+ :e,
183
+ ss], @collector.calls
184
+ end
185
+
186
+ def test_insert_statement
187
+ stmt = Nodes::InsertStatement.new
188
+ stmt.relation = :a
189
+ stmt.columns << :b
190
+ stmt.values = :c
191
+
192
+ @visitor.accept stmt
193
+ assert_equal [:a, :b, stmt.columns, :c, stmt], @collector.calls
194
+ end
195
+
196
+ def test_node
197
+ node = Nodes::Node.new
198
+ @visitor.accept node
199
+ assert_equal [node], @collector.calls
200
+ end
201
+ end
202
+ end
203
+ end
@@ -22,6 +22,13 @@ module Arel
22
22
  sql = @visitor.accept(stmt)
23
23
  sql.must_be_like "SELECT FROM DUAL"
24
24
  end
25
+
26
+ it 'uses FOR UPDATE when locking' do
27
+ stmt = Nodes::SelectStatement.new
28
+ stmt.lock = Nodes::Lock.new
29
+ sql = @visitor.accept(stmt)
30
+ sql.must_be_like "SELECT FROM DUAL FOR UPDATE"
31
+ end
25
32
  end
26
33
  end
27
34
  end
@@ -21,6 +21,11 @@ module Arel
21
21
  end
22
22
  end
23
23
 
24
+ it "should visit string subclass" do
25
+ @visitor.accept(Class.new(String).new(":'("))
26
+ @visitor.accept(Class.new(Class.new(String)).new(":'("))
27
+ end
28
+
24
29
  it "should visit_Class" do
25
30
  @visitor.accept(DateTime).must_equal "'DateTime'"
26
31
  end
@@ -33,6 +38,17 @@ module Arel
33
38
  @visitor.accept 2.14
34
39
  end
35
40
 
41
+ it "should visit_Not" do
42
+ sql = @visitor.accept Nodes::Not.new(Arel.sql("foo"))
43
+ sql.must_be_like "NOT foo"
44
+ end
45
+
46
+ it "should visit_As" do
47
+ as = Nodes::As.new(Arel.sql("foo"), Arel.sql("bar"))
48
+ sql = @visitor.accept as
49
+ sql.must_be_like "foo AS bar"
50
+ end
51
+
36
52
  it "should visit_Bignum" do
37
53
  @visitor.accept 8787878092
38
54
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arel
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 5
4
5
  prerelease: false
5
6
  segments:
6
7
  - 2
7
8
  - 0
8
- - 4
9
- version: 2.0.4
9
+ - 5
10
+ version: 2.0.5
10
11
  platform: ruby
11
12
  authors:
12
13
  - Aaron Patterson
@@ -17,22 +18,23 @@ autorequire:
17
18
  bindir: bin
18
19
  cert_chain: []
19
20
 
20
- date: 2010-11-17 00:00:00 -08:00
21
+ date: 2010-11-30 00:00:00 -08:00
21
22
  default_executable:
22
23
  dependencies:
23
24
  - !ruby/object:Gem::Dependency
24
- name: rubyforge
25
+ name: minitest
25
26
  prerelease: false
26
27
  requirement: &id001 !ruby/object:Gem::Requirement
27
28
  none: false
28
29
  requirements:
29
30
  - - ">="
30
31
  - !ruby/object:Gem::Version
32
+ hash: 15
31
33
  segments:
32
34
  - 2
33
35
  - 0
34
- - 4
35
- version: 2.0.4
36
+ - 0
37
+ version: 2.0.0
36
38
  type: :development
37
39
  version_requirements: *id001
38
40
  - !ruby/object:Gem::Dependency
@@ -43,6 +45,7 @@ dependencies:
43
45
  requirements:
44
46
  - - ">="
45
47
  - !ruby/object:Gem::Version
48
+ hash: 11
46
49
  segments:
47
50
  - 2
48
51
  - 1
@@ -58,6 +61,7 @@ dependencies:
58
61
  requirements:
59
62
  - - ">="
60
63
  - !ruby/object:Gem::Version
64
+ hash: 15
61
65
  segments:
62
66
  - 1
63
67
  - 6
@@ -73,6 +77,7 @@ dependencies:
73
77
  requirements:
74
78
  - - ">="
75
79
  - !ruby/object:Gem::Version
80
+ hash: 19
76
81
  segments:
77
82
  - 2
78
83
  - 6
@@ -115,6 +120,7 @@ files:
115
120
  - lib/arel/insert_manager.rb
116
121
  - lib/arel/nodes.rb
117
122
  - lib/arel/nodes/and.rb
123
+ - lib/arel/nodes/as.rb
118
124
  - lib/arel/nodes/assignment.rb
119
125
  - lib/arel/nodes/avg.rb
120
126
  - lib/arel/nodes/between.rb
@@ -141,6 +147,7 @@ files:
141
147
  - lib/arel/nodes/max.rb
142
148
  - lib/arel/nodes/min.rb
143
149
  - lib/arel/nodes/node.rb
150
+ - lib/arel/nodes/not.rb
144
151
  - lib/arel/nodes/not_equal.rb
145
152
  - lib/arel/nodes/not_in.rb
146
153
  - lib/arel/nodes/offset.rb
@@ -154,6 +161,7 @@ files:
154
161
  - lib/arel/nodes/string_join.rb
155
162
  - lib/arel/nodes/sum.rb
156
163
  - lib/arel/nodes/table_alias.rb
164
+ - lib/arel/nodes/unary.rb
157
165
  - lib/arel/nodes/unqualified_column.rb
158
166
  - lib/arel/nodes/update_statement.rb
159
167
  - lib/arel/nodes/values.rb
@@ -166,6 +174,7 @@ files:
166
174
  - lib/arel/tree_manager.rb
167
175
  - lib/arel/update_manager.rb
168
176
  - lib/arel/visitors.rb
177
+ - lib/arel/visitors/depth_first.rb
169
178
  - lib/arel/visitors/dot.rb
170
179
  - lib/arel/visitors/join_sql.rb
171
180
  - lib/arel/visitors/mysql.rb
@@ -178,10 +187,13 @@ files:
178
187
  - lib/arel/visitors/where_sql.rb
179
188
  - test/attributes/test_attribute.rb
180
189
  - test/helper.rb
190
+ - test/nodes/test_as.rb
181
191
  - test/nodes/test_count.rb
182
192
  - test/nodes/test_delete_statement.rb
183
193
  - test/nodes/test_equality.rb
184
194
  - test/nodes/test_insert_statement.rb
195
+ - test/nodes/test_node.rb
196
+ - test/nodes/test_not.rb
185
197
  - test/nodes/test_or.rb
186
198
  - test/nodes/test_select_core.rb
187
199
  - test/nodes/test_select_statement.rb
@@ -197,6 +209,7 @@ files:
197
209
  - test/test_select_manager.rb
198
210
  - test/test_table.rb
199
211
  - test/test_update_manager.rb
212
+ - test/visitors/test_depth_first.rb
200
213
  - test/visitors/test_join_sql.rb
201
214
  - test/visitors/test_mysql.rb
202
215
  - test/visitors/test_oracle.rb
@@ -218,6 +231,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
231
  requirements:
219
232
  - - ">="
220
233
  - !ruby/object:Gem::Version
234
+ hash: 3
221
235
  segments:
222
236
  - 0
223
237
  version: "0"
@@ -226,6 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - ">="
228
242
  - !ruby/object:Gem::Version
243
+ hash: 3
229
244
  segments:
230
245
  - 0
231
246
  version: "0"
@@ -238,10 +253,13 @@ specification_version: 3
238
253
  summary: Arel is a Relational Algebra for Ruby
239
254
  test_files:
240
255
  - test/attributes/test_attribute.rb
256
+ - test/nodes/test_as.rb
241
257
  - test/nodes/test_count.rb
242
258
  - test/nodes/test_delete_statement.rb
243
259
  - test/nodes/test_equality.rb
244
260
  - test/nodes/test_insert_statement.rb
261
+ - test/nodes/test_node.rb
262
+ - test/nodes/test_not.rb
245
263
  - test/nodes/test_or.rb
246
264
  - test/nodes/test_select_core.rb
247
265
  - test/nodes/test_select_statement.rb
@@ -256,6 +274,7 @@ test_files:
256
274
  - test/test_select_manager.rb
257
275
  - test/test_table.rb
258
276
  - test/test_update_manager.rb
277
+ - test/visitors/test_depth_first.rb
259
278
  - test/visitors/test_join_sql.rb
260
279
  - test/visitors/test_mysql.rb
261
280
  - test/visitors/test_oracle.rb