arel 7.0.0 → 7.1.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 +1 -1
- data/{README.markdown → README.md} +80 -29
- data/lib/arel.rb +1 -1
- data/lib/arel/math.rb +24 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/nodes/case.rb +57 -0
- data/lib/arel/nodes/casted.rb +4 -0
- data/lib/arel/nodes/infix_operation.rb +36 -1
- data/lib/arel/nodes/unary.rb +6 -2
- data/lib/arel/nodes/unary_operation.rb +25 -0
- data/lib/arel/predications.rb +8 -0
- data/lib/arel/visitors.rb +0 -23
- data/lib/arel/visitors/depth_first.rb +15 -1
- data/lib/arel/visitors/dot.rb +6 -0
- data/lib/arel/visitors/mysql.rb +8 -0
- data/lib/arel/visitors/oracle12.rb +9 -3
- data/lib/arel/visitors/postgresql.rb +36 -0
- data/lib/arel/visitors/sqlite.rb +9 -0
- data/lib/arel/visitors/to_sql.rb +52 -37
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2342eabbd34e994cf145023635cfe2da0c06cdf1
|
4
|
+
data.tar.gz: 044e71730354450e808cc454d89b8c362b2c8248
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14fd92387019cbab3bd4a102d0bddf0de1870eb16308054c69488d5d33a7692250f8e4c833ee0b7c76079fb8ed77778e98c55dc3da5f74a9726c793312661cda
|
7
|
+
data.tar.gz: ee5a6f43ddfae8c144f300fc7cb387bb0b836cb9cbbdbd8e1b597d22ed3493ee49a60656ac9ca1420bf9404a406d7a3ccd2fc5eda8281c03cb5ffb616654fe56
|
data/History.txt
CHANGED
data/MIT-LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2007-
|
1
|
+
Copyright (c) 2007-2016 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
|
@@ -8,8 +8,8 @@ Arel Really Exasperates Logicians
|
|
8
8
|
|
9
9
|
Arel is a SQL AST manager for Ruby. It
|
10
10
|
|
11
|
-
1.
|
12
|
-
2.
|
11
|
+
1. simplifies the generation of complex SQL queries, and
|
12
|
+
2. adapts to various RDBMSes.
|
13
13
|
|
14
14
|
It is intended to be a framework framework; that is, you can build your own ORM
|
15
15
|
with it, focusing on innovative object and collection modeling as opposed to
|
@@ -17,7 +17,7 @@ database compatibility and query generation.
|
|
17
17
|
|
18
18
|
## Status
|
19
19
|
|
20
|
-
For the moment, Arel uses Active Record's connection adapters to connect to the various engines
|
20
|
+
For the moment, Arel uses Active Record's connection adapters to connect to the various engines and perform connection pooling, quoting, and type conversion.
|
21
21
|
|
22
22
|
## A Gentle Introduction
|
23
23
|
|
@@ -27,7 +27,7 @@ Generating a query with Arel is simple. For example, in order to produce
|
|
27
27
|
SELECT * FROM users
|
28
28
|
```
|
29
29
|
|
30
|
-
you construct a table relation and convert it to
|
30
|
+
you construct a table relation and convert it to SQL:
|
31
31
|
|
32
32
|
```ruby
|
33
33
|
users = Arel::Table.new(:users)
|
@@ -56,13 +56,48 @@ users.project(users[:id])
|
|
56
56
|
Comparison operators `=`, `!=`, `<`, `>`, `<=`, `>=`, `IN`:
|
57
57
|
|
58
58
|
```ruby
|
59
|
-
users.where(users[:age].eq(10)).project(Arel.sql('*'))
|
60
|
-
|
61
|
-
|
62
|
-
users.where(users[:age].
|
63
|
-
|
64
|
-
|
65
|
-
users.where(users[:age].
|
59
|
+
users.where(users[:age].eq(10)).project(Arel.sql('*'))
|
60
|
+
# => SELECT * FROM "users" WHERE "users"."age" = 10
|
61
|
+
|
62
|
+
users.where(users[:age].not_eq(10)).project(Arel.sql('*'))
|
63
|
+
# => SELECT * FROM "users" WHERE "users"."age" != 10
|
64
|
+
|
65
|
+
users.where(users[:age].lt(10)).project(Arel.sql('*'))
|
66
|
+
# => SELECT * FROM "users" WHERE "users"."age" < 10
|
67
|
+
|
68
|
+
users.where(users[:age].gt(10)).project(Arel.sql('*'))
|
69
|
+
# => SELECT * FROM "users" WHERE "users"."age" > 10
|
70
|
+
|
71
|
+
users.where(users[:age].lteq(10)).project(Arel.sql('*'))
|
72
|
+
# => SELECT * FROM "users" WHERE "users"."age" <= 10
|
73
|
+
|
74
|
+
users.where(users[:age].gteq(10)).project(Arel.sql('*'))
|
75
|
+
# => SELECT * FROM "users" WHERE "users"."age" >= 10
|
76
|
+
|
77
|
+
users.where(users[:age].in([20, 16, 17])).project(Arel.sql('*'))
|
78
|
+
# => SELECT * FROM "users" WHERE "users"."age" IN (20, 16, 17)
|
79
|
+
```
|
80
|
+
|
81
|
+
Bitwise operators `&`, `|`, `^`, `<<`, `>>`:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
users.where((users[:bitmap] & 16).gt(0)).project(Arel.sql('*'))
|
85
|
+
# => SELECT * FROM "users" WHERE ("users"."bitmap" & 16) > 0
|
86
|
+
|
87
|
+
users.where((users[:bitmap] | 16).gt(0)).project(Arel.sql('*'))
|
88
|
+
# => SELECT * FROM "users" WHERE ("users"."bitmap" | 16) > 0
|
89
|
+
|
90
|
+
users.where((users[:bitmap] ^ 16).gt(0)).project(Arel.sql('*'))
|
91
|
+
# => SELECT * FROM "users" WHERE ("users"."bitmap" ^ 16) > 0
|
92
|
+
|
93
|
+
users.where((users[:bitmap] << 1).gt(0)).project(Arel.sql('*'))
|
94
|
+
# => SELECT * FROM "users" WHERE ("users"."bitmap" << 1) > 0
|
95
|
+
|
96
|
+
users.where((users[:bitmap] >> 1).gt(0)).project(Arel.sql('*'))
|
97
|
+
# => SELECT * FROM "users" WHERE ("users"."bitmap" >> 1) > 0
|
98
|
+
|
99
|
+
users.where((~ users[:bitmap]).gt(0)).project(Arel.sql('*'))
|
100
|
+
# => SELECT FROM "users" WHERE ~ "users"."bitmap" > 0
|
66
101
|
```
|
67
102
|
|
68
103
|
Joins resemble SQL strongly:
|
@@ -72,7 +107,7 @@ users.join(photos).on(users[:id].eq(photos[:user_id]))
|
|
72
107
|
# => SELECT * FROM users INNER JOIN photos ON users.id = photos.user_id
|
73
108
|
```
|
74
109
|
|
75
|
-
Left
|
110
|
+
Left joins:
|
76
111
|
|
77
112
|
```ruby
|
78
113
|
users.join(photos, Arel::Nodes::OuterJoin).on(users[:id].eq(photos[:user_id]))
|
@@ -93,7 +128,7 @@ users.project(users[:name]).group(users[:name])
|
|
93
128
|
# => SELECT users.name FROM users GROUP BY users.name
|
94
129
|
```
|
95
130
|
|
96
|
-
The best property of
|
131
|
+
The best property of Arel is its "composability," or closure under all operations. For example, to restrict AND project, just "chain" the method invocations:
|
97
132
|
|
98
133
|
```ruby
|
99
134
|
users \
|
@@ -119,23 +154,35 @@ The `AND` operator behaves similarly.
|
|
119
154
|
Aggregate functions `AVG`, `SUM`, `COUNT`, `MIN`, `MAX`, `HAVING`:
|
120
155
|
|
121
156
|
```ruby
|
122
|
-
photos.group(photos[:user_id]).having(photos[:id].count.gt(5))
|
123
|
-
|
124
|
-
|
125
|
-
users.project(users[:age].
|
126
|
-
|
127
|
-
|
157
|
+
photos.group(photos[:user_id]).having(photos[:id].count.gt(5))
|
158
|
+
# => SELECT FROM photos GROUP BY photos.user_id HAVING COUNT(photos.id) > 5
|
159
|
+
|
160
|
+
users.project(users[:age].sum)
|
161
|
+
# => SELECT SUM(users.age) FROM users
|
162
|
+
|
163
|
+
users.project(users[:age].average)
|
164
|
+
# => SELECT AVG(users.age) FROM users
|
165
|
+
|
166
|
+
users.project(users[:age].maximum)
|
167
|
+
# => SELECT MAX(users.age) FROM users
|
168
|
+
|
169
|
+
users.project(users[:age].minimum)
|
170
|
+
# => SELECT MIN(users.age) FROM users
|
171
|
+
|
172
|
+
users.project(users[:age].count)
|
173
|
+
# => SELECT COUNT(users.age) FROM users
|
128
174
|
```
|
129
175
|
|
130
176
|
Aliasing Aggregate Functions:
|
131
177
|
|
132
178
|
```ruby
|
133
|
-
users.project(users[:age].average.as("mean_age"))
|
179
|
+
users.project(users[:age].average.as("mean_age"))
|
180
|
+
# => SELECT AVG(users.age) AS mean_age FROM users
|
134
181
|
```
|
135
182
|
|
136
183
|
### The Crazy Features
|
137
184
|
|
138
|
-
The examples above are fairly simple and other libraries match or come close to matching the expressiveness of Arel (e.g
|
185
|
+
The examples above are fairly simple and other libraries match or come close to matching the expressiveness of Arel (e.g. `Sequel` in Ruby).
|
139
186
|
|
140
187
|
#### Inline math operations
|
141
188
|
|
@@ -179,12 +226,13 @@ Joining a table to itself requires aliasing in SQL. This aliasing can be handled
|
|
179
226
|
replies = comments.alias
|
180
227
|
comments_with_replies = \
|
181
228
|
comments.join(replies).on(replies[:parent_id].eq(comments[:id])).where(comments[:id].eq(1))
|
182
|
-
# => SELECT * FROM comments INNER JOIN comments AS comments_2
|
229
|
+
# => SELECT * FROM comments INNER JOIN comments AS comments_2
|
230
|
+
# WHERE comments_2.parent_id = comments.id AND comments.id = 1
|
183
231
|
```
|
184
232
|
|
185
233
|
This will return the reply for the first comment.
|
186
234
|
|
187
|
-
[Common Table Expressions(CTE)](https://en.wikipedia.org/wiki/Common_table_expressions#Common_table_expression) support via:
|
235
|
+
[Common Table Expressions (CTE)](https://en.wikipedia.org/wiki/Common_table_expressions#Common_table_expression) support via:
|
188
236
|
|
189
237
|
Create a `CTE`
|
190
238
|
|
@@ -201,7 +249,9 @@ users.
|
|
201
249
|
project(users[:id], cte_table[:click].sum).
|
202
250
|
with(composed_cte)
|
203
251
|
|
204
|
-
# => WITH cte_table AS (SELECT FROM photos WHERE photos.created_at > '2014-05-02')
|
252
|
+
# => WITH cte_table AS (SELECT FROM photos WHERE photos.created_at > '2014-05-02')
|
253
|
+
# SELECT users.id, SUM(cte_table.click)
|
254
|
+
# FROM users INNER JOIN cte_table ON users.id = cte_table.user_id
|
205
255
|
```
|
206
256
|
|
207
257
|
When your query is too complex for `Arel`, you can use `Arel::SqlLiteral`:
|
@@ -214,17 +264,18 @@ photo_clicks = Arel::Nodes::SqlLiteral.new(<<-SQL
|
|
214
264
|
ELSE default_calculation END
|
215
265
|
SQL
|
216
266
|
)
|
267
|
+
|
217
268
|
photos.project(photo_clicks.as("photo_clicks"))
|
218
269
|
# => SELECT CASE WHEN condition1 THEN calculation1
|
219
|
-
WHEN condition2 THEN calculation2
|
220
|
-
WHEN condition3 THEN calculation3
|
221
|
-
ELSE default_calculation END
|
222
|
-
|
270
|
+
# WHEN condition2 THEN calculation2
|
271
|
+
# WHEN condition3 THEN calculation3
|
272
|
+
# ELSE default_calculation END
|
273
|
+
# FROM "photos"
|
223
274
|
```
|
224
275
|
|
225
276
|
## Contributing to Arel
|
226
277
|
|
227
|
-
Arel is work of many contributors. You're encouraged to submit pull requests, propose
|
278
|
+
Arel is the work of many contributors. You're encouraged to submit pull requests, propose
|
228
279
|
features and discuss issues.
|
229
280
|
|
230
281
|
See [CONTRIBUTING](CONTRIBUTING.md).
|
data/lib/arel.rb
CHANGED
data/lib/arel/math.rb
CHANGED
@@ -15,5 +15,29 @@ module Arel
|
|
15
15
|
def /(other)
|
16
16
|
Arel::Nodes::Division.new(self, other)
|
17
17
|
end
|
18
|
+
|
19
|
+
def &(other)
|
20
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::BitwiseAnd.new(self, other))
|
21
|
+
end
|
22
|
+
|
23
|
+
def |(other)
|
24
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::BitwiseOr.new(self, other))
|
25
|
+
end
|
26
|
+
|
27
|
+
def ^(other)
|
28
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::BitwiseXor.new(self, other))
|
29
|
+
end
|
30
|
+
|
31
|
+
def <<(other)
|
32
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::BitwiseShiftLeft.new(self, other))
|
33
|
+
end
|
34
|
+
|
35
|
+
def >>(other)
|
36
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::BitwiseShiftRight.new(self, other))
|
37
|
+
end
|
38
|
+
|
39
|
+
def ~@
|
40
|
+
Arel::Nodes::BitwiseNot.new(self)
|
41
|
+
end
|
18
42
|
end
|
19
43
|
end
|
data/lib/arel/nodes.rb
CHANGED
@@ -28,6 +28,7 @@ require 'arel/nodes/join_source'
|
|
28
28
|
require 'arel/nodes/delete_statement'
|
29
29
|
require 'arel/nodes/table_alias'
|
30
30
|
require 'arel/nodes/infix_operation'
|
31
|
+
require 'arel/nodes/unary_operation'
|
31
32
|
require 'arel/nodes/over'
|
32
33
|
require 'arel/nodes/matches'
|
33
34
|
require 'arel/nodes/regexp'
|
@@ -47,6 +48,9 @@ require 'arel/nodes/named_function'
|
|
47
48
|
# windows
|
48
49
|
require 'arel/nodes/window'
|
49
50
|
|
51
|
+
# conditional expressions
|
52
|
+
require 'arel/nodes/case'
|
53
|
+
|
50
54
|
# joins
|
51
55
|
require 'arel/nodes/full_outer_join'
|
52
56
|
require 'arel/nodes/inner_join'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
class Case < Arel::Nodes::Node
|
4
|
+
include Arel::OrderPredications
|
5
|
+
include Arel::Predications
|
6
|
+
include Arel::AliasPredication
|
7
|
+
|
8
|
+
attr_accessor :case, :conditions, :default
|
9
|
+
|
10
|
+
def initialize expression = nil, default = nil
|
11
|
+
@case = expression
|
12
|
+
@conditions = []
|
13
|
+
@default = default
|
14
|
+
end
|
15
|
+
|
16
|
+
def when condition, expression = nil
|
17
|
+
@conditions << When.new(Nodes.build_quoted(condition), expression)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def then expression
|
22
|
+
@conditions.last.right = Nodes.build_quoted(expression)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def else expression
|
27
|
+
@default = Else.new Nodes.build_quoted(expression)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize_copy other
|
32
|
+
super
|
33
|
+
@case = @case.clone if @case
|
34
|
+
@conditions = @conditions.map { |x| x.clone }
|
35
|
+
@default = @default.clone if @default
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash
|
39
|
+
[@case, @conditions, @default].hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def eql? other
|
43
|
+
self.class == other.class &&
|
44
|
+
self.case == other.case &&
|
45
|
+
self.conditions == other.conditions &&
|
46
|
+
self.default == other.default
|
47
|
+
end
|
48
|
+
alias :== :eql?
|
49
|
+
end
|
50
|
+
|
51
|
+
class When < Binary # :nodoc:
|
52
|
+
end
|
53
|
+
|
54
|
+
class Else < Unary # :nodoc:
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/arel/nodes/casted.rb
CHANGED
@@ -40,5 +40,40 @@ module Arel
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
class Concat < InfixOperation
|
44
|
+
def initialize left, right
|
45
|
+
super('||', left, right)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class BitwiseAnd < InfixOperation
|
50
|
+
def initialize left, right
|
51
|
+
super(:&, left, right)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class BitwiseOr < InfixOperation
|
56
|
+
def initialize left, right
|
57
|
+
super(:|, left, right)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class BitwiseXor < InfixOperation
|
62
|
+
def initialize left, right
|
63
|
+
super(:^, left, right)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class BitwiseShiftLeft < InfixOperation
|
68
|
+
def initialize left, right
|
69
|
+
super(:<<, left, right)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class BitwiseShiftRight < InfixOperation
|
74
|
+
def initialize left, right
|
75
|
+
super(:>>, left, right)
|
76
|
+
end
|
77
|
+
end
|
43
78
|
end
|
44
|
-
end
|
79
|
+
end
|
data/lib/arel/nodes/unary.rb
CHANGED
@@ -22,15 +22,19 @@ module Arel
|
|
22
22
|
|
23
23
|
%w{
|
24
24
|
Bin
|
25
|
+
Cube
|
26
|
+
DistinctOn
|
25
27
|
Group
|
28
|
+
GroupingElement
|
29
|
+
GroupingSet
|
26
30
|
Limit
|
31
|
+
Lock
|
27
32
|
Not
|
28
33
|
Offset
|
29
34
|
On
|
30
35
|
Ordering
|
36
|
+
RollUp
|
31
37
|
Top
|
32
|
-
Lock
|
33
|
-
DistinctOn
|
34
38
|
}.each do |name|
|
35
39
|
const_set(name, Class.new(Unary))
|
36
40
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Arel
|
2
|
+
module Nodes
|
3
|
+
|
4
|
+
class UnaryOperation < Unary
|
5
|
+
include Arel::Expressions
|
6
|
+
include Arel::Predications
|
7
|
+
include Arel::OrderPredications
|
8
|
+
include Arel::AliasPredication
|
9
|
+
include Arel::Math
|
10
|
+
|
11
|
+
attr_reader :operator
|
12
|
+
|
13
|
+
def initialize operator, operand
|
14
|
+
super(operand)
|
15
|
+
@operator = operator
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class BitwiseNot < UnaryOperation
|
20
|
+
def initialize operand
|
21
|
+
super(:~, operand)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/arel/predications.rb
CHANGED
@@ -198,6 +198,14 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead.
|
|
198
198
|
grouping_all :lteq, others
|
199
199
|
end
|
200
200
|
|
201
|
+
def when right
|
202
|
+
Nodes::Case.new(self).when quoted_node(right)
|
203
|
+
end
|
204
|
+
|
205
|
+
def concat other
|
206
|
+
Nodes::Concat.new self, other
|
207
|
+
end
|
208
|
+
|
201
209
|
private
|
202
210
|
|
203
211
|
def grouping_any method_id, others, *extras
|
data/lib/arel/visitors.rb
CHANGED
@@ -14,28 +14,5 @@ require 'arel/visitors/informix'
|
|
14
14
|
|
15
15
|
module Arel
|
16
16
|
module Visitors
|
17
|
-
VISITORS = {
|
18
|
-
'postgresql' => Arel::Visitors::PostgreSQL,
|
19
|
-
'mysql' => Arel::Visitors::MySQL,
|
20
|
-
'mysql2' => Arel::Visitors::MySQL,
|
21
|
-
'mssql' => Arel::Visitors::MSSQL,
|
22
|
-
'sqlserver' => Arel::Visitors::MSSQL,
|
23
|
-
'oracle_enhanced' => Arel::Visitors::Oracle,
|
24
|
-
'sqlite' => Arel::Visitors::SQLite,
|
25
|
-
'sqlite3' => Arel::Visitors::SQLite,
|
26
|
-
'ibm_db' => Arel::Visitors::IBM_DB,
|
27
|
-
'informix' => Arel::Visitors::Informix,
|
28
|
-
}
|
29
|
-
|
30
|
-
ENGINE_VISITORS = Hash.new do |hash, engine|
|
31
|
-
pool = engine.connection_pool
|
32
|
-
adapter = pool.spec.config[:adapter]
|
33
|
-
hash[engine] = (VISITORS[adapter] || Visitors::ToSql).new(engine)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.visitor_for engine
|
37
|
-
ENGINE_VISITORS[engine]
|
38
|
-
end
|
39
|
-
class << self; alias :for :visitor_for; end
|
40
17
|
end
|
41
18
|
end
|
@@ -16,7 +16,12 @@ module Arel
|
|
16
16
|
def unary o
|
17
17
|
visit o.expr
|
18
18
|
end
|
19
|
+
alias :visit_Arel_Nodes_Else :unary
|
19
20
|
alias :visit_Arel_Nodes_Group :unary
|
21
|
+
alias :visit_Arel_Nodes_Cube :unary
|
22
|
+
alias :visit_Arel_Nodes_RollUp :unary
|
23
|
+
alias :visit_Arel_Nodes_GroupingSet :unary
|
24
|
+
alias :visit_Arel_Nodes_GroupingElement :unary
|
20
25
|
alias :visit_Arel_Nodes_Grouping :unary
|
21
26
|
alias :visit_Arel_Nodes_Having :unary
|
22
27
|
alias :visit_Arel_Nodes_Limit :unary
|
@@ -53,6 +58,12 @@ module Arel
|
|
53
58
|
visit o.distinct
|
54
59
|
end
|
55
60
|
|
61
|
+
def visit_Arel_Nodes_Case o
|
62
|
+
visit o.case
|
63
|
+
visit o.conditions
|
64
|
+
visit o.default
|
65
|
+
end
|
66
|
+
|
56
67
|
def nary o
|
57
68
|
o.children.each { |child| visit child}
|
58
69
|
end
|
@@ -65,6 +76,7 @@ module Arel
|
|
65
76
|
alias :visit_Arel_Nodes_As :binary
|
66
77
|
alias :visit_Arel_Nodes_Assignment :binary
|
67
78
|
alias :visit_Arel_Nodes_Between :binary
|
79
|
+
alias :visit_Arel_Nodes_Concat :binary
|
68
80
|
alias :visit_Arel_Nodes_DeleteStatement :binary
|
69
81
|
alias :visit_Arel_Nodes_DoesNotMatch :binary
|
70
82
|
alias :visit_Arel_Nodes_Equality :binary
|
@@ -86,8 +98,9 @@ module Arel
|
|
86
98
|
alias :visit_Arel_Nodes_Regexp :binary
|
87
99
|
alias :visit_Arel_Nodes_RightOuterJoin :binary
|
88
100
|
alias :visit_Arel_Nodes_TableAlias :binary
|
89
|
-
alias :visit_Arel_Nodes_Values :binary
|
90
101
|
alias :visit_Arel_Nodes_Union :binary
|
102
|
+
alias :visit_Arel_Nodes_Values :binary
|
103
|
+
alias :visit_Arel_Nodes_When :binary
|
91
104
|
|
92
105
|
def visit_Arel_Nodes_StringJoin o
|
93
106
|
visit o.left
|
@@ -128,6 +141,7 @@ module Arel
|
|
128
141
|
alias :visit_FalseClass :terminal
|
129
142
|
alias :visit_Fixnum :terminal
|
130
143
|
alias :visit_Float :terminal
|
144
|
+
alias :visit_Integer :terminal
|
131
145
|
alias :visit_NilClass :terminal
|
132
146
|
alias :visit_String :terminal
|
133
147
|
alias :visit_Symbol :terminal
|
data/lib/arel/visitors/dot.rb
CHANGED
@@ -69,6 +69,10 @@ module Arel
|
|
69
69
|
visit_edge o, "expr"
|
70
70
|
end
|
71
71
|
alias :visit_Arel_Nodes_Group :unary
|
72
|
+
alias :visit_Arel_Nodes_Cube :unary
|
73
|
+
alias :visit_Arel_Nodes_RollUp :unary
|
74
|
+
alias :visit_Arel_Nodes_GroupingSet :unary
|
75
|
+
alias :visit_Arel_Nodes_GroupingElement :unary
|
72
76
|
alias :visit_Arel_Nodes_Grouping :unary
|
73
77
|
alias :visit_Arel_Nodes_Having :unary
|
74
78
|
alias :visit_Arel_Nodes_Limit :unary
|
@@ -176,6 +180,7 @@ module Arel
|
|
176
180
|
alias :visit_Arel_Nodes_As :binary
|
177
181
|
alias :visit_Arel_Nodes_Assignment :binary
|
178
182
|
alias :visit_Arel_Nodes_Between :binary
|
183
|
+
alias :visit_Arel_Nodes_Concat :binary
|
179
184
|
alias :visit_Arel_Nodes_DoesNotMatch :binary
|
180
185
|
alias :visit_Arel_Nodes_Equality :binary
|
181
186
|
alias :visit_Arel_Nodes_GreaterThan :binary
|
@@ -200,6 +205,7 @@ module Arel
|
|
200
205
|
alias :visit_TrueClass :visit_String
|
201
206
|
alias :visit_FalseClass :visit_String
|
202
207
|
alias :visit_Arel_Nodes_BindParam :visit_String
|
208
|
+
alias :visit_Integer :visit_String
|
203
209
|
alias :visit_Fixnum :visit_String
|
204
210
|
alias :visit_BigDecimal :visit_String
|
205
211
|
alias :visit_Float :visit_String
|
data/lib/arel/visitors/mysql.rb
CHANGED
@@ -72,6 +72,14 @@ module Arel
|
|
72
72
|
maybe_visit o.limit, collector
|
73
73
|
end
|
74
74
|
|
75
|
+
def visit_Arel_Nodes_Concat o, collector
|
76
|
+
collector << " CONCAT("
|
77
|
+
visit o.left, collector
|
78
|
+
collector << ", "
|
79
|
+
visit o.right, collector
|
80
|
+
collector << ") "
|
81
|
+
collector
|
82
|
+
end
|
75
83
|
end
|
76
84
|
end
|
77
85
|
end
|
@@ -6,10 +6,12 @@ module Arel
|
|
6
6
|
def visit_Arel_Nodes_SelectStatement o, collector
|
7
7
|
# Oracle does not allow LIMIT clause with select for update
|
8
8
|
if o.limit && o.lock
|
9
|
-
|
10
|
-
|
9
|
+
raise ArgumentError, <<-MSG
|
10
|
+
'Combination of limit and lock is not supported.
|
11
|
+
because generated SQL statements
|
12
|
+
`SELECT FOR UPDATE and FETCH FIRST n ROWS` generates ORA-02014.`
|
13
|
+
MSG
|
11
14
|
end
|
12
|
-
|
13
15
|
super
|
14
16
|
end
|
15
17
|
|
@@ -48,6 +50,10 @@ module Arel
|
|
48
50
|
|
49
51
|
super
|
50
52
|
end
|
53
|
+
|
54
|
+
def visit_Arel_Nodes_BindParam o, collector
|
55
|
+
collector.add_bind(o) { |i| ":a#{i}" }
|
56
|
+
end
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module Arel
|
2
2
|
module Visitors
|
3
3
|
class PostgreSQL < Arel::Visitors::ToSql
|
4
|
+
CUBE = 'CUBE'
|
5
|
+
ROLLUP = 'ROLLUP'
|
6
|
+
GROUPING_SET = 'GROUPING SET'
|
7
|
+
|
4
8
|
private
|
5
9
|
|
6
10
|
def visit_Arel_Nodes_Matches o, collector
|
@@ -43,6 +47,38 @@ module Arel
|
|
43
47
|
def visit_Arel_Nodes_BindParam o, collector
|
44
48
|
collector.add_bind(o) { |i| "$#{i}" }
|
45
49
|
end
|
50
|
+
|
51
|
+
def visit_Arel_Nodes_GroupingElement o, collector
|
52
|
+
collector << "( "
|
53
|
+
visit(o.expr, collector) << " )"
|
54
|
+
end
|
55
|
+
|
56
|
+
def visit_Arel_Nodes_Cube o, collector
|
57
|
+
collector << CUBE
|
58
|
+
grouping_array_or_grouping_element o, collector
|
59
|
+
end
|
60
|
+
|
61
|
+
def visit_Arel_Nodes_RollUp o, collector
|
62
|
+
collector << ROLLUP
|
63
|
+
grouping_array_or_grouping_element o, collector
|
64
|
+
end
|
65
|
+
|
66
|
+
def visit_Arel_Nodes_GroupingSet o, collector
|
67
|
+
collector << GROUPING_SET
|
68
|
+
grouping_array_or_grouping_element o, collector
|
69
|
+
end
|
70
|
+
|
71
|
+
# Utilized by GroupingSet, Cube & RollUp visitors to
|
72
|
+
# handle grouping aggregation semantics
|
73
|
+
def grouping_array_or_grouping_element o, collector
|
74
|
+
if o.expr.is_a? Array
|
75
|
+
collector << "( "
|
76
|
+
visit o.expr, collector
|
77
|
+
collector << " )"
|
78
|
+
else
|
79
|
+
visit o.expr, collector
|
80
|
+
end
|
81
|
+
end
|
46
82
|
end
|
47
83
|
end
|
48
84
|
end
|
data/lib/arel/visitors/sqlite.rb
CHANGED
@@ -12,6 +12,15 @@ module Arel
|
|
12
12
|
o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
|
13
13
|
super
|
14
14
|
end
|
15
|
+
|
16
|
+
def visit_Arel_Nodes_True o, collector
|
17
|
+
collector << "1"
|
18
|
+
end
|
19
|
+
|
20
|
+
def visit_Arel_Nodes_False o, collector
|
21
|
+
collector << "0"
|
22
|
+
end
|
23
|
+
|
15
24
|
end
|
16
25
|
end
|
17
26
|
end
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -199,7 +199,7 @@ module Arel
|
|
199
199
|
collector << quote(value, attr && column_for(attr)).to_s
|
200
200
|
end
|
201
201
|
unless i == len
|
202
|
-
collector <<
|
202
|
+
collector << COMMA
|
203
203
|
end
|
204
204
|
}
|
205
205
|
|
@@ -243,53 +243,33 @@ module Arel
|
|
243
243
|
|
244
244
|
collector = maybe_visit o.set_quantifier, collector
|
245
245
|
|
246
|
-
|
247
|
-
collector << SPACE
|
248
|
-
len = o.projections.length - 1
|
249
|
-
o.projections.each_with_index do |x, i|
|
250
|
-
collector = visit(x, collector)
|
251
|
-
collector << COMMA unless len == i
|
252
|
-
end
|
253
|
-
end
|
246
|
+
collect_nodes_for o.projections, collector, SPACE
|
254
247
|
|
255
248
|
if o.source && !o.source.empty?
|
256
249
|
collector << " FROM "
|
257
250
|
collector = visit o.source, collector
|
258
251
|
end
|
259
252
|
|
260
|
-
|
261
|
-
|
262
|
-
len = o.wheres.length - 1
|
263
|
-
o.wheres.each_with_index do |x, i|
|
264
|
-
collector = visit(x, collector)
|
265
|
-
collector << AND unless len == i
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
unless o.groups.empty?
|
270
|
-
collector << GROUP_BY
|
271
|
-
len = o.groups.length - 1
|
272
|
-
o.groups.each_with_index do |x, i|
|
273
|
-
collector = visit(x, collector)
|
274
|
-
collector << COMMA unless len == i
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
253
|
+
collect_nodes_for o.wheres, collector, WHERE, AND
|
254
|
+
collect_nodes_for o.groups, collector, GROUP_BY
|
278
255
|
unless o.havings.empty?
|
279
256
|
collector << " HAVING "
|
280
257
|
inject_join o.havings, collector, AND
|
281
258
|
end
|
259
|
+
collect_nodes_for o.windows, collector, WINDOW
|
282
260
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
261
|
+
collector
|
262
|
+
end
|
263
|
+
|
264
|
+
def collect_nodes_for nodes, collector, spacer, connector = COMMA
|
265
|
+
unless nodes.empty?
|
266
|
+
collector << spacer
|
267
|
+
len = nodes.length - 1
|
268
|
+
nodes.each_with_index do |x, i|
|
287
269
|
collector = visit(x, collector)
|
288
|
-
collector <<
|
270
|
+
collector << connector unless len == i
|
289
271
|
end
|
290
272
|
end
|
291
|
-
|
292
|
-
collector
|
293
273
|
end
|
294
274
|
|
295
275
|
def visit_Arel_Nodes_Bin o, collector
|
@@ -349,13 +329,13 @@ module Arel
|
|
349
329
|
end
|
350
330
|
|
351
331
|
if o.orders.any?
|
352
|
-
collector <<
|
332
|
+
collector << SPACE if o.partitions.any?
|
353
333
|
collector << "ORDER BY "
|
354
334
|
collector = inject_join o.orders, collector, ", "
|
355
335
|
end
|
356
336
|
|
357
337
|
if o.framing
|
358
|
-
collector <<
|
338
|
+
collector << SPACE if o.partitions.any? or o.orders.any?
|
359
339
|
collector = visit o.framing, collector
|
360
340
|
end
|
361
341
|
|
@@ -564,7 +544,7 @@ module Arel
|
|
564
544
|
collector = visit o.left, collector
|
565
545
|
end
|
566
546
|
if o.right.any?
|
567
|
-
collector <<
|
547
|
+
collector << SPACE if o.left
|
568
548
|
collector = inject_join o.right, collector, ' '
|
569
549
|
end
|
570
550
|
collector
|
@@ -708,6 +688,35 @@ module Arel
|
|
708
688
|
visit o.right, collector
|
709
689
|
end
|
710
690
|
|
691
|
+
def visit_Arel_Nodes_Case o, collector
|
692
|
+
collector << "CASE "
|
693
|
+
if o.case
|
694
|
+
visit o.case, collector
|
695
|
+
collector << " "
|
696
|
+
end
|
697
|
+
o.conditions.each do |condition|
|
698
|
+
visit condition, collector
|
699
|
+
collector << " "
|
700
|
+
end
|
701
|
+
if o.default
|
702
|
+
visit o.default, collector
|
703
|
+
collector << " "
|
704
|
+
end
|
705
|
+
collector << "END"
|
706
|
+
end
|
707
|
+
|
708
|
+
def visit_Arel_Nodes_When o, collector
|
709
|
+
collector << "WHEN "
|
710
|
+
visit o.left, collector
|
711
|
+
collector << " THEN "
|
712
|
+
visit o.right, collector
|
713
|
+
end
|
714
|
+
|
715
|
+
def visit_Arel_Nodes_Else o, collector
|
716
|
+
collector << "ELSE "
|
717
|
+
visit o.expr, collector
|
718
|
+
end
|
719
|
+
|
711
720
|
def visit_Arel_Nodes_UnqualifiedColumn o, collector
|
712
721
|
collector << "#{quote_column_name o.name}"
|
713
722
|
collector
|
@@ -733,6 +742,7 @@ module Arel
|
|
733
742
|
alias :visit_Arel_Nodes_SqlLiteral :literal
|
734
743
|
alias :visit_Bignum :literal
|
735
744
|
alias :visit_Fixnum :literal
|
745
|
+
alias :visit_Integer :literal
|
736
746
|
|
737
747
|
def quoted o, a
|
738
748
|
if a && a.able_to_type_cast?
|
@@ -772,6 +782,11 @@ module Arel
|
|
772
782
|
alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation
|
773
783
|
alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation
|
774
784
|
|
785
|
+
def visit_Arel_Nodes_UnaryOperation o, collector
|
786
|
+
collector << " #{o.operator} "
|
787
|
+
visit o.expr, collector
|
788
|
+
end
|
789
|
+
|
775
790
|
def visit_Array o, collector
|
776
791
|
inject_join o, collector, ", "
|
777
792
|
end
|
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: 7.
|
4
|
+
version: 7.1.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: 2016-07-20 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: minitest
|
@@ -75,11 +75,11 @@ extensions: []
|
|
75
75
|
extra_rdoc_files:
|
76
76
|
- History.txt
|
77
77
|
- MIT-LICENSE.txt
|
78
|
-
- README.
|
78
|
+
- README.md
|
79
79
|
files:
|
80
80
|
- History.txt
|
81
81
|
- MIT-LICENSE.txt
|
82
|
-
- README.
|
82
|
+
- README.md
|
83
83
|
- lib/arel.rb
|
84
84
|
- lib/arel/alias_predication.rb
|
85
85
|
- lib/arel/attributes.rb
|
@@ -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/case.rb
|
102
103
|
- lib/arel/nodes/casted.rb
|
103
104
|
- lib/arel/nodes/count.rb
|
104
105
|
- lib/arel/nodes/delete_statement.rb
|
@@ -129,6 +130,7 @@ files:
|
|
129
130
|
- lib/arel/nodes/terminal.rb
|
130
131
|
- lib/arel/nodes/true.rb
|
131
132
|
- lib/arel/nodes/unary.rb
|
133
|
+
- lib/arel/nodes/unary_operation.rb
|
132
134
|
- lib/arel/nodes/unqualified_column.rb
|
133
135
|
- lib/arel/nodes/update_statement.rb
|
134
136
|
- lib/arel/nodes/values.rb
|
@@ -165,7 +167,7 @@ metadata: {}
|
|
165
167
|
post_install_message:
|
166
168
|
rdoc_options:
|
167
169
|
- "--main"
|
168
|
-
- README.
|
170
|
+
- README.md
|
169
171
|
require_paths:
|
170
172
|
- lib
|
171
173
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -180,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
182
|
version: '0'
|
181
183
|
requirements: []
|
182
184
|
rubyforge_project:
|
183
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.6.6
|
184
186
|
signing_key:
|
185
187
|
specification_version: 4
|
186
188
|
summary: Arel Really Exasperates Logicians Arel is a SQL AST manager for Ruby
|