arel 5.0.1.20140414130214 → 6.0.0.beta1
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/.travis.yml +4 -2
- data/History.txt +9 -4
- data/Manifest.txt +9 -7
- data/README.markdown +85 -8
- data/Rakefile +1 -1
- data/arel.gemspec +15 -16
- data/lib/arel.rb +1 -12
- data/lib/arel/collectors/bind.rb +36 -0
- data/lib/arel/collectors/plain_string.rb +18 -0
- data/lib/arel/collectors/sql_string.rb +18 -0
- data/lib/arel/factory_methods.rb +1 -1
- data/lib/arel/insert_manager.rb +5 -1
- data/lib/arel/nodes.rb +41 -0
- data/lib/arel/nodes/and.rb +1 -5
- data/lib/arel/nodes/binary.rb +2 -0
- data/lib/arel/nodes/extract.rb +0 -2
- data/lib/arel/nodes/full_outer_join.rb +6 -0
- data/lib/arel/nodes/function.rb +0 -1
- data/lib/arel/nodes/insert_statement.rb +5 -2
- data/lib/arel/nodes/node.rb +5 -1
- data/lib/arel/nodes/right_outer_join.rb +6 -0
- data/lib/arel/nodes/window.rb +23 -5
- data/lib/arel/predications.rb +41 -33
- data/lib/arel/select_manager.rb +13 -37
- data/lib/arel/table.rb +13 -9
- data/lib/arel/tree_manager.rb +8 -2
- data/lib/arel/update_manager.rb +2 -2
- data/lib/arel/visitors.rb +0 -2
- data/lib/arel/visitors/bind_substitute.rb +9 -0
- data/lib/arel/visitors/bind_visitor.rb +10 -5
- data/lib/arel/visitors/depth_first.rb +60 -57
- data/lib/arel/visitors/dot.rb +84 -80
- data/lib/arel/visitors/ibm_db.rb +4 -2
- data/lib/arel/visitors/informix.rb +39 -21
- data/lib/arel/visitors/mssql.rb +41 -23
- data/lib/arel/visitors/mysql.rb +48 -22
- data/lib/arel/visitors/oracle.rb +33 -24
- data/lib/arel/visitors/postgresql.rb +15 -8
- data/lib/arel/visitors/reduce.rb +25 -0
- data/lib/arel/visitors/sqlite.rb +3 -2
- data/lib/arel/visitors/to_sql.rb +455 -248
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel/visitors/where_sql.rb +3 -2
- data/test/attributes/test_attribute.rb +12 -3
- data/test/collectors/test_bind_collector.rb +70 -0
- data/test/collectors/test_sql_string.rb +38 -0
- data/test/helper.rb +10 -1
- data/test/nodes/test_bin.rb +2 -2
- data/test/nodes/test_count.rb +0 -6
- data/test/nodes/test_equality.rb +1 -1
- data/test/nodes/test_grouping.rb +1 -1
- data/test/nodes/test_infix_operation.rb +1 -1
- data/test/nodes/test_select_core.rb +7 -7
- data/test/nodes/test_sql_literal.rb +10 -6
- data/test/nodes/test_window.rb +9 -3
- data/test/support/fake_record.rb +16 -4
- data/test/test_factory_methods.rb +1 -1
- data/test/test_insert_manager.rb +33 -4
- data/test/test_select_manager.rb +164 -92
- data/test/test_table.rb +49 -4
- data/test/visitors/test_bind_visitor.rb +18 -10
- data/test/visitors/test_depth_first.rb +12 -0
- data/test/visitors/test_dot.rb +4 -4
- data/test/visitors/test_ibm_db.rb +11 -5
- data/test/visitors/test_informix.rb +14 -8
- data/test/visitors/test_mssql.rb +12 -8
- data/test/visitors/test_mysql.rb +17 -12
- data/test/visitors/test_oracle.rb +25 -21
- data/test/visitors/test_postgres.rb +50 -12
- data/test/visitors/test_sqlite.rb +2 -2
- data/test/visitors/test_to_sql.rb +177 -81
- metadata +24 -19
- data/lib/arel/deprecated.rb +0 -4
- data/lib/arel/expression.rb +0 -5
- data/lib/arel/sql/engine.rb +0 -10
- data/lib/arel/sql_literal.rb +0 -4
- data/lib/arel/visitors/join_sql.rb +0 -19
- data/lib/arel/visitors/order_clauses.rb +0 -11
- data/test/visitors/test_join_sql.rb +0 -42
data/lib/arel/visitors/sqlite.rb
CHANGED
@@ -4,10 +4,11 @@ module Arel
|
|
4
4
|
private
|
5
5
|
|
6
6
|
# Locks are not supported in SQLite
|
7
|
-
def visit_Arel_Nodes_Lock o,
|
7
|
+
def visit_Arel_Nodes_Lock o, collector
|
8
|
+
collector
|
8
9
|
end
|
9
10
|
|
10
|
-
def visit_Arel_Nodes_SelectStatement o,
|
11
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
11
12
|
o.limit = Arel::Nodes::Limit.new(-1) if o.offset && !o.limit
|
12
13
|
super
|
13
14
|
end
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'date'
|
3
|
+
require 'arel/visitors/reduce'
|
3
4
|
|
4
5
|
module Arel
|
5
6
|
module Visitors
|
6
|
-
class ToSql < Arel::Visitors::
|
7
|
+
class ToSql < Arel::Visitors::Reduce
|
7
8
|
##
|
8
9
|
# This is some roflscale crazy stuff. I'm roflscaling this because
|
9
10
|
# building SQL queries is a hotspot. I will explain the roflscale so that
|
@@ -64,13 +65,21 @@ module Arel
|
|
64
65
|
@quoted_columns = {}
|
65
66
|
end
|
66
67
|
|
68
|
+
def compile node, &block
|
69
|
+
accept(node, Arel::Collectors::SQLString.new, &block).value
|
70
|
+
end
|
71
|
+
|
67
72
|
private
|
68
73
|
|
69
|
-
def visit_Arel_Nodes_DeleteStatement o,
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
+
def visit_Arel_Nodes_DeleteStatement o, collector
|
75
|
+
collector << "DELETE FROM "
|
76
|
+
collector = visit o.relation, collector
|
77
|
+
if o.wheres.any?
|
78
|
+
collector << " WHERE "
|
79
|
+
inject_join o.wheres, collector, AND
|
80
|
+
else
|
81
|
+
collector
|
82
|
+
end
|
74
83
|
end
|
75
84
|
|
76
85
|
# FIXME: we should probably have a 2-pass visitor for this
|
@@ -85,43 +94,71 @@ module Arel
|
|
85
94
|
stmt
|
86
95
|
end
|
87
96
|
|
88
|
-
def visit_Arel_Nodes_UpdateStatement o,
|
97
|
+
def visit_Arel_Nodes_UpdateStatement o, collector
|
89
98
|
if o.orders.empty? && o.limit.nil?
|
90
99
|
wheres = o.wheres
|
91
100
|
else
|
92
101
|
wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])]
|
93
102
|
end
|
94
103
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
104
|
+
collector << "UPDATE "
|
105
|
+
collector = visit o.relation, collector
|
106
|
+
unless o.values.empty?
|
107
|
+
collector << " SET "
|
108
|
+
collector = inject_join o.values, collector, ", "
|
109
|
+
end
|
110
|
+
|
111
|
+
unless wheres.empty?
|
112
|
+
collector << " WHERE "
|
113
|
+
collector = inject_join wheres, collector, " AND "
|
114
|
+
end
|
115
|
+
|
116
|
+
collector
|
100
117
|
end
|
101
118
|
|
102
|
-
def visit_Arel_Nodes_InsertStatement o,
|
103
|
-
|
104
|
-
|
119
|
+
def visit_Arel_Nodes_InsertStatement o, collector
|
120
|
+
collector << "INSERT INTO "
|
121
|
+
collector = visit o.relation, collector
|
122
|
+
if o.columns.any?
|
123
|
+
collector << " (#{o.columns.map { |x|
|
124
|
+
quote_column_name x.name
|
125
|
+
}.join ', '})"
|
126
|
+
end
|
105
127
|
|
106
|
-
|
107
|
-
|
108
|
-
|
128
|
+
if o.values
|
129
|
+
maybe_visit o.values, collector
|
130
|
+
elsif o.select
|
131
|
+
maybe_visit o.select, collector
|
132
|
+
else
|
133
|
+
collector
|
134
|
+
end
|
135
|
+
end
|
109
136
|
|
110
|
-
|
111
|
-
|
137
|
+
def visit_Arel_Nodes_Exists o, collector
|
138
|
+
collector << "EXISTS ("
|
139
|
+
collector = visit(o.expressions, collector) << ")"
|
140
|
+
if o.alias
|
141
|
+
collector << " AS "
|
142
|
+
visit o.alias, collector
|
143
|
+
else
|
144
|
+
collector
|
145
|
+
end
|
112
146
|
end
|
113
147
|
|
114
|
-
def
|
115
|
-
|
116
|
-
o.alias ? " AS #{visit o.alias, a}" : ''}"
|
148
|
+
def visit_Arel_Nodes_Casted o, collector
|
149
|
+
collector << quoted(o.val, o.attribute).to_s
|
117
150
|
end
|
118
151
|
|
119
|
-
def
|
120
|
-
|
152
|
+
def visit_Arel_Nodes_Quoted o, collector
|
153
|
+
collector << quoted(o.expr, nil).to_s
|
121
154
|
end
|
122
155
|
|
123
|
-
def
|
124
|
-
"
|
156
|
+
def visit_Arel_Nodes_True o, collector
|
157
|
+
collector << "TRUE"
|
158
|
+
end
|
159
|
+
|
160
|
+
def visit_Arel_Nodes_False o, collector
|
161
|
+
collector << "FALSE"
|
125
162
|
end
|
126
163
|
|
127
164
|
def table_exists? name
|
@@ -142,402 +179,527 @@ module Arel
|
|
142
179
|
@schema_cache.columns_hash(table)
|
143
180
|
end
|
144
181
|
|
145
|
-
def visit_Arel_Nodes_Values o,
|
146
|
-
"VALUES (
|
182
|
+
def visit_Arel_Nodes_Values o, collector
|
183
|
+
collector << "VALUES ("
|
184
|
+
|
185
|
+
len = o.expressions.length - 1
|
186
|
+
o.expressions.zip(o.columns).each_with_index { |(value, attr), i|
|
147
187
|
if Nodes::SqlLiteral === value
|
148
|
-
visit value,
|
188
|
+
collector = visit value, collector
|
149
189
|
else
|
150
|
-
quote(value, attr && column_for(attr))
|
190
|
+
collector << quote(value, attr && column_for(attr)).to_s
|
151
191
|
end
|
152
|
-
|
153
|
-
|
192
|
+
unless i == len
|
193
|
+
collector << ', '
|
194
|
+
end
|
195
|
+
}
|
154
196
|
|
155
|
-
|
156
|
-
|
197
|
+
collector << ")"
|
198
|
+
end
|
157
199
|
|
200
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
158
201
|
if o.with
|
159
|
-
|
160
|
-
|
202
|
+
collector = visit o.with, collector
|
203
|
+
collector << SPACE
|
161
204
|
end
|
162
205
|
|
163
|
-
o.cores.
|
206
|
+
collector = o.cores.inject(collector) { |c,x|
|
207
|
+
visit_Arel_Nodes_SelectCore(x, c)
|
208
|
+
}
|
164
209
|
|
165
210
|
unless o.orders.empty?
|
166
|
-
|
167
|
-
|
211
|
+
collector << SPACE
|
212
|
+
collector << ORDER_BY
|
168
213
|
len = o.orders.length - 1
|
169
214
|
o.orders.each_with_index { |x, i|
|
170
|
-
|
171
|
-
|
215
|
+
collector = visit(x, collector)
|
216
|
+
collector << COMMA unless len == i
|
172
217
|
}
|
173
218
|
end
|
174
219
|
|
175
|
-
|
176
|
-
|
177
|
-
|
220
|
+
collector = maybe_visit o.limit, collector
|
221
|
+
collector = maybe_visit o.offset, collector
|
222
|
+
collector = maybe_visit o.lock, collector
|
178
223
|
|
179
|
-
|
180
|
-
str
|
224
|
+
collector
|
181
225
|
end
|
182
226
|
|
183
|
-
def visit_Arel_Nodes_SelectCore o,
|
184
|
-
|
227
|
+
def visit_Arel_Nodes_SelectCore o, collector
|
228
|
+
collector << "SELECT"
|
185
229
|
|
186
|
-
|
187
|
-
|
230
|
+
if o.top
|
231
|
+
collector << " "
|
232
|
+
collector = visit o.top, collector
|
233
|
+
end
|
234
|
+
|
235
|
+
if o.set_quantifier
|
236
|
+
collector << " "
|
237
|
+
collector = visit o.set_quantifier, collector
|
238
|
+
end
|
188
239
|
|
189
240
|
unless o.projections.empty?
|
190
|
-
|
241
|
+
collector << SPACE
|
191
242
|
len = o.projections.length - 1
|
192
243
|
o.projections.each_with_index do |x, i|
|
193
|
-
|
194
|
-
|
244
|
+
collector = visit(x, collector)
|
245
|
+
collector << COMMA unless len == i
|
195
246
|
end
|
196
247
|
end
|
197
248
|
|
198
|
-
|
249
|
+
if o.source && !o.source.empty?
|
250
|
+
collector << " FROM "
|
251
|
+
collector = visit o.source, collector
|
252
|
+
end
|
199
253
|
|
200
254
|
unless o.wheres.empty?
|
201
|
-
|
255
|
+
collector << WHERE
|
202
256
|
len = o.wheres.length - 1
|
203
257
|
o.wheres.each_with_index do |x, i|
|
204
|
-
|
205
|
-
|
258
|
+
collector = visit(x, collector)
|
259
|
+
collector << AND unless len == i
|
206
260
|
end
|
207
261
|
end
|
208
262
|
|
209
263
|
unless o.groups.empty?
|
210
|
-
|
264
|
+
collector << GROUP_BY
|
211
265
|
len = o.groups.length - 1
|
212
266
|
o.groups.each_with_index do |x, i|
|
213
|
-
|
214
|
-
|
267
|
+
collector = visit(x, collector)
|
268
|
+
collector << COMMA unless len == i
|
215
269
|
end
|
216
270
|
end
|
217
271
|
|
218
|
-
|
272
|
+
if o.having
|
273
|
+
collector << " "
|
274
|
+
collector = visit(o.having, collector)
|
275
|
+
end
|
219
276
|
|
220
277
|
unless o.windows.empty?
|
221
|
-
|
278
|
+
collector << WINDOW
|
222
279
|
len = o.windows.length - 1
|
223
280
|
o.windows.each_with_index do |x, i|
|
224
|
-
|
225
|
-
|
281
|
+
collector = visit(x, collector)
|
282
|
+
collector << COMMA unless len == i
|
226
283
|
end
|
227
284
|
end
|
228
285
|
|
229
|
-
|
286
|
+
collector
|
230
287
|
end
|
231
288
|
|
232
|
-
def visit_Arel_Nodes_Bin o,
|
233
|
-
visit o.expr,
|
289
|
+
def visit_Arel_Nodes_Bin o, collector
|
290
|
+
visit o.expr, collector
|
234
291
|
end
|
235
292
|
|
236
|
-
def visit_Arel_Nodes_Distinct o,
|
237
|
-
DISTINCT
|
293
|
+
def visit_Arel_Nodes_Distinct o, collector
|
294
|
+
collector << DISTINCT
|
238
295
|
end
|
239
296
|
|
240
|
-
def visit_Arel_Nodes_DistinctOn o,
|
297
|
+
def visit_Arel_Nodes_DistinctOn o, collector
|
241
298
|
raise NotImplementedError, 'DISTINCT ON not implemented for this db'
|
242
299
|
end
|
243
300
|
|
244
|
-
def visit_Arel_Nodes_With o,
|
245
|
-
"WITH
|
301
|
+
def visit_Arel_Nodes_With o, collector
|
302
|
+
collector << "WITH "
|
303
|
+
inject_join o.children, collector, ', '
|
246
304
|
end
|
247
305
|
|
248
|
-
def visit_Arel_Nodes_WithRecursive o,
|
249
|
-
"WITH RECURSIVE
|
306
|
+
def visit_Arel_Nodes_WithRecursive o, collector
|
307
|
+
collector << "WITH RECURSIVE "
|
308
|
+
inject_join o.children, collector, ', '
|
250
309
|
end
|
251
310
|
|
252
|
-
def visit_Arel_Nodes_Union o,
|
253
|
-
"(
|
311
|
+
def visit_Arel_Nodes_Union o, collector
|
312
|
+
collector << "( "
|
313
|
+
infix_value(o, collector, " UNION ") << " )"
|
254
314
|
end
|
255
315
|
|
256
|
-
def visit_Arel_Nodes_UnionAll o,
|
257
|
-
"(
|
316
|
+
def visit_Arel_Nodes_UnionAll o, collector
|
317
|
+
collector << "( "
|
318
|
+
infix_value(o, collector, " UNION ALL ") << " )"
|
258
319
|
end
|
259
320
|
|
260
|
-
def visit_Arel_Nodes_Intersect o,
|
261
|
-
"(
|
321
|
+
def visit_Arel_Nodes_Intersect o, collector
|
322
|
+
collector << "( "
|
323
|
+
infix_value(o, collector, " INTERSECT ") << " )"
|
262
324
|
end
|
263
325
|
|
264
|
-
def visit_Arel_Nodes_Except o,
|
265
|
-
"(
|
326
|
+
def visit_Arel_Nodes_Except o, collector
|
327
|
+
collector << "( "
|
328
|
+
infix_value(o, collector, " EXCEPT ") << " )"
|
266
329
|
end
|
267
330
|
|
268
|
-
def visit_Arel_Nodes_NamedWindow o,
|
269
|
-
|
331
|
+
def visit_Arel_Nodes_NamedWindow o, collector
|
332
|
+
collector << quote_column_name(o.name)
|
333
|
+
collector << " AS "
|
334
|
+
visit_Arel_Nodes_Window o, collector
|
270
335
|
end
|
271
336
|
|
272
|
-
def visit_Arel_Nodes_Window o,
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
337
|
+
def visit_Arel_Nodes_Window o, collector
|
338
|
+
collector << "("
|
339
|
+
|
340
|
+
if o.partitions.any?
|
341
|
+
collector << "PARTITION BY "
|
342
|
+
collector = inject_join o.partitions, collector, ", "
|
343
|
+
end
|
344
|
+
|
345
|
+
if o.orders.any?
|
346
|
+
collector << ' ' if o.partitions.any?
|
347
|
+
collector << "ORDER BY "
|
348
|
+
collector = inject_join o.orders, collector, ", "
|
349
|
+
end
|
350
|
+
|
351
|
+
if o.framing
|
352
|
+
collector << ' ' if o.partitions.any? or o.orders.any?
|
353
|
+
collector = visit o.framing, collector
|
354
|
+
end
|
355
|
+
|
356
|
+
collector << ")"
|
278
357
|
end
|
279
358
|
|
280
|
-
def visit_Arel_Nodes_Rows o,
|
359
|
+
def visit_Arel_Nodes_Rows o, collector
|
281
360
|
if o.expr
|
282
|
-
"ROWS
|
361
|
+
collector << "ROWS "
|
362
|
+
visit o.expr, collector
|
283
363
|
else
|
284
|
-
"ROWS"
|
364
|
+
collector << "ROWS"
|
285
365
|
end
|
286
366
|
end
|
287
367
|
|
288
|
-
def visit_Arel_Nodes_Range o,
|
368
|
+
def visit_Arel_Nodes_Range o, collector
|
289
369
|
if o.expr
|
290
|
-
"RANGE
|
370
|
+
collector << "RANGE "
|
371
|
+
visit o.expr, collector
|
291
372
|
else
|
292
|
-
"RANGE"
|
373
|
+
collector << "RANGE"
|
293
374
|
end
|
294
375
|
end
|
295
376
|
|
296
|
-
def visit_Arel_Nodes_Preceding o,
|
297
|
-
|
377
|
+
def visit_Arel_Nodes_Preceding o, collector
|
378
|
+
collector = if o.expr
|
379
|
+
visit o.expr, collector
|
380
|
+
else
|
381
|
+
collector << "UNBOUNDED"
|
382
|
+
end
|
383
|
+
|
384
|
+
collector << " PRECEDING"
|
298
385
|
end
|
299
386
|
|
300
|
-
def visit_Arel_Nodes_Following o,
|
301
|
-
|
387
|
+
def visit_Arel_Nodes_Following o, collector
|
388
|
+
collector = if o.expr
|
389
|
+
visit o.expr, collector
|
390
|
+
else
|
391
|
+
collector << "UNBOUNDED"
|
392
|
+
end
|
393
|
+
|
394
|
+
collector << " FOLLOWING"
|
302
395
|
end
|
303
396
|
|
304
|
-
def visit_Arel_Nodes_CurrentRow o,
|
305
|
-
"CURRENT ROW"
|
397
|
+
def visit_Arel_Nodes_CurrentRow o, collector
|
398
|
+
collector << "CURRENT ROW"
|
306
399
|
end
|
307
400
|
|
308
|
-
def visit_Arel_Nodes_Over o,
|
401
|
+
def visit_Arel_Nodes_Over o, collector
|
309
402
|
case o.right
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
403
|
+
when nil
|
404
|
+
visit(o.left, collector) << " OVER ()"
|
405
|
+
when Arel::Nodes::SqlLiteral
|
406
|
+
infix_value o, collector, " OVER "
|
407
|
+
when String, Symbol
|
408
|
+
visit(o.left, collector) << " OVER #{quote_column_name o.right.to_s}"
|
409
|
+
else
|
410
|
+
infix_value o, collector, " OVER "
|
318
411
|
end
|
319
412
|
end
|
320
413
|
|
321
|
-
def visit_Arel_Nodes_Having o,
|
322
|
-
"HAVING
|
414
|
+
def visit_Arel_Nodes_Having o, collector
|
415
|
+
collector << "HAVING "
|
416
|
+
visit o.expr, collector
|
323
417
|
end
|
324
418
|
|
325
|
-
def visit_Arel_Nodes_Offset o,
|
326
|
-
"OFFSET
|
419
|
+
def visit_Arel_Nodes_Offset o, collector
|
420
|
+
collector << "OFFSET "
|
421
|
+
visit o.expr, collector
|
327
422
|
end
|
328
423
|
|
329
|
-
def visit_Arel_Nodes_Limit o,
|
330
|
-
"LIMIT
|
424
|
+
def visit_Arel_Nodes_Limit o, collector
|
425
|
+
collector << "LIMIT "
|
426
|
+
visit o.expr, collector
|
331
427
|
end
|
332
428
|
|
333
429
|
# FIXME: this does nothing on most databases, but does on MSSQL
|
334
|
-
def visit_Arel_Nodes_Top o,
|
335
|
-
|
430
|
+
def visit_Arel_Nodes_Top o, collector
|
431
|
+
collector
|
336
432
|
end
|
337
433
|
|
338
|
-
def visit_Arel_Nodes_Lock o,
|
339
|
-
visit o.expr,
|
434
|
+
def visit_Arel_Nodes_Lock o, collector
|
435
|
+
visit o.expr, collector
|
340
436
|
end
|
341
437
|
|
342
|
-
def visit_Arel_Nodes_Grouping o,
|
343
|
-
|
438
|
+
def visit_Arel_Nodes_Grouping o, collector
|
439
|
+
collector << "("
|
440
|
+
visit(o.expr, collector) << ")"
|
344
441
|
end
|
345
442
|
|
346
|
-
def visit_Arel_SelectManager o,
|
347
|
-
"(#{o.to_sql.rstrip})"
|
443
|
+
def visit_Arel_SelectManager o, collector
|
444
|
+
collector << "(#{o.to_sql.rstrip})"
|
348
445
|
end
|
349
446
|
|
350
|
-
def visit_Arel_Nodes_Ascending o,
|
351
|
-
|
447
|
+
def visit_Arel_Nodes_Ascending o, collector
|
448
|
+
visit(o.expr, collector) << " ASC"
|
352
449
|
end
|
353
450
|
|
354
|
-
def visit_Arel_Nodes_Descending o,
|
355
|
-
|
451
|
+
def visit_Arel_Nodes_Descending o, collector
|
452
|
+
visit(o.expr, collector) << " DESC"
|
356
453
|
end
|
357
454
|
|
358
|
-
def visit_Arel_Nodes_Group o,
|
359
|
-
visit o.expr,
|
455
|
+
def visit_Arel_Nodes_Group o, collector
|
456
|
+
visit o.expr, collector
|
360
457
|
end
|
361
458
|
|
362
|
-
def visit_Arel_Nodes_NamedFunction o,
|
363
|
-
|
364
|
-
|
365
|
-
|
459
|
+
def visit_Arel_Nodes_NamedFunction o, collector
|
460
|
+
collector << o.name
|
461
|
+
collector << "("
|
462
|
+
collector << "DISTINCT " if o.distinct
|
463
|
+
collector = inject_join(o.expressions, collector, ", ") << ")"
|
464
|
+
if o.alias
|
465
|
+
collector << " AS "
|
466
|
+
visit o.alias, collector
|
467
|
+
else
|
468
|
+
collector
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def visit_Arel_Nodes_Extract o, collector
|
473
|
+
collector << "EXTRACT(#{o.field.to_s.upcase} FROM "
|
474
|
+
collector = visit o.expr, collector
|
475
|
+
collector << ")"
|
476
|
+
if o.alias
|
477
|
+
collector << " AS "
|
478
|
+
visit o.alias, collector
|
479
|
+
else
|
480
|
+
collector
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
def visit_Arel_Nodes_Count o, collector
|
485
|
+
aggregate "COUNT", o, collector
|
486
|
+
end
|
487
|
+
|
488
|
+
def visit_Arel_Nodes_Sum o, collector
|
489
|
+
aggregate "SUM", o, collector
|
366
490
|
end
|
367
491
|
|
368
|
-
def
|
369
|
-
"
|
492
|
+
def visit_Arel_Nodes_Max o, collector
|
493
|
+
aggregate "MAX", o, collector
|
370
494
|
end
|
371
495
|
|
372
|
-
def
|
373
|
-
"
|
374
|
-
visit x, a
|
375
|
-
}.join(', ')})#{o.alias ? " AS #{visit o.alias, a}" : ''}"
|
496
|
+
def visit_Arel_Nodes_Min o, collector
|
497
|
+
aggregate "MIN", o, collector
|
376
498
|
end
|
377
499
|
|
378
|
-
def
|
379
|
-
"
|
380
|
-
visit x, a }.join(', ')})#{o.alias ? " AS #{visit o.alias, a}" : ''}"
|
500
|
+
def visit_Arel_Nodes_Avg o, collector
|
501
|
+
aggregate "AVG", o, collector
|
381
502
|
end
|
382
503
|
|
383
|
-
def
|
384
|
-
|
385
|
-
|
504
|
+
def visit_Arel_Nodes_TableAlias o, collector
|
505
|
+
collector = visit o.relation, collector
|
506
|
+
collector << " "
|
507
|
+
collector << quote_table_name(o.name)
|
386
508
|
end
|
387
509
|
|
388
|
-
def
|
389
|
-
|
390
|
-
|
510
|
+
def visit_Arel_Nodes_Between o, collector
|
511
|
+
collector = visit o.left, collector
|
512
|
+
collector << " BETWEEN "
|
513
|
+
visit o.right, collector
|
391
514
|
end
|
392
515
|
|
393
|
-
def
|
394
|
-
|
395
|
-
|
516
|
+
def visit_Arel_Nodes_GreaterThanOrEqual o, collector
|
517
|
+
collector = visit o.left, collector
|
518
|
+
collector << " >= "
|
519
|
+
visit o.right, collector
|
396
520
|
end
|
397
521
|
|
398
|
-
def
|
399
|
-
|
522
|
+
def visit_Arel_Nodes_GreaterThan o, collector
|
523
|
+
collector = visit o.left, collector
|
524
|
+
collector << " > "
|
525
|
+
visit o.right, collector
|
400
526
|
end
|
401
527
|
|
402
|
-
def
|
403
|
-
|
404
|
-
|
528
|
+
def visit_Arel_Nodes_LessThanOrEqual o, collector
|
529
|
+
collector = visit o.left, collector
|
530
|
+
collector << " <= "
|
531
|
+
visit o.right, collector
|
405
532
|
end
|
406
533
|
|
407
|
-
def
|
408
|
-
|
409
|
-
|
534
|
+
def visit_Arel_Nodes_LessThan o, collector
|
535
|
+
collector = visit o.left, collector
|
536
|
+
collector << " < "
|
537
|
+
visit o.right, collector
|
410
538
|
end
|
411
539
|
|
412
|
-
def
|
413
|
-
|
414
|
-
|
540
|
+
def visit_Arel_Nodes_Matches o, collector
|
541
|
+
collector = visit o.left, collector
|
542
|
+
collector << " LIKE "
|
543
|
+
visit o.right, collector
|
415
544
|
end
|
416
545
|
|
417
|
-
def
|
418
|
-
|
419
|
-
|
546
|
+
def visit_Arel_Nodes_DoesNotMatch o, collector
|
547
|
+
collector = visit o.left, collector
|
548
|
+
collector << " NOT LIKE "
|
549
|
+
visit o.right, collector
|
420
550
|
end
|
421
551
|
|
422
|
-
def
|
423
|
-
|
424
|
-
|
552
|
+
def visit_Arel_Nodes_JoinSource o, collector
|
553
|
+
if o.left
|
554
|
+
collector = visit o.left, collector
|
555
|
+
end
|
556
|
+
if o.right.any?
|
557
|
+
collector << " " if o.left
|
558
|
+
collector = inject_join o.right, collector, ' '
|
559
|
+
end
|
560
|
+
collector
|
425
561
|
end
|
426
562
|
|
427
|
-
def
|
428
|
-
|
429
|
-
"#{visit o.left, a} LIKE #{visit o.right, a}"
|
563
|
+
def visit_Arel_Nodes_Regexp o, collector
|
564
|
+
raise NotImplementedError, '~ not implemented for this db'
|
430
565
|
end
|
431
566
|
|
432
|
-
def
|
433
|
-
|
434
|
-
"#{visit o.left, a} NOT LIKE #{visit o.right, a}"
|
567
|
+
def visit_Arel_Nodes_NotRegexp o, collector
|
568
|
+
raise NotImplementedError, '!~ not implemented for this db'
|
435
569
|
end
|
436
570
|
|
437
|
-
def
|
438
|
-
|
439
|
-
(visit(o.left, a) if o.left),
|
440
|
-
o.right.map { |j| visit j, a }.join(' ')
|
441
|
-
].compact.join ' '
|
571
|
+
def visit_Arel_Nodes_StringJoin o, collector
|
572
|
+
visit o.left, collector
|
442
573
|
end
|
443
574
|
|
444
|
-
def
|
445
|
-
visit o.left
|
575
|
+
def visit_Arel_Nodes_FullOuterJoin o
|
576
|
+
"FULL OUTER JOIN #{visit o.left} #{visit o.right}"
|
446
577
|
end
|
447
578
|
|
448
|
-
def visit_Arel_Nodes_OuterJoin o,
|
449
|
-
"LEFT OUTER JOIN
|
579
|
+
def visit_Arel_Nodes_OuterJoin o, collector
|
580
|
+
collector << "LEFT OUTER JOIN "
|
581
|
+
collector = visit o.left, collector
|
582
|
+
collector << " "
|
583
|
+
visit o.right, collector
|
450
584
|
end
|
451
585
|
|
452
|
-
def
|
453
|
-
|
586
|
+
def visit_Arel_Nodes_RightOuterJoin o
|
587
|
+
"RIGHT OUTER JOIN #{visit o.left} #{visit o.right}"
|
588
|
+
end
|
589
|
+
|
590
|
+
def visit_Arel_Nodes_InnerJoin o, collector
|
591
|
+
collector << "INNER JOIN "
|
592
|
+
collector = visit o.left, collector
|
454
593
|
if o.right
|
455
|
-
|
456
|
-
|
594
|
+
collector << SPACE
|
595
|
+
visit(o.right, collector)
|
596
|
+
else
|
597
|
+
collector
|
457
598
|
end
|
458
|
-
s
|
459
599
|
end
|
460
600
|
|
461
|
-
def visit_Arel_Nodes_On o,
|
462
|
-
"ON
|
601
|
+
def visit_Arel_Nodes_On o, collector
|
602
|
+
collector << "ON "
|
603
|
+
visit o.expr, collector
|
463
604
|
end
|
464
605
|
|
465
|
-
def visit_Arel_Nodes_Not o,
|
466
|
-
"NOT (
|
606
|
+
def visit_Arel_Nodes_Not o, collector
|
607
|
+
collector << "NOT ("
|
608
|
+
visit(o.expr, collector) << ")"
|
467
609
|
end
|
468
610
|
|
469
|
-
def visit_Arel_Table o,
|
611
|
+
def visit_Arel_Table o, collector
|
470
612
|
if o.table_alias
|
471
|
-
"#{quote_table_name o.name} #{quote_table_name o.table_alias}"
|
613
|
+
collector << "#{quote_table_name o.name} #{quote_table_name o.table_alias}"
|
472
614
|
else
|
473
|
-
quote_table_name
|
615
|
+
collector << quote_table_name(o.name)
|
474
616
|
end
|
475
617
|
end
|
476
618
|
|
477
|
-
def visit_Arel_Nodes_In o,
|
619
|
+
def visit_Arel_Nodes_In o, collector
|
478
620
|
if Array === o.right && o.right.empty?
|
479
|
-
'1=0'
|
621
|
+
collector << '1=0'
|
480
622
|
else
|
481
|
-
|
482
|
-
|
623
|
+
collector = visit o.left, collector
|
624
|
+
collector << " IN ("
|
625
|
+
visit(o.right, collector) << ")"
|
483
626
|
end
|
484
627
|
end
|
485
628
|
|
486
|
-
def visit_Arel_Nodes_NotIn o,
|
629
|
+
def visit_Arel_Nodes_NotIn o, collector
|
487
630
|
if Array === o.right && o.right.empty?
|
488
|
-
'1=1'
|
631
|
+
collector << '1=1'
|
489
632
|
else
|
490
|
-
|
491
|
-
|
633
|
+
collector = visit o.left, collector
|
634
|
+
collector << " NOT IN ("
|
635
|
+
collector = visit o.right, collector
|
636
|
+
collector << ")"
|
492
637
|
end
|
493
638
|
end
|
494
639
|
|
495
|
-
def visit_Arel_Nodes_And o,
|
496
|
-
o.children
|
640
|
+
def visit_Arel_Nodes_And o, collector
|
641
|
+
inject_join o.children, collector, " AND "
|
497
642
|
end
|
498
643
|
|
499
|
-
def visit_Arel_Nodes_Or o,
|
500
|
-
|
644
|
+
def visit_Arel_Nodes_Or o, collector
|
645
|
+
collector = visit o.left, collector
|
646
|
+
collector << " OR "
|
647
|
+
visit o.right, collector
|
501
648
|
end
|
502
649
|
|
503
|
-
def visit_Arel_Nodes_Assignment o,
|
504
|
-
|
505
|
-
|
650
|
+
def visit_Arel_Nodes_Assignment o, collector
|
651
|
+
case o.right
|
652
|
+
when Arel::Nodes::UnqualifiedColumn, Arel::Attributes::Attribute, Arel::Nodes::BindParam
|
653
|
+
collector = visit o.left, collector
|
654
|
+
collector << " = "
|
655
|
+
visit o.right, collector
|
656
|
+
else
|
657
|
+
collector = visit o.left, collector
|
658
|
+
collector << " = "
|
659
|
+
collector << quote(o.right, column_for(o.left)).to_s
|
660
|
+
end
|
506
661
|
end
|
507
662
|
|
508
|
-
def visit_Arel_Nodes_Equality o,
|
663
|
+
def visit_Arel_Nodes_Equality o, collector
|
509
664
|
right = o.right
|
510
665
|
|
511
|
-
|
666
|
+
collector = visit o.left, collector
|
667
|
+
|
512
668
|
if right.nil?
|
513
|
-
|
669
|
+
collector << " IS NULL"
|
514
670
|
else
|
515
|
-
|
671
|
+
collector << " = "
|
672
|
+
visit right, collector
|
516
673
|
end
|
517
674
|
end
|
518
675
|
|
519
|
-
def visit_Arel_Nodes_NotEqual o,
|
676
|
+
def visit_Arel_Nodes_NotEqual o, collector
|
520
677
|
right = o.right
|
521
678
|
|
522
|
-
|
679
|
+
collector = visit o.left, collector
|
680
|
+
|
523
681
|
if right.nil?
|
524
|
-
|
682
|
+
collector << " IS NOT NULL"
|
525
683
|
else
|
526
|
-
|
684
|
+
collector << " != "
|
685
|
+
visit right, collector
|
527
686
|
end
|
528
687
|
end
|
529
688
|
|
530
|
-
def visit_Arel_Nodes_As o,
|
531
|
-
|
689
|
+
def visit_Arel_Nodes_As o, collector
|
690
|
+
collector = visit o.left, collector
|
691
|
+
collector << " AS "
|
692
|
+
visit o.right, collector
|
532
693
|
end
|
533
694
|
|
534
|
-
def visit_Arel_Nodes_UnqualifiedColumn o,
|
535
|
-
"#{quote_column_name o.name}"
|
695
|
+
def visit_Arel_Nodes_UnqualifiedColumn o, collector
|
696
|
+
collector << "#{quote_column_name o.name}"
|
697
|
+
collector
|
536
698
|
end
|
537
699
|
|
538
|
-
def visit_Arel_Attributes_Attribute o,
|
700
|
+
def visit_Arel_Attributes_Attribute o, collector
|
539
701
|
join_name = o.relation.table_alias || o.relation.name
|
540
|
-
"#{quote_table_name join_name}.#{quote_column_name o.name}"
|
702
|
+
collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
|
541
703
|
end
|
542
704
|
alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute
|
543
705
|
alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute
|
@@ -546,11 +708,13 @@ module Arel
|
|
546
708
|
alias :visit_Arel_Attributes_Time :visit_Arel_Attributes_Attribute
|
547
709
|
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
|
548
710
|
|
549
|
-
def literal o,
|
711
|
+
def literal o, collector; collector << o.to_s; end
|
712
|
+
|
713
|
+
def visit_Arel_Nodes_BindParam o, collector
|
714
|
+
collector.add_bind o
|
715
|
+
end
|
550
716
|
|
551
|
-
alias :visit_Arel_Nodes_BindParam :literal
|
552
717
|
alias :visit_Arel_Nodes_SqlLiteral :literal
|
553
|
-
alias :visit_Arel_SqlLiteral :literal # This is deprecated
|
554
718
|
alias :visit_Bignum :literal
|
555
719
|
alias :visit_Fixnum :literal
|
556
720
|
|
@@ -558,23 +722,29 @@ module Arel
|
|
558
722
|
quote(o, column_for(a))
|
559
723
|
end
|
560
724
|
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
alias :
|
566
|
-
alias :
|
567
|
-
alias :
|
568
|
-
alias :
|
569
|
-
alias :
|
570
|
-
alias :
|
571
|
-
alias :
|
572
|
-
alias :
|
573
|
-
alias :
|
574
|
-
alias :
|
725
|
+
def unsupported o, collector
|
726
|
+
raise "unsupported: #{o.class.name}"
|
727
|
+
end
|
728
|
+
|
729
|
+
alias :visit_ActiveSupport_Multibyte_Chars :unsupported
|
730
|
+
alias :visit_ActiveSupport_StringInquirer :unsupported
|
731
|
+
alias :visit_BigDecimal :unsupported
|
732
|
+
alias :visit_Class :unsupported
|
733
|
+
alias :visit_Date :unsupported
|
734
|
+
alias :visit_DateTime :unsupported
|
735
|
+
alias :visit_FalseClass :unsupported
|
736
|
+
alias :visit_Float :unsupported
|
737
|
+
alias :visit_Hash :unsupported
|
738
|
+
alias :visit_NilClass :unsupported
|
739
|
+
alias :visit_String :unsupported
|
740
|
+
alias :visit_Symbol :unsupported
|
741
|
+
alias :visit_Time :unsupported
|
742
|
+
alias :visit_TrueClass :unsupported
|
575
743
|
|
576
|
-
def visit_Arel_Nodes_InfixOperation o,
|
577
|
-
|
744
|
+
def visit_Arel_Nodes_InfixOperation o, collector
|
745
|
+
collector = visit o.left, collector
|
746
|
+
collector << " #{o.operator} "
|
747
|
+
visit o.right, collector
|
578
748
|
end
|
579
749
|
|
580
750
|
alias :visit_Arel_Nodes_Addition :visit_Arel_Nodes_InfixOperation
|
@@ -582,8 +752,8 @@ module Arel
|
|
582
752
|
alias :visit_Arel_Nodes_Multiplication :visit_Arel_Nodes_InfixOperation
|
583
753
|
alias :visit_Arel_Nodes_Division :visit_Arel_Nodes_InfixOperation
|
584
754
|
|
585
|
-
def visit_Array o,
|
586
|
-
o
|
755
|
+
def visit_Array o, collector
|
756
|
+
inject_join o, collector, ", "
|
587
757
|
end
|
588
758
|
|
589
759
|
def quote value, column = nil
|
@@ -599,6 +769,43 @@ module Arel
|
|
599
769
|
def quote_column_name name
|
600
770
|
@quoted_columns[name] ||= Arel::Nodes::SqlLiteral === name ? name : @connection.quote_column_name(name)
|
601
771
|
end
|
772
|
+
|
773
|
+
def maybe_visit thing, collector
|
774
|
+
return collector unless thing
|
775
|
+
collector << " "
|
776
|
+
visit thing, collector
|
777
|
+
end
|
778
|
+
|
779
|
+
def inject_join list, collector, join_str
|
780
|
+
len = list.length - 1
|
781
|
+
list.each_with_index.inject(collector) { |c, (x,i)|
|
782
|
+
if i == len
|
783
|
+
visit x, c
|
784
|
+
else
|
785
|
+
visit(x, c) << join_str
|
786
|
+
end
|
787
|
+
}
|
788
|
+
end
|
789
|
+
|
790
|
+
def infix_value o, collector, value
|
791
|
+
collector = visit o.left, collector
|
792
|
+
collector << value
|
793
|
+
visit o.right, collector
|
794
|
+
end
|
795
|
+
|
796
|
+
def aggregate name, o, collector
|
797
|
+
collector << "#{name}("
|
798
|
+
if o.distinct
|
799
|
+
collector << "DISTINCT "
|
800
|
+
end
|
801
|
+
collector = inject_join(o.expressions, collector, ", ") << ")"
|
802
|
+
if o.alias
|
803
|
+
collector << " AS "
|
804
|
+
visit o.alias, collector
|
805
|
+
else
|
806
|
+
collector
|
807
|
+
end
|
808
|
+
end
|
602
809
|
end
|
603
810
|
end
|
604
811
|
end
|