arel 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +26 -0
- data/History.txt +18 -0
- data/Manifest.txt +31 -30
- data/README.markdown +7 -99
- data/Rakefile +3 -2
- data/arel.gemspec +18 -11
- data/lib/arel.rb +2 -1
- data/lib/arel/attributes/attribute.rb +1 -174
- data/lib/arel/crud.rb +2 -2
- data/lib/arel/delete_manager.rb +4 -4
- data/lib/arel/insert_manager.rb +8 -8
- data/lib/arel/nodes/exists.rb +2 -6
- data/lib/arel/nodes/sql_literal.rb +1 -0
- data/lib/arel/predications.rb +177 -0
- data/lib/arel/select_manager.rb +17 -11
- data/lib/arel/table.rb +4 -0
- data/lib/arel/tree_manager.rb +4 -3
- data/lib/arel/update_manager.rb +8 -8
- data/lib/arel/visitors.rb +4 -0
- data/lib/arel/visitors/dot.rb +3 -3
- data/lib/arel/visitors/join_sql.rb +2 -0
- data/lib/arel/visitors/mysql.rb +14 -0
- data/lib/arel/visitors/oracle.rb +31 -1
- data/lib/arel/visitors/order_clauses.rb +2 -0
- data/lib/arel/visitors/sqlite.rb +11 -0
- data/lib/arel/visitors/to_sql.rb +8 -11
- data/lib/arel/visitors/visitor.rb +19 -0
- data/{spec/attributes/attribute_spec.rb → test/attributes/test_attribute.rb} +84 -84
- data/test/helper.rb +13 -0
- data/{spec/nodes/count_spec.rb → test/nodes/test_count.rb} +3 -3
- data/{spec/nodes/delete_statement_spec.rb → test/nodes/test_delete_statement.rb} +3 -4
- data/{spec/nodes/equality_spec.rb → test/nodes/test_equality.rb} +10 -8
- data/{spec/nodes/insert_statement_spec.rb → test/nodes/test_insert_statement.rb} +6 -6
- data/{spec/nodes/or_spec.rb → test/nodes/test_or.rb} +6 -4
- data/test/nodes/test_select_core.rb +22 -0
- data/{spec/nodes/select_statement_spec.rb → test/nodes/test_select_statement.rb} +3 -4
- data/test/nodes/test_sql_literal.rb +52 -0
- data/{spec/nodes/sum_spec.rb → test/nodes/test_sum.rb} +2 -2
- data/{spec/nodes/update_statement_spec.rb → test/nodes/test_update_statement.rb} +6 -6
- data/{spec → test}/support/fake_record.rb +4 -2
- data/{spec/activerecord_compat_spec.rb → test/test_activerecord_compat.rb} +3 -3
- data/{spec/attributes_spec.rb → test/test_attributes.rb} +7 -7
- data/{spec/crud_spec.rb → test/test_crud.rb} +4 -4
- data/{spec/delete_manager_spec.rb → test/test_delete_manager.rb} +5 -16
- data/{spec/insert_manager_spec.rb → test/test_insert_manager.rb} +15 -31
- data/{spec/select_manager_spec.rb → test/test_select_manager.rb} +95 -77
- data/{spec/table_spec.rb → test/test_table.rb} +38 -32
- data/{spec/update_manager_spec.rb → test/test_update_manager.rb} +9 -21
- data/{spec/visitors/join_sql_spec.rb → test/visitors/test_join_sql.rb} +3 -3
- data/test/visitors/test_mysql.rb +27 -0
- data/{spec/visitors/oracle_spec.rb → test/visitors/test_oracle.rb} +26 -10
- data/{spec/visitors/postgres_spec.rb → test/visitors/test_postgres.rb} +2 -2
- data/test/visitors/test_sqlite.rb +18 -0
- data/{spec/visitors/to_sql_spec.rb → test/visitors/test_to_sql.rb} +25 -18
- metadata +101 -43
- data/spec/nodes/select_core_spec.rb +0 -21
- data/spec/nodes/sql_literal_spec.rb +0 -26
- data/spec/spec.opts +0 -3
- data/spec/spec_helper.rb +0 -18
- data/spec/support/check.rb +0 -6
- data/spec/support/matchers.rb +0 -4
- data/spec/support/matchers/be_like.rb +0 -24
- data/spec/support/shared/tree_manager_shared.rb +0 -9
data/lib/arel/crud.rb
CHANGED
data/lib/arel/delete_manager.rb
CHANGED
@@ -2,21 +2,21 @@ module Arel
|
|
2
2
|
class DeleteManager < Arel::TreeManager
|
3
3
|
def initialize engine
|
4
4
|
super
|
5
|
-
@
|
5
|
+
@ast = Nodes::DeleteStatement.new
|
6
6
|
end
|
7
7
|
|
8
8
|
def from relation
|
9
|
-
@
|
9
|
+
@ast.relation = relation
|
10
10
|
self
|
11
11
|
end
|
12
12
|
|
13
13
|
def where expression
|
14
|
-
@
|
14
|
+
@ast.wheres << expression
|
15
15
|
self
|
16
16
|
end
|
17
17
|
|
18
18
|
def wheres= list
|
19
|
-
@
|
19
|
+
@ast.wheres = list
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
data/lib/arel/insert_manager.rb
CHANGED
@@ -2,32 +2,32 @@ module Arel
|
|
2
2
|
class InsertManager < Arel::TreeManager
|
3
3
|
def initialize engine
|
4
4
|
super
|
5
|
-
@
|
5
|
+
@ast = Nodes::InsertStatement.new
|
6
6
|
end
|
7
7
|
|
8
8
|
def into table
|
9
|
-
@
|
9
|
+
@ast.relation = table
|
10
10
|
self
|
11
11
|
end
|
12
12
|
|
13
|
-
def columns; @
|
14
|
-
def values= val; @
|
13
|
+
def columns; @ast.columns end
|
14
|
+
def values= val; @ast.values = val; end
|
15
15
|
|
16
16
|
def insert fields
|
17
17
|
return if fields.empty?
|
18
18
|
|
19
19
|
if String === fields
|
20
|
-
@
|
20
|
+
@ast.values = SqlLiteral.new(fields)
|
21
21
|
else
|
22
|
-
@
|
22
|
+
@ast.relation ||= fields.first.first.relation
|
23
23
|
|
24
24
|
values = []
|
25
25
|
|
26
26
|
fields.each do |column, value|
|
27
|
-
@
|
27
|
+
@ast.columns << column
|
28
28
|
values << value
|
29
29
|
end
|
30
|
-
@
|
30
|
+
@ast.values = Nodes::Values.new values, @ast.columns
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
data/lib/arel/nodes/exists.rb
CHANGED
@@ -0,0 +1,177 @@
|
|
1
|
+
module Arel
|
2
|
+
module Predications
|
3
|
+
def not_eq other
|
4
|
+
Nodes::NotEqual.new self, other
|
5
|
+
end
|
6
|
+
|
7
|
+
def not_eq_any others
|
8
|
+
grouping_any :not_eq, others
|
9
|
+
end
|
10
|
+
|
11
|
+
def not_eq_all others
|
12
|
+
grouping_all :not_eq, others
|
13
|
+
end
|
14
|
+
|
15
|
+
def eq other
|
16
|
+
Nodes::Equality.new self, other
|
17
|
+
end
|
18
|
+
|
19
|
+
def eq_any others
|
20
|
+
grouping_any :eq, others
|
21
|
+
end
|
22
|
+
|
23
|
+
def eq_all others
|
24
|
+
grouping_all :eq, others
|
25
|
+
end
|
26
|
+
|
27
|
+
def in other
|
28
|
+
case other
|
29
|
+
when Arel::SelectManager
|
30
|
+
Nodes::In.new self, other.to_a.map { |x| x.id }
|
31
|
+
when Range
|
32
|
+
if other.exclude_end?
|
33
|
+
left = Nodes::GreaterThanOrEqual.new(self, other.min)
|
34
|
+
right = Nodes::LessThan.new(self, other.max + 1)
|
35
|
+
Nodes::And.new left, right
|
36
|
+
else
|
37
|
+
Nodes::Between.new(self, Nodes::And.new(other.min, other.max))
|
38
|
+
end
|
39
|
+
else
|
40
|
+
Nodes::In.new self, other
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def in_any others
|
45
|
+
grouping_any :in, others
|
46
|
+
end
|
47
|
+
|
48
|
+
def in_all others
|
49
|
+
grouping_all :in, others
|
50
|
+
end
|
51
|
+
|
52
|
+
def not_in other
|
53
|
+
case other
|
54
|
+
when Arel::SelectManager
|
55
|
+
Nodes::NotIn.new self, other.to_a.map { |x| x.id }
|
56
|
+
when Range
|
57
|
+
if other.exclude_end?
|
58
|
+
left = Nodes::LessThan.new(self, other.min)
|
59
|
+
right = Nodes::GreaterThanOrEqual.new(self, other.max)
|
60
|
+
Nodes::Or.new left, right
|
61
|
+
else
|
62
|
+
left = Nodes::LessThan.new(self, other.min)
|
63
|
+
right = Nodes::GreaterThan.new(self, other.max)
|
64
|
+
Nodes::Or.new left, right
|
65
|
+
end
|
66
|
+
else
|
67
|
+
Nodes::NotIn.new self, other
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def not_in_any others
|
72
|
+
grouping_any :not_in, others
|
73
|
+
end
|
74
|
+
|
75
|
+
def not_in_all others
|
76
|
+
grouping_all :not_in, others
|
77
|
+
end
|
78
|
+
|
79
|
+
def matches other
|
80
|
+
Nodes::Matches.new self, other
|
81
|
+
end
|
82
|
+
|
83
|
+
def matches_any others
|
84
|
+
grouping_any :matches, others
|
85
|
+
end
|
86
|
+
|
87
|
+
def matches_all others
|
88
|
+
grouping_all :matches, others
|
89
|
+
end
|
90
|
+
|
91
|
+
def does_not_match other
|
92
|
+
Nodes::DoesNotMatch.new self, other
|
93
|
+
end
|
94
|
+
|
95
|
+
def does_not_match_any others
|
96
|
+
grouping_any :does_not_match, others
|
97
|
+
end
|
98
|
+
|
99
|
+
def does_not_match_all others
|
100
|
+
grouping_all :does_not_match, others
|
101
|
+
end
|
102
|
+
|
103
|
+
def gteq right
|
104
|
+
Nodes::GreaterThanOrEqual.new self, right
|
105
|
+
end
|
106
|
+
|
107
|
+
def gteq_any others
|
108
|
+
grouping_any :gteq, others
|
109
|
+
end
|
110
|
+
|
111
|
+
def gteq_all others
|
112
|
+
grouping_all :gteq, others
|
113
|
+
end
|
114
|
+
|
115
|
+
def gt right
|
116
|
+
Nodes::GreaterThan.new self, right
|
117
|
+
end
|
118
|
+
|
119
|
+
def gt_any others
|
120
|
+
grouping_any :gt, others
|
121
|
+
end
|
122
|
+
|
123
|
+
def gt_all others
|
124
|
+
grouping_all :gt, others
|
125
|
+
end
|
126
|
+
|
127
|
+
def lt right
|
128
|
+
Nodes::LessThan.new self, right
|
129
|
+
end
|
130
|
+
|
131
|
+
def lt_any others
|
132
|
+
grouping_any :lt, others
|
133
|
+
end
|
134
|
+
|
135
|
+
def lt_all others
|
136
|
+
grouping_all :lt, others
|
137
|
+
end
|
138
|
+
|
139
|
+
def lteq right
|
140
|
+
Nodes::LessThanOrEqual.new self, right
|
141
|
+
end
|
142
|
+
|
143
|
+
def lteq_any others
|
144
|
+
grouping_any :lteq, others
|
145
|
+
end
|
146
|
+
|
147
|
+
def lteq_all others
|
148
|
+
grouping_all :lteq, others
|
149
|
+
end
|
150
|
+
|
151
|
+
def asc
|
152
|
+
Nodes::Ordering.new self, :asc
|
153
|
+
end
|
154
|
+
|
155
|
+
def desc
|
156
|
+
Nodes::Ordering.new self, :desc
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def grouping_any method_id, others
|
162
|
+
first = send method_id, others.shift
|
163
|
+
|
164
|
+
Nodes::Grouping.new others.inject(first) { |memo,expr|
|
165
|
+
Nodes::Or.new(memo, send(method_id, expr))
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def grouping_all method_id, others
|
170
|
+
first = send method_id, others.shift
|
171
|
+
|
172
|
+
Nodes::Grouping.new others.inject(first) { |memo,expr|
|
173
|
+
Nodes::And.new(memo, send(method_id, expr))
|
174
|
+
}
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/lib/arel/select_manager.rb
CHANGED
@@ -4,13 +4,13 @@ module Arel
|
|
4
4
|
|
5
5
|
def initialize engine, table = nil
|
6
6
|
super(engine)
|
7
|
-
@
|
8
|
-
@ctx = @
|
7
|
+
@ast = Nodes::SelectStatement.new
|
8
|
+
@ctx = @ast.cores.last
|
9
9
|
from table
|
10
10
|
end
|
11
11
|
|
12
12
|
def taken
|
13
|
-
@
|
13
|
+
@ast.limit
|
14
14
|
end
|
15
15
|
|
16
16
|
def constraints
|
@@ -18,10 +18,16 @@ module Arel
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def skip amount
|
21
|
-
@
|
21
|
+
@ast.offset = Nodes::Offset.new(amount)
|
22
22
|
self
|
23
23
|
end
|
24
24
|
|
25
|
+
###
|
26
|
+
# Produces an Arel::Nodes::Exists node
|
27
|
+
def exists
|
28
|
+
Arel::Nodes::Exists.new @ast
|
29
|
+
end
|
30
|
+
|
25
31
|
def where_clauses
|
26
32
|
#warn "where_clauses is deprecated" if $VERBOSE
|
27
33
|
to_sql = Visitors::ToSql.new @engine
|
@@ -31,12 +37,12 @@ module Arel
|
|
31
37
|
def lock locking = true
|
32
38
|
# FIXME: do we even need to store this? If locking is +false+ shouldn't
|
33
39
|
# we just remove the node from the AST?
|
34
|
-
@
|
40
|
+
@ast.lock = Nodes::Lock.new
|
35
41
|
self
|
36
42
|
end
|
37
43
|
|
38
44
|
def locked
|
39
|
-
@
|
45
|
+
@ast.lock
|
40
46
|
end
|
41
47
|
|
42
48
|
def on *exprs
|
@@ -96,7 +102,7 @@ module Arel
|
|
96
102
|
# FIXME: converting these to SQLLiterals is probably not good, but
|
97
103
|
# rails tests require it.
|
98
104
|
@ctx.projections.concat projections.map { |x|
|
99
|
-
String
|
105
|
+
[Symbol, String].include?(x.class) ? SqlLiteral.new(x.to_s) : x
|
100
106
|
}
|
101
107
|
self
|
102
108
|
end
|
@@ -108,14 +114,14 @@ module Arel
|
|
108
114
|
|
109
115
|
def order *expr
|
110
116
|
# FIXME: We SHOULD NOT be converting these to SqlLiteral automatically
|
111
|
-
@
|
117
|
+
@ast.orders.concat expr.map { |x|
|
112
118
|
String === x || Symbol === x ? Nodes::SqlLiteral.new(x.to_s) : x
|
113
119
|
}
|
114
120
|
self
|
115
121
|
end
|
116
122
|
|
117
123
|
def orders
|
118
|
-
@
|
124
|
+
@ast.orders
|
119
125
|
end
|
120
126
|
|
121
127
|
def wheres
|
@@ -130,7 +136,7 @@ module Arel
|
|
130
136
|
end
|
131
137
|
|
132
138
|
def take limit
|
133
|
-
@
|
139
|
+
@ast.limit = limit
|
134
140
|
self
|
135
141
|
end
|
136
142
|
|
@@ -142,7 +148,7 @@ module Arel
|
|
142
148
|
end
|
143
149
|
|
144
150
|
def order_clauses
|
145
|
-
Visitors::OrderClauses.new(@engine).accept(@
|
151
|
+
Visitors::OrderClauses.new(@engine).accept(@ast).map { |x|
|
146
152
|
Nodes::SqlLiteral.new x
|
147
153
|
}
|
148
154
|
end
|
data/lib/arel/table.rb
CHANGED
data/lib/arel/tree_manager.rb
CHANGED
@@ -4,6 +4,7 @@ module Arel
|
|
4
4
|
include Arel::Relation
|
5
5
|
|
6
6
|
attr_accessor :visitor
|
7
|
+
attr_reader :ast, :engine
|
7
8
|
|
8
9
|
def initialize engine
|
9
10
|
@engine = engine
|
@@ -11,16 +12,16 @@ module Arel
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def to_dot
|
14
|
-
Visitors::Dot.new.accept @
|
15
|
+
Visitors::Dot.new.accept @ast
|
15
16
|
end
|
16
17
|
|
17
18
|
def to_sql
|
18
|
-
@visitor.accept @
|
19
|
+
@visitor.accept @ast
|
19
20
|
end
|
20
21
|
|
21
22
|
def initialize_copy other
|
22
23
|
super
|
23
|
-
@
|
24
|
+
@ast = @ast.clone
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|
data/lib/arel/update_manager.rb
CHANGED
@@ -2,40 +2,40 @@ module Arel
|
|
2
2
|
class UpdateManager < Arel::TreeManager
|
3
3
|
def initialize engine
|
4
4
|
super
|
5
|
-
@
|
5
|
+
@ast = Nodes::UpdateStatement.new
|
6
6
|
end
|
7
7
|
|
8
8
|
def take limit
|
9
|
-
@
|
9
|
+
@ast.limit = limit
|
10
10
|
self
|
11
11
|
end
|
12
12
|
|
13
13
|
def order *expr
|
14
|
-
@
|
14
|
+
@ast.orders = expr
|
15
15
|
self
|
16
16
|
end
|
17
17
|
|
18
18
|
###
|
19
19
|
# UPDATE +table+
|
20
20
|
def table table
|
21
|
-
@
|
21
|
+
@ast.relation = table
|
22
22
|
self
|
23
23
|
end
|
24
24
|
|
25
25
|
def wheres= exprs
|
26
|
-
@
|
26
|
+
@ast.wheres = exprs
|
27
27
|
end
|
28
28
|
|
29
29
|
def where expr
|
30
|
-
@
|
30
|
+
@ast.wheres << expr
|
31
31
|
self
|
32
32
|
end
|
33
33
|
|
34
34
|
def set values
|
35
35
|
if String === values
|
36
|
-
@
|
36
|
+
@ast.values = [values]
|
37
37
|
else
|
38
|
-
@
|
38
|
+
@ast.values = values.map { |column,value|
|
39
39
|
Nodes::Assignment.new(
|
40
40
|
Nodes::UnqualifiedColumn.new(column),
|
41
41
|
value
|