arel 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|