arel 6.0.0 → 7.0.0
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.
- 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
|