arel 6.0.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +8 -0
- data/MIT-LICENSE.txt +2 -1
- data/README.markdown +9 -3
- data/lib/arel/attributes/attribute.rb +8 -0
- data/lib/arel/crud.rb +4 -3
- data/lib/arel/delete_manager.rb +6 -1
- data/lib/arel/insert_manager.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -2
- data/lib/arel/nodes/bind_param.rb +3 -0
- data/lib/arel/nodes/casted.rb +40 -0
- data/lib/arel/nodes/delete_statement.rb +2 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/matches.rb +3 -1
- data/lib/arel/nodes/regexp.rb +14 -0
- data/lib/arel/nodes/select_core.rb +5 -5
- data/lib/arel/nodes/table_alias.rb +6 -2
- data/lib/arel/nodes/unary.rb +0 -1
- data/lib/arel/nodes.rb +2 -38
- data/lib/arel/predications.rb +30 -14
- data/lib/arel/select_manager.rb +9 -9
- data/lib/arel/table.rb +33 -54
- data/lib/arel/tree_manager.rb +3 -8
- data/lib/arel/update_manager.rb +1 -1
- data/lib/arel/visitors/depth_first.rb +1 -1
- data/lib/arel/visitors/informix.rb +6 -1
- data/lib/arel/visitors/mssql.rb +35 -3
- data/lib/arel/visitors/mysql.rb +1 -1
- data/lib/arel/visitors/oracle.rb +1 -1
- data/lib/arel/visitors/oracle12.rb +53 -0
- data/lib/arel/visitors/postgresql.rb +20 -4
- data/lib/arel/visitors/to_sql.rb +54 -20
- data/lib/arel/visitors/where_sql.rb +10 -1
- data/lib/arel/visitors.rb +1 -0
- data/lib/arel.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d7b8575f1877fe831a05c70632e7046c6ce384c9
|
4
|
+
data.tar.gz: ab4c6895e273c5ad2bd6456bdf2f0fd1b3f7e0a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71feebe60212b48f1bce1fe0acc756728aff663f7e84836bc5888ed237bc6315b22d95993d9b9fce655dbccbf35c75652e9fd62c185d141c0c246084e3d70e68
|
7
|
+
data.tar.gz: 563e00ae3191b5d4be40b8ead9168ead202242593a9761a2a5e938454b13c3094542d83b2e3ca5706c572ca2d1551772a9bce80631e55be9aa3379435bfecb75
|
data/History.txt
CHANGED
data/MIT-LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2007-
|
1
|
+
Copyright (c) 2007-2015 Nick Kallen, Bryan Helmkamp, Emilio Tagua, Aaron Patterson
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -18,3 +18,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
20
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.markdown
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Arel
|
1
|
+
# Arel
|
2
2
|
|
3
3
|
* http://github.com/rails/arel
|
4
4
|
|
@@ -222,6 +222,12 @@ photos.project(photo_clicks.as("photo_clicks"))
|
|
222
222
|
FROM "photos"
|
223
223
|
```
|
224
224
|
|
225
|
-
|
225
|
+
## Contributing to Arel
|
226
226
|
|
227
|
-
Arel is
|
227
|
+
Arel is work of many contributors. You're encouraged to submit pull requests, propose
|
228
|
+
features and discuss issues.
|
229
|
+
|
230
|
+
See [CONTRIBUTING](CONTRIBUTING.md).
|
231
|
+
|
232
|
+
## License
|
233
|
+
Arel is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
@@ -12,6 +12,14 @@ module Arel
|
|
12
12
|
def lower
|
13
13
|
relation.lower self
|
14
14
|
end
|
15
|
+
|
16
|
+
def type_cast_for_database(value)
|
17
|
+
relation.type_cast_for_database(name, value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def able_to_type_cast?
|
21
|
+
relation.able_to_type_cast?
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
25
|
class String < Attribute; end
|
data/lib/arel/crud.rb
CHANGED
@@ -3,7 +3,7 @@ module Arel
|
|
3
3
|
# FIXME hopefully we can remove this
|
4
4
|
module Crud
|
5
5
|
def compile_update values, pk
|
6
|
-
um = UpdateManager.new
|
6
|
+
um = UpdateManager.new
|
7
7
|
|
8
8
|
if Nodes::SqlLiteral === values
|
9
9
|
relation = @ctx.from
|
@@ -26,11 +26,12 @@ module Arel
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def create_insert
|
29
|
-
InsertManager.new
|
29
|
+
InsertManager.new
|
30
30
|
end
|
31
31
|
|
32
32
|
def compile_delete
|
33
|
-
dm = DeleteManager.new
|
33
|
+
dm = DeleteManager.new
|
34
|
+
dm.take @ast.limit.expr if @ast.limit
|
34
35
|
dm.wheres = @ctx.wheres
|
35
36
|
dm.from @ctx.froms
|
36
37
|
dm
|
data/lib/arel/delete_manager.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Arel
|
2
2
|
class DeleteManager < Arel::TreeManager
|
3
|
-
def initialize
|
3
|
+
def initialize
|
4
4
|
super
|
5
5
|
@ast = Nodes::DeleteStatement.new
|
6
6
|
@ctx = @ast
|
@@ -11,6 +11,11 @@ module Arel
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
+
def take limit
|
15
|
+
@ast.limit = Nodes::Limit.new(Nodes.build_quoted(limit)) if limit
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
14
19
|
def wheres= list
|
15
20
|
@ast.wheres = list
|
16
21
|
end
|
data/lib/arel/insert_manager.rb
CHANGED
data/lib/arel/nodes/binary.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
class Casted < Arel::Nodes::Node # :nodoc:
|
4
|
+
attr_reader :val, :attribute
|
5
|
+
def initialize val, attribute
|
6
|
+
@val = val
|
7
|
+
@attribute = attribute
|
8
|
+
super()
|
9
|
+
end
|
10
|
+
|
11
|
+
def nil?; @val.nil?; end
|
12
|
+
|
13
|
+
def eql? other
|
14
|
+
self.class == other.class &&
|
15
|
+
self.val == other.val &&
|
16
|
+
self.attribute == other.attribute
|
17
|
+
end
|
18
|
+
alias :== :eql?
|
19
|
+
end
|
20
|
+
|
21
|
+
class Quoted < Arel::Nodes::Unary # :nodoc:
|
22
|
+
alias :val :value
|
23
|
+
def nil?; val.nil?; end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.build_quoted other, attribute = nil
|
27
|
+
case other
|
28
|
+
when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager, Arel::Nodes::Quoted
|
29
|
+
other
|
30
|
+
else
|
31
|
+
case attribute
|
32
|
+
when Arel::Attributes::Attribute
|
33
|
+
Casted.new other, attribute
|
34
|
+
else
|
35
|
+
Quoted.new other
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/arel/nodes/function.rb
CHANGED
data/lib/arel/nodes/matches.rb
CHANGED
@@ -2,10 +2,12 @@ module Arel
|
|
2
2
|
module Nodes
|
3
3
|
class Matches < Binary
|
4
4
|
attr_reader :escape
|
5
|
+
attr_accessor :case_sensitive
|
5
6
|
|
6
|
-
def initialize(left, right, escape = nil)
|
7
|
+
def initialize(left, right, escape = nil, case_sensitive = false)
|
7
8
|
super(left, right)
|
8
9
|
@escape = escape && Nodes.build_quoted(escape)
|
10
|
+
@case_sensitive = case_sensitive
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
class Regexp < Binary
|
4
|
+
attr_accessor :case_sensitive
|
5
|
+
|
6
|
+
def initialize(left, right, case_sensitive = true)
|
7
|
+
super(left, right)
|
8
|
+
@case_sensitive = case_sensitive
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class NotRegexp < Regexp; end
|
13
|
+
end
|
14
|
+
end
|
@@ -2,7 +2,7 @@ module Arel
|
|
2
2
|
module Nodes
|
3
3
|
class SelectCore < Arel::Nodes::Node
|
4
4
|
attr_accessor :top, :projections, :wheres, :groups, :windows
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :havings, :source, :set_quantifier
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
super()
|
@@ -14,7 +14,7 @@ module Arel
|
|
14
14
|
@projections = []
|
15
15
|
@wheres = []
|
16
16
|
@groups = []
|
17
|
-
@
|
17
|
+
@havings = []
|
18
18
|
@windows = []
|
19
19
|
end
|
20
20
|
|
@@ -35,14 +35,14 @@ module Arel
|
|
35
35
|
@projections = @projections.clone
|
36
36
|
@wheres = @wheres.clone
|
37
37
|
@groups = @groups.clone
|
38
|
-
@
|
38
|
+
@havings = @havings.clone
|
39
39
|
@windows = @windows.clone
|
40
40
|
end
|
41
41
|
|
42
42
|
def hash
|
43
43
|
[
|
44
44
|
@source, @top, @set_quantifier, @projections,
|
45
|
-
@wheres, @groups, @
|
45
|
+
@wheres, @groups, @havings, @windows
|
46
46
|
].hash
|
47
47
|
end
|
48
48
|
|
@@ -54,7 +54,7 @@ module Arel
|
|
54
54
|
self.projections == other.projections &&
|
55
55
|
self.wheres == other.wheres &&
|
56
56
|
self.groups == other.groups &&
|
57
|
-
self.
|
57
|
+
self.havings == other.havings &&
|
58
58
|
self.windows == other.windows
|
59
59
|
end
|
60
60
|
alias :== :eql?
|
@@ -13,8 +13,12 @@ module Arel
|
|
13
13
|
relation.respond_to?(:name) ? relation.name : name
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
relation.
|
16
|
+
def type_cast_for_database(*args)
|
17
|
+
relation.type_cast_for_database(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def able_to_type_cast?
|
21
|
+
relation.respond_to?(:able_to_type_cast?) && relation.able_to_type_cast?
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
data/lib/arel/nodes/unary.rb
CHANGED
data/lib/arel/nodes.rb
CHANGED
@@ -30,6 +30,7 @@ require 'arel/nodes/table_alias'
|
|
30
30
|
require 'arel/nodes/infix_operation'
|
31
31
|
require 'arel/nodes/over'
|
32
32
|
require 'arel/nodes/matches'
|
33
|
+
require 'arel/nodes/regexp'
|
33
34
|
|
34
35
|
# nary
|
35
36
|
require 'arel/nodes/and'
|
@@ -55,41 +56,4 @@ require 'arel/nodes/string_join'
|
|
55
56
|
|
56
57
|
require 'arel/nodes/sql_literal'
|
57
58
|
|
58
|
-
|
59
|
-
module Nodes
|
60
|
-
class Casted < Arel::Nodes::Node # :nodoc:
|
61
|
-
attr_reader :val, :attribute
|
62
|
-
def initialize val, attribute
|
63
|
-
@val = val
|
64
|
-
@attribute = attribute
|
65
|
-
super()
|
66
|
-
end
|
67
|
-
|
68
|
-
def nil?; @val.nil?; end
|
69
|
-
|
70
|
-
def eql? other
|
71
|
-
self.class == other.class &&
|
72
|
-
self.val == other.val &&
|
73
|
-
self.attribute == other.attribute
|
74
|
-
end
|
75
|
-
alias :== :eql?
|
76
|
-
end
|
77
|
-
|
78
|
-
class Quoted < Arel::Nodes::Unary # :nodoc:
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.build_quoted other, attribute = nil
|
82
|
-
case other
|
83
|
-
when Arel::Nodes::Node, Arel::Attributes::Attribute, Arel::Table, Arel::Nodes::BindParam, Arel::SelectManager
|
84
|
-
other
|
85
|
-
else
|
86
|
-
case attribute
|
87
|
-
when Arel::Attributes::Attribute
|
88
|
-
Casted.new other, attribute
|
89
|
-
else
|
90
|
-
Quoted.new other
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
59
|
+
require 'arel/nodes/casted'
|
data/lib/arel/predications.rb
CHANGED
@@ -25,15 +25,15 @@ module Arel
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def between other
|
28
|
-
if other.begin
|
29
|
-
if other.end
|
28
|
+
if equals_quoted?(other.begin, -Float::INFINITY)
|
29
|
+
if equals_quoted?(other.end, Float::INFINITY)
|
30
30
|
not_in([])
|
31
31
|
elsif other.exclude_end?
|
32
32
|
lt(other.end)
|
33
33
|
else
|
34
34
|
lteq(other.end)
|
35
35
|
end
|
36
|
-
elsif other.end
|
36
|
+
elsif equals_quoted?(other.end, Float::INFINITY)
|
37
37
|
gteq(other.begin)
|
38
38
|
elsif other.exclude_end?
|
39
39
|
gteq(other.begin).and(lt(other.end))
|
@@ -71,15 +71,15 @@ Passing a range to `#in` is deprecated. Call `#between`, instead.
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def not_between other
|
74
|
-
if other.begin
|
75
|
-
if other.end
|
74
|
+
if equals_quoted?(other.begin, -Float::INFINITY)
|
75
|
+
if equals_quoted?(other.end, Float::INFINITY)
|
76
76
|
self.in([])
|
77
77
|
elsif other.exclude_end?
|
78
78
|
gteq(other.end)
|
79
79
|
else
|
80
80
|
gt(other.end)
|
81
81
|
end
|
82
|
-
elsif other.end
|
82
|
+
elsif equals_quoted?(other.end, Float::INFINITY)
|
83
83
|
lt(other.begin)
|
84
84
|
else
|
85
85
|
left = lt(other.begin)
|
@@ -118,20 +118,28 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
118
118
|
grouping_all :not_in, others
|
119
119
|
end
|
120
120
|
|
121
|
-
def matches other, escape = nil
|
122
|
-
Nodes::Matches.new self, quoted_node(other), escape
|
121
|
+
def matches other, escape = nil, case_sensitive = false
|
122
|
+
Nodes::Matches.new self, quoted_node(other), escape, case_sensitive
|
123
123
|
end
|
124
124
|
|
125
|
-
def
|
126
|
-
|
125
|
+
def matches_regexp other, case_sensitive = true
|
126
|
+
Nodes::Regexp.new self, quoted_node(other), case_sensitive
|
127
127
|
end
|
128
128
|
|
129
|
-
def
|
130
|
-
|
129
|
+
def matches_any others, escape = nil, case_sensitive = false
|
130
|
+
grouping_any :matches, others, escape, case_sensitive
|
131
131
|
end
|
132
132
|
|
133
|
-
def
|
134
|
-
|
133
|
+
def matches_all others, escape = nil, case_sensitive = false
|
134
|
+
grouping_all :matches, others, escape, case_sensitive
|
135
|
+
end
|
136
|
+
|
137
|
+
def does_not_match other, escape = nil, case_sensitive = false
|
138
|
+
Nodes::DoesNotMatch.new self, quoted_node(other), escape, case_sensitive
|
139
|
+
end
|
140
|
+
|
141
|
+
def does_not_match_regexp other, case_sensitive = true
|
142
|
+
Nodes::NotRegexp.new self, quoted_node(other), case_sensitive
|
135
143
|
end
|
136
144
|
|
137
145
|
def does_not_match_any others, escape = nil
|
@@ -211,5 +219,13 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
211
219
|
def quoted_array(others)
|
212
220
|
others.map { |v| quoted_node(v) }
|
213
221
|
end
|
222
|
+
|
223
|
+
def equals_quoted?(maybe_quoted, value)
|
224
|
+
if maybe_quoted.is_a?(Nodes::Quoted)
|
225
|
+
maybe_quoted.val == value
|
226
|
+
else
|
227
|
+
maybe_quoted == value
|
228
|
+
end
|
229
|
+
end
|
214
230
|
end
|
215
231
|
end
|
data/lib/arel/select_manager.rb
CHANGED
@@ -6,8 +6,8 @@ module Arel
|
|
6
6
|
|
7
7
|
STRING_OR_SYMBOL_CLASS = [Symbol, String]
|
8
8
|
|
9
|
-
def initialize
|
10
|
-
super(
|
9
|
+
def initialize table = nil
|
10
|
+
super()
|
11
11
|
@ast = Nodes::SelectStatement.new
|
12
12
|
@ctx = @ast.cores.last
|
13
13
|
from table
|
@@ -19,7 +19,7 @@ module Arel
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def limit
|
22
|
-
@ast.limit && @ast.limit.expr
|
22
|
+
@ast.limit && @ast.limit.expr
|
23
23
|
end
|
24
24
|
alias :taken :limit
|
25
25
|
|
@@ -118,8 +118,8 @@ module Arel
|
|
118
118
|
join(relation, Nodes::OuterJoin)
|
119
119
|
end
|
120
120
|
|
121
|
-
def having
|
122
|
-
@ctx.
|
121
|
+
def having expr
|
122
|
+
@ctx.havings << expr
|
123
123
|
self
|
124
124
|
end
|
125
125
|
|
@@ -176,10 +176,10 @@ module Arel
|
|
176
176
|
@ast.orders
|
177
177
|
end
|
178
178
|
|
179
|
-
def where_sql
|
179
|
+
def where_sql engine = Table.engine
|
180
180
|
return if @ctx.wheres.empty?
|
181
181
|
|
182
|
-
viz = Visitors::WhereSql.new
|
182
|
+
viz = Visitors::WhereSql.new(engine.connection.visitor, engine.connection)
|
183
183
|
Nodes::SqlLiteral.new viz.accept(@ctx, Collectors::SQLString.new).value
|
184
184
|
end
|
185
185
|
|
@@ -216,8 +216,8 @@ module Arel
|
|
216
216
|
|
217
217
|
def take limit
|
218
218
|
if limit
|
219
|
-
@ast.limit = Nodes::Limit.new(
|
220
|
-
@ctx.top = Nodes::Top.new(
|
219
|
+
@ast.limit = Nodes::Limit.new(limit)
|
220
|
+
@ctx.top = Nodes::Top.new(limit)
|
221
221
|
else
|
222
222
|
@ast.limit = nil
|
223
223
|
@ctx.top = nil
|
data/lib/arel/table.rb
CHANGED
@@ -6,40 +6,24 @@ module Arel
|
|
6
6
|
@engine = nil
|
7
7
|
class << self; attr_accessor :engine; end
|
8
8
|
|
9
|
-
attr_accessor :name, :
|
9
|
+
attr_accessor :name, :aliases, :table_alias
|
10
10
|
|
11
11
|
# TableAlias and Table both have a #table_name which is the name of the underlying table
|
12
12
|
alias :table_name :name
|
13
13
|
|
14
|
-
def initialize
|
14
|
+
def initialize(name, as: nil, type_caster: nil)
|
15
15
|
@name = name.to_s
|
16
|
-
@engine = engine
|
17
16
|
@columns = nil
|
18
17
|
@aliases = []
|
19
|
-
@
|
20
|
-
@primary_key = nil
|
18
|
+
@type_caster = type_caster
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# TableAlias node?
|
28
|
-
@table_alias = engine[:as] unless engine[:as].to_s == @name
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def primary_key
|
33
|
-
if $VERBOSE
|
34
|
-
warn <<-eowarn
|
35
|
-
primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
36
|
-
eowarn
|
37
|
-
end
|
38
|
-
@primary_key ||= begin
|
39
|
-
primary_key_name = @engine.connection.primary_key(name)
|
40
|
-
# some tables might be without primary key
|
41
|
-
primary_key_name && self[primary_key_name]
|
20
|
+
# Sometime AR sends an :as parameter to table, to let the table know
|
21
|
+
# that it is an Alias. We may want to override new, and return a
|
22
|
+
# TableAlias node?
|
23
|
+
if as.to_s == @name
|
24
|
+
as = nil
|
42
25
|
end
|
26
|
+
@table_alias = as
|
43
27
|
end
|
44
28
|
|
45
29
|
def alias name = "#{self.name}_2"
|
@@ -48,12 +32,12 @@ primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
|
48
32
|
end
|
49
33
|
end
|
50
34
|
|
51
|
-
def from
|
52
|
-
SelectManager.new(
|
35
|
+
def from
|
36
|
+
SelectManager.new(self)
|
53
37
|
end
|
54
38
|
|
55
39
|
def join relation, klass = Nodes::InnerJoin
|
56
|
-
return from
|
40
|
+
return from unless relation
|
57
41
|
|
58
42
|
case relation
|
59
43
|
when String, Nodes::SqlLiteral
|
@@ -61,7 +45,7 @@ primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
|
61
45
|
klass = Nodes::StringJoin
|
62
46
|
end
|
63
47
|
|
64
|
-
from
|
48
|
+
from.join(relation, klass)
|
65
49
|
end
|
66
50
|
|
67
51
|
def outer_join relation
|
@@ -69,55 +53,39 @@ primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
|
69
53
|
end
|
70
54
|
|
71
55
|
def group *columns
|
72
|
-
from
|
56
|
+
from.group(*columns)
|
73
57
|
end
|
74
58
|
|
75
59
|
def order *expr
|
76
|
-
from
|
60
|
+
from.order(*expr)
|
77
61
|
end
|
78
62
|
|
79
63
|
def where condition
|
80
|
-
from
|
64
|
+
from.where condition
|
81
65
|
end
|
82
66
|
|
83
67
|
def project *things
|
84
|
-
from
|
68
|
+
from.project(*things)
|
85
69
|
end
|
86
70
|
|
87
71
|
def take amount
|
88
|
-
from
|
72
|
+
from.take amount
|
89
73
|
end
|
90
74
|
|
91
75
|
def skip amount
|
92
|
-
from
|
76
|
+
from.skip amount
|
93
77
|
end
|
94
78
|
|
95
79
|
def having expr
|
96
|
-
from
|
80
|
+
from.having expr
|
97
81
|
end
|
98
82
|
|
99
83
|
def [] name
|
100
84
|
::Arel::Attribute.new self, name
|
101
85
|
end
|
102
86
|
|
103
|
-
def select_manager
|
104
|
-
SelectManager.new(@engine)
|
105
|
-
end
|
106
|
-
|
107
|
-
def insert_manager
|
108
|
-
InsertManager.new(@engine)
|
109
|
-
end
|
110
|
-
|
111
|
-
def update_manager
|
112
|
-
UpdateManager.new(@engine)
|
113
|
-
end
|
114
|
-
|
115
|
-
def delete_manager
|
116
|
-
DeleteManager.new(@engine)
|
117
|
-
end
|
118
|
-
|
119
87
|
def hash
|
120
|
-
# Perf note: aliases
|
88
|
+
# Perf note: aliases and table alias is excluded from the hash
|
121
89
|
# aliases can have a loop back to this table breaking hashes in parent
|
122
90
|
# relations, for the vast majority of cases @name is unique to a query
|
123
91
|
@name.hash
|
@@ -126,12 +94,23 @@ primary_key (#{caller.first}) is deprecated and will be removed in Arel 4.0.0
|
|
126
94
|
def eql? other
|
127
95
|
self.class == other.class &&
|
128
96
|
self.name == other.name &&
|
129
|
-
self.engine == other.engine &&
|
130
97
|
self.aliases == other.aliases &&
|
131
98
|
self.table_alias == other.table_alias
|
132
99
|
end
|
133
100
|
alias :== :eql?
|
134
101
|
|
102
|
+
def type_cast_for_database(attribute_name, value)
|
103
|
+
type_caster.type_cast_for_database(attribute_name, value)
|
104
|
+
end
|
105
|
+
|
106
|
+
def able_to_type_cast?
|
107
|
+
!type_caster.nil?
|
108
|
+
end
|
109
|
+
|
110
|
+
protected
|
111
|
+
|
112
|
+
attr_reader :type_caster
|
113
|
+
|
135
114
|
private
|
136
115
|
|
137
116
|
def attributes_for columns
|
data/lib/arel/tree_manager.rb
CHANGED
@@ -8,8 +8,7 @@ module Arel
|
|
8
8
|
|
9
9
|
attr_accessor :bind_values
|
10
10
|
|
11
|
-
def initialize
|
12
|
-
@engine = engine
|
11
|
+
def initialize
|
13
12
|
@ctx = nil
|
14
13
|
@bind_values = []
|
15
14
|
end
|
@@ -20,13 +19,9 @@ module Arel
|
|
20
19
|
collector.value
|
21
20
|
end
|
22
21
|
|
23
|
-
def
|
24
|
-
engine.connection.visitor
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_sql
|
22
|
+
def to_sql engine = Table.engine
|
28
23
|
collector = Arel::Collectors::SQLString.new
|
29
|
-
collector = visitor.accept @ast, collector
|
24
|
+
collector = engine.connection.visitor.accept @ast, collector
|
30
25
|
collector.value
|
31
26
|
end
|
32
27
|
|
data/lib/arel/update_manager.rb
CHANGED
@@ -34,8 +34,13 @@ module Arel
|
|
34
34
|
collector = inject_join o.groups, collector, ", "
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
if o.havings.any?
|
38
|
+
collector << " HAVING "
|
39
|
+
collector = inject_join o.havings, collector, " AND "
|
40
|
+
end
|
41
|
+
collector
|
38
42
|
end
|
43
|
+
|
39
44
|
def visit_Arel_Nodes_Offset o, collector
|
40
45
|
collector << "SKIP "
|
41
46
|
visit o.expr, collector
|
data/lib/arel/visitors/mssql.rb
CHANGED
@@ -3,6 +3,11 @@ module Arel
|
|
3
3
|
class MSSQL < Arel::Visitors::ToSql
|
4
4
|
RowNumber = Struct.new :children
|
5
5
|
|
6
|
+
def initialize(*)
|
7
|
+
@primary_keys = {}
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
6
11
|
private
|
7
12
|
|
8
13
|
# `top` wouldn't really work here. I.e. User.select("distinct first_name").limit(10) would generate
|
@@ -61,6 +66,23 @@ module Arel
|
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
69
|
+
def visit_Arel_Nodes_DeleteStatement o, collector
|
70
|
+
collector << 'DELETE '
|
71
|
+
if o.limit
|
72
|
+
collector << 'TOP ('
|
73
|
+
visit o.limit.expr, collector
|
74
|
+
collector << ') '
|
75
|
+
end
|
76
|
+
collector << 'FROM '
|
77
|
+
collector = visit o.relation, collector
|
78
|
+
if o.wheres.any?
|
79
|
+
collector << ' WHERE '
|
80
|
+
inject_join o.wheres, collector, AND
|
81
|
+
else
|
82
|
+
collector
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
64
86
|
def determine_order_by orders, x
|
65
87
|
if orders.any?
|
66
88
|
orders
|
@@ -81,10 +103,20 @@ module Arel
|
|
81
103
|
end
|
82
104
|
|
83
105
|
# FIXME raise exception of there is no pk?
|
84
|
-
# FIXME!! Table.primary_key will be deprecated. What is the replacement??
|
85
106
|
def find_left_table_pk o
|
86
|
-
|
87
|
-
|
107
|
+
if o.kind_of?(Arel::Nodes::Join)
|
108
|
+
find_left_table_pk(o.left)
|
109
|
+
elsif o.instance_of?(Arel::Table)
|
110
|
+
find_primary_key(o)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_primary_key(o)
|
115
|
+
@primary_keys[o.name] ||= begin
|
116
|
+
primary_key_name = @connection.primary_key(o.name)
|
117
|
+
# some tables might be without primary key
|
118
|
+
primary_key_name && o[primary_key_name]
|
119
|
+
end
|
88
120
|
end
|
89
121
|
end
|
90
122
|
end
|
data/lib/arel/visitors/mysql.rb
CHANGED
@@ -40,7 +40,7 @@ module Arel
|
|
40
40
|
# http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214
|
41
41
|
def visit_Arel_Nodes_SelectStatement o, collector
|
42
42
|
if o.offset && !o.limit
|
43
|
-
o.limit = Arel::Nodes::Limit.new(
|
43
|
+
o.limit = Arel::Nodes::Limit.new(18446744073709551615)
|
44
44
|
end
|
45
45
|
super
|
46
46
|
end
|
data/lib/arel/visitors/oracle.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class Oracle12 < Arel::Visitors::ToSql
|
4
|
+
private
|
5
|
+
|
6
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
7
|
+
# Oracle does not allow LIMIT clause with select for update
|
8
|
+
if o.limit && o.lock
|
9
|
+
o = o.dup
|
10
|
+
o.limit = []
|
11
|
+
end
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def visit_Arel_Nodes_SelectOptions o, collector
|
17
|
+
collector = maybe_visit o.offset, collector
|
18
|
+
collector = maybe_visit o.limit, collector
|
19
|
+
collector = maybe_visit o.lock, collector
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit_Arel_Nodes_Limit o, collector
|
23
|
+
collector << "FETCH FIRST "
|
24
|
+
collector = visit o.expr, collector
|
25
|
+
collector << " ROWS ONLY"
|
26
|
+
end
|
27
|
+
|
28
|
+
def visit_Arel_Nodes_Offset o, collector
|
29
|
+
collector << "OFFSET "
|
30
|
+
visit o.expr, collector
|
31
|
+
collector << " ROWS"
|
32
|
+
end
|
33
|
+
|
34
|
+
def visit_Arel_Nodes_Except o, collector
|
35
|
+
collector << "( "
|
36
|
+
collector = infix_value o, collector, " MINUS "
|
37
|
+
collector << " )"
|
38
|
+
end
|
39
|
+
|
40
|
+
def visit_Arel_Nodes_UpdateStatement o, collector
|
41
|
+
# Oracle does not allow ORDER BY/LIMIT in UPDATEs.
|
42
|
+
if o.orders.any? && o.limit.nil?
|
43
|
+
# However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided,
|
44
|
+
# otherwise let the user deal with the error
|
45
|
+
o = o.dup
|
46
|
+
o.orders = []
|
47
|
+
end
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -4,19 +4,35 @@ module Arel
|
|
4
4
|
private
|
5
5
|
|
6
6
|
def visit_Arel_Nodes_Matches o, collector
|
7
|
-
|
7
|
+
op = o.case_sensitive ? ' LIKE ' : ' ILIKE '
|
8
|
+
collector = infix_value o, collector, op
|
9
|
+
if o.escape
|
10
|
+
collector << ' ESCAPE '
|
11
|
+
visit o.escape, collector
|
12
|
+
else
|
13
|
+
collector
|
14
|
+
end
|
8
15
|
end
|
9
16
|
|
10
17
|
def visit_Arel_Nodes_DoesNotMatch o, collector
|
11
|
-
|
18
|
+
op = o.case_sensitive ? ' NOT LIKE ' : ' NOT ILIKE '
|
19
|
+
collector = infix_value o, collector, op
|
20
|
+
if o.escape
|
21
|
+
collector << ' ESCAPE '
|
22
|
+
visit o.escape, collector
|
23
|
+
else
|
24
|
+
collector
|
25
|
+
end
|
12
26
|
end
|
13
27
|
|
14
28
|
def visit_Arel_Nodes_Regexp o, collector
|
15
|
-
|
29
|
+
op = o.case_sensitive ? ' ~ ' : ' ~* '
|
30
|
+
infix_value o, collector, op
|
16
31
|
end
|
17
32
|
|
18
33
|
def visit_Arel_Nodes_NotRegexp o, collector
|
19
|
-
|
34
|
+
op = o.case_sensitive ? ' !~ ' : ' !~* '
|
35
|
+
infix_value o, collector, op
|
20
36
|
end
|
21
37
|
|
22
38
|
def visit_Arel_Nodes_DistinctOn o, collector
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -4,6 +4,12 @@ require 'arel/visitors/reduce'
|
|
4
4
|
|
5
5
|
module Arel
|
6
6
|
module Visitors
|
7
|
+
class UnsupportedVisitError < StandardError
|
8
|
+
def initialize(object)
|
9
|
+
super "Unsupported argument type: #{object.class.name}. Construct an Arel node instead."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
class ToSql < Arel::Visitors::Reduce
|
8
14
|
##
|
9
15
|
# This is some roflscale crazy stuff. I'm roflscaling this because
|
@@ -74,14 +80,14 @@ module Arel
|
|
74
80
|
end
|
75
81
|
|
76
82
|
def visit_Arel_Nodes_DeleteStatement o, collector
|
77
|
-
collector <<
|
83
|
+
collector << 'DELETE FROM '
|
78
84
|
collector = visit o.relation, collector
|
79
85
|
if o.wheres.any?
|
80
|
-
collector <<
|
81
|
-
inject_join o.wheres, collector, AND
|
82
|
-
else
|
83
|
-
collector
|
86
|
+
collector << ' WHERE '
|
87
|
+
collector = inject_join o.wheres, collector, AND
|
84
88
|
end
|
89
|
+
|
90
|
+
maybe_visit o.limit, collector
|
85
91
|
end
|
86
92
|
|
87
93
|
# FIXME: we should probably have a 2-pass visitor for this
|
@@ -211,7 +217,6 @@ module Arel
|
|
211
217
|
}
|
212
218
|
|
213
219
|
unless o.orders.empty?
|
214
|
-
collector << SPACE
|
215
220
|
collector << ORDER_BY
|
216
221
|
len = o.orders.length - 1
|
217
222
|
o.orders.each_with_index { |x, i|
|
@@ -220,11 +225,15 @@ module Arel
|
|
220
225
|
}
|
221
226
|
end
|
222
227
|
|
228
|
+
visit_Arel_Nodes_SelectOptions(o, collector)
|
229
|
+
|
230
|
+
collector
|
231
|
+
end
|
232
|
+
|
233
|
+
def visit_Arel_Nodes_SelectOptions o, collector
|
223
234
|
collector = maybe_visit o.limit, collector
|
224
235
|
collector = maybe_visit o.offset, collector
|
225
236
|
collector = maybe_visit o.lock, collector
|
226
|
-
|
227
|
-
collector
|
228
237
|
end
|
229
238
|
|
230
239
|
def visit_Arel_Nodes_SelectCore o, collector
|
@@ -266,7 +275,10 @@ module Arel
|
|
266
275
|
end
|
267
276
|
end
|
268
277
|
|
269
|
-
|
278
|
+
unless o.havings.empty?
|
279
|
+
collector << " HAVING "
|
280
|
+
inject_join o.havings, collector, AND
|
281
|
+
end
|
270
282
|
|
271
283
|
unless o.windows.empty?
|
272
284
|
collector << WINDOW
|
@@ -405,11 +417,6 @@ module Arel
|
|
405
417
|
end
|
406
418
|
end
|
407
419
|
|
408
|
-
def visit_Arel_Nodes_Having o, collector
|
409
|
-
collector << "HAVING "
|
410
|
-
visit o.expr, collector
|
411
|
-
end
|
412
|
-
|
413
420
|
def visit_Arel_Nodes_Offset o, collector
|
414
421
|
collector << "OFFSET "
|
415
422
|
visit o.expr, collector
|
@@ -575,8 +582,11 @@ module Arel
|
|
575
582
|
visit o.left, collector
|
576
583
|
end
|
577
584
|
|
578
|
-
def visit_Arel_Nodes_FullOuterJoin o
|
579
|
-
"FULL OUTER JOIN
|
585
|
+
def visit_Arel_Nodes_FullOuterJoin o, collector
|
586
|
+
collector << "FULL OUTER JOIN "
|
587
|
+
collector = visit o.left, collector
|
588
|
+
collector << SPACE
|
589
|
+
visit o.right, collector
|
580
590
|
end
|
581
591
|
|
582
592
|
def visit_Arel_Nodes_OuterJoin o, collector
|
@@ -586,8 +596,11 @@ module Arel
|
|
586
596
|
visit o.right, collector
|
587
597
|
end
|
588
598
|
|
589
|
-
def visit_Arel_Nodes_RightOuterJoin o
|
590
|
-
"RIGHT OUTER JOIN
|
599
|
+
def visit_Arel_Nodes_RightOuterJoin o, collector
|
600
|
+
collector << "RIGHT OUTER JOIN "
|
601
|
+
collector = visit o.left, collector
|
602
|
+
collector << SPACE
|
603
|
+
visit o.right, collector
|
591
604
|
end
|
592
605
|
|
593
606
|
def visit_Arel_Nodes_InnerJoin o, collector
|
@@ -722,11 +735,15 @@ module Arel
|
|
722
735
|
alias :visit_Fixnum :literal
|
723
736
|
|
724
737
|
def quoted o, a
|
725
|
-
|
738
|
+
if a && a.able_to_type_cast?
|
739
|
+
quote(a.type_cast_for_database(o))
|
740
|
+
else
|
741
|
+
quote(o, column_for(a))
|
742
|
+
end
|
726
743
|
end
|
727
744
|
|
728
745
|
def unsupported o, collector
|
729
|
-
raise
|
746
|
+
raise UnsupportedVisitError.new(o)
|
730
747
|
end
|
731
748
|
|
732
749
|
alias :visit_ActiveSupport_Multibyte_Chars :unsupported
|
@@ -762,6 +779,9 @@ module Arel
|
|
762
779
|
|
763
780
|
def quote value, column = nil
|
764
781
|
return value if Arel::Nodes::SqlLiteral === value
|
782
|
+
if column
|
783
|
+
print_type_cast_deprecation
|
784
|
+
end
|
765
785
|
@connection.quote value, column
|
766
786
|
end
|
767
787
|
|
@@ -811,6 +831,20 @@ module Arel
|
|
811
831
|
collector
|
812
832
|
end
|
813
833
|
end
|
834
|
+
|
835
|
+
def print_type_cast_deprecation
|
836
|
+
unless defined?($arel_silence_type_casting_deprecation) && $arel_silence_type_casting_deprecation
|
837
|
+
warn <<-eowarn
|
838
|
+
Arel performing automatic type casting is deprecated, and will be removed in Arel 8.0. If you are seeing this, it is because you are manually passing a value to an Arel predicate, and the `Arel::Table` object was constructed manually. The easiest way to remove this warning is to use an `Arel::Table` object returned from calling `arel_table` on an ActiveRecord::Base subclass.
|
839
|
+
|
840
|
+
If you're certain the value is already of the right type, change `attribute.eq(value)` to `attribute.eq(Arel::Nodes::Quoted.new(value))` (you will be able to remove that in Arel 8.0, it is only required to silence this deprecation warning).
|
841
|
+
|
842
|
+
You can also silence this warning globally by setting `$arel_silence_type_casting_deprecation` to `true`. (Do NOT do this if you are a library author)
|
843
|
+
|
844
|
+
If you are passing user input to a predicate, you must either give an appropriate type caster object to the `Arel::Table`, or manually cast the value before passing it to Arel.
|
845
|
+
eowarn
|
846
|
+
end
|
847
|
+
end
|
814
848
|
end
|
815
849
|
end
|
816
850
|
end
|
@@ -1,11 +1,20 @@
|
|
1
1
|
module Arel
|
2
2
|
module Visitors
|
3
3
|
class WhereSql < Arel::Visitors::ToSql
|
4
|
+
def initialize(inner_visitor, *args, &block)
|
5
|
+
@inner_visitor = inner_visitor
|
6
|
+
super(*args, &block)
|
7
|
+
end
|
8
|
+
|
4
9
|
private
|
5
10
|
|
6
11
|
def visit_Arel_Nodes_SelectCore o, collector
|
7
12
|
collector << "WHERE "
|
8
|
-
|
13
|
+
wheres = o.wheres.map do |where|
|
14
|
+
Nodes::SqlLiteral.new(@inner_visitor.accept(where, collector.class.new).value)
|
15
|
+
end
|
16
|
+
|
17
|
+
inject_join wheres, collector, ' AND '
|
9
18
|
end
|
10
19
|
end
|
11
20
|
end
|
data/lib/arel/visitors.rb
CHANGED
@@ -6,6 +6,7 @@ require 'arel/visitors/postgresql'
|
|
6
6
|
require 'arel/visitors/mysql'
|
7
7
|
require 'arel/visitors/mssql'
|
8
8
|
require 'arel/visitors/oracle'
|
9
|
+
require 'arel/visitors/oracle12'
|
9
10
|
require 'arel/visitors/where_sql'
|
10
11
|
require 'arel/visitors/dot'
|
11
12
|
require 'arel/visitors/ibm_db'
|
data/lib/arel.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2015-12-17 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: minitest
|
@@ -99,6 +99,7 @@ files:
|
|
99
99
|
- lib/arel/nodes/ascending.rb
|
100
100
|
- lib/arel/nodes/binary.rb
|
101
101
|
- lib/arel/nodes/bind_param.rb
|
102
|
+
- lib/arel/nodes/casted.rb
|
102
103
|
- lib/arel/nodes/count.rb
|
103
104
|
- lib/arel/nodes/delete_statement.rb
|
104
105
|
- lib/arel/nodes/descending.rb
|
@@ -118,6 +119,7 @@ files:
|
|
118
119
|
- lib/arel/nodes/node.rb
|
119
120
|
- lib/arel/nodes/outer_join.rb
|
120
121
|
- lib/arel/nodes/over.rb
|
122
|
+
- lib/arel/nodes/regexp.rb
|
121
123
|
- lib/arel/nodes/right_outer_join.rb
|
122
124
|
- lib/arel/nodes/select_core.rb
|
123
125
|
- lib/arel/nodes/select_statement.rb
|
@@ -148,6 +150,7 @@ files:
|
|
148
150
|
- lib/arel/visitors/mssql.rb
|
149
151
|
- lib/arel/visitors/mysql.rb
|
150
152
|
- lib/arel/visitors/oracle.rb
|
153
|
+
- lib/arel/visitors/oracle12.rb
|
151
154
|
- lib/arel/visitors/postgresql.rb
|
152
155
|
- lib/arel/visitors/reduce.rb
|
153
156
|
- lib/arel/visitors/sqlite.rb
|
@@ -177,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
180
|
version: '0'
|
178
181
|
requirements: []
|
179
182
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.
|
183
|
+
rubygems_version: 2.4.5.1
|
181
184
|
signing_key:
|
182
185
|
specification_version: 4
|
183
186
|
summary: Arel Really Exasperates Logicians Arel is a SQL AST manager for Ruby
|