arel_extensions 2.0.0 → 2.0.10

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +59 -91
  4. data/Gemfile +14 -19
  5. data/README.md +17 -12
  6. data/Rakefile +38 -27
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +2 -2
  9. data/functions.html +3 -3
  10. data/gemfiles/rails4.gemfile +1 -1
  11. data/gemfiles/rails6.gemfile +30 -0
  12. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  13. data/generate_gems.sh +14 -0
  14. data/init/mssql.sql +4 -4
  15. data/init/mysql.sql +38 -38
  16. data/init/postgresql.sql +21 -21
  17. data/lib/arel_extensions.rb +63 -19
  18. data/lib/arel_extensions/attributes.rb +0 -1
  19. data/lib/arel_extensions/boolean_functions.rb +38 -13
  20. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  21. data/lib/arel_extensions/comparators.rb +4 -2
  22. data/lib/arel_extensions/insert_manager.rb +15 -13
  23. data/lib/arel_extensions/math.rb +3 -3
  24. data/lib/arel_extensions/math_functions.rb +10 -5
  25. data/lib/arel_extensions/nodes.rb +1 -1
  26. data/lib/arel_extensions/nodes/abs.rb +0 -0
  27. data/lib/arel_extensions/nodes/aggregate_function.rb +14 -0
  28. data/lib/arel_extensions/nodes/case.rb +8 -4
  29. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  30. data/lib/arel_extensions/nodes/coalesce.rb +2 -2
  31. data/lib/arel_extensions/nodes/collate.rb +1 -1
  32. data/lib/arel_extensions/nodes/concat.rb +6 -13
  33. data/lib/arel_extensions/nodes/date_diff.rb +3 -5
  34. data/lib/arel_extensions/nodes/duration.rb +0 -2
  35. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  36. data/lib/arel_extensions/nodes/floor.rb +0 -0
  37. data/lib/arel_extensions/nodes/format.rb +8 -8
  38. data/lib/arel_extensions/nodes/formatted_number.rb +23 -23
  39. data/lib/arel_extensions/nodes/function.rb +2 -0
  40. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  41. data/lib/arel_extensions/nodes/json.rb +28 -30
  42. data/lib/arel_extensions/nodes/length.rb +0 -0
  43. data/lib/arel_extensions/nodes/locate.rb +0 -0
  44. data/lib/arel_extensions/nodes/matches.rb +4 -4
  45. data/lib/arel_extensions/nodes/power.rb +6 -5
  46. data/lib/arel_extensions/nodes/rand.rb +0 -0
  47. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  48. data/lib/arel_extensions/nodes/replace.rb +24 -6
  49. data/lib/arel_extensions/nodes/round.rb +5 -5
  50. data/lib/arel_extensions/nodes/soundex.rb +16 -15
  51. data/lib/arel_extensions/nodes/std.rb +19 -21
  52. data/lib/arel_extensions/nodes/substring.rb +8 -15
  53. data/lib/arel_extensions/nodes/sum.rb +7 -0
  54. data/lib/arel_extensions/nodes/trim.rb +3 -3
  55. data/lib/arel_extensions/nodes/union.rb +2 -3
  56. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  57. data/lib/arel_extensions/nodes/wday.rb +0 -0
  58. data/lib/arel_extensions/null_functions.rb +2 -2
  59. data/lib/arel_extensions/predications.rb +35 -33
  60. data/lib/arel_extensions/set_functions.rb +2 -2
  61. data/lib/arel_extensions/string_functions.rb +34 -12
  62. data/lib/arel_extensions/tasks.rb +5 -5
  63. data/lib/arel_extensions/version.rb +1 -1
  64. data/lib/arel_extensions/visitors.rb +1 -1
  65. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  66. data/lib/arel_extensions/visitors/mssql.rb +14 -13
  67. data/lib/arel_extensions/visitors/mysql.rb +90 -37
  68. data/lib/arel_extensions/visitors/oracle.rb +15 -15
  69. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  70. data/lib/arel_extensions/visitors/postgresql.rb +78 -32
  71. data/lib/arel_extensions/visitors/sqlite.rb +61 -53
  72. data/lib/arel_extensions/visitors/to_sql.rb +70 -58
  73. data/test/arelx_test_helper.rb +28 -0
  74. data/test/real_db_test.rb +1 -1
  75. data/test/support/fake_record.rb +1 -1
  76. data/test/test_comparators.rb +9 -8
  77. data/test/visitors/test_bulk_insert_oracle.rb +8 -7
  78. data/test/visitors/test_bulk_insert_sqlite.rb +9 -8
  79. data/test/visitors/test_bulk_insert_to_sql.rb +8 -10
  80. data/test/visitors/test_oracle.rb +41 -40
  81. data/test/visitors/test_to_sql.rb +367 -193
  82. data/test/with_ar/all_agnostic_test.rb +68 -35
  83. data/test/with_ar/insert_agnostic_test.rb +3 -2
  84. data/test/with_ar/test_bulk_sqlite.rb +6 -5
  85. data/test/with_ar/test_math_sqlite.rb +4 -4
  86. data/test/with_ar/test_string_mysql.rb +4 -6
  87. data/test/with_ar/test_string_sqlite.rb +3 -7
  88. data/version_v1.rb +3 -0
  89. data/version_v2.rb +3 -0
  90. metadata +14 -7
  91. data/test/helper.rb +0 -18
@@ -68,7 +68,7 @@ module ArelExtensions
68
68
  if i != 0
69
69
  collector << Arel::Visitors::MySQL::COMMA
70
70
  end
71
- collector = visit v, collector
71
+ collector = visit v, collector
72
72
  end
73
73
  collector << ')'
74
74
  when Hash
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::PostgreSQL.class_eval do
3
+ class Arel::Visitors::PostgreSQL
4
4
  Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
5
  Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
6
6
  '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
@@ -83,23 +83,49 @@ module ArelExtensions
83
83
  collector
84
84
  end
85
85
 
86
+ def visit_Aggregate_For_AggregateFunction o, collector
87
+ if !o.order.blank? || !o.group.blank?
88
+ collector << " OVER ("
89
+ if !o.group.blank?
90
+ collector << " PARTITION BY "
91
+ o.group.each_with_index do |group, i|
92
+ collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
93
+ visit group, collector
94
+ end
95
+ end
96
+ if !o.order.blank?
97
+ collector << " ORDER BY "
98
+ o.order.each_with_index do |order, i|
99
+ collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
100
+ visit order, collector
101
+ end
102
+ end
103
+ collector << ")"
104
+ end
105
+ collector
106
+ end
107
+
86
108
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
87
109
  collector << "array_to_string(array_agg("
88
110
  collector = visit o.left, collector
89
- if !o.orders.blank?
90
- collector << ' ORDER BY '
91
- o.orders.each_with_index do |order,i|
111
+ if o.order && !o.order.blank?
112
+ collector << " ORDER BY"
113
+ o.order.each_with_index do |order, i|
92
114
  collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
93
- collector = visit order, collector
115
+ collector << " "
116
+ visit order, collector
94
117
  end
95
118
  end
96
119
  collector << ")"
120
+ o.order = nil
121
+ visit_Aggregate_For_AggregateFunction o, collector
97
122
  collector << Arel::Visitors::PostgreSQL::COMMA
98
- if o.right && o.right != 'NULL'
99
- collector = visit o.right, collector
100
- else
101
- collector = visit Arel::Nodes.build_quoted(','), collector
102
- end
123
+ collector =
124
+ if o.separator && o.separator != 'NULL'
125
+ visit o.separator, collector
126
+ else
127
+ visit Arel::Nodes.build_quoted(','), collector
128
+ end
103
129
  collector << ")"
104
130
  collector
105
131
  end
@@ -277,6 +303,22 @@ module ArelExtensions
277
303
  collector
278
304
  end
279
305
 
306
+ def visit_ArelExtensions_Nodes_RegexpReplace o, collector
307
+ collector << "REGEXP_REPLACE("
308
+ visit o.left, collector
309
+ collector << Arel::Visitors::ToSql::COMMA
310
+ tab = o.pattern.inspect+ 'g' # Make it always global
311
+ pattern = tab.split('/')[1..-2].join('/')
312
+ flags = tab.split('/')[-1]
313
+ visit Arel::Nodes.build_quoted(pattern), collector
314
+ collector << Arel::Visitors::ToSql::COMMA
315
+ visit o.substitute, collector
316
+ collector << Arel::Visitors::ToSql::COMMA
317
+ visit Arel::Nodes.build_quoted(flags+"g"), collector
318
+ collector << ")"
319
+ collector
320
+ end
321
+
280
322
  def visit_ArelExtensions_Nodes_IsNull o, collector
281
323
  collector = visit o.expr, collector
282
324
  collector << ' IS NULL'
@@ -293,6 +335,7 @@ module ArelExtensions
293
335
  collector << "sum("
294
336
  collector = visit o.expr, collector
295
337
  collector << ")"
338
+ visit_Aggregate_For_AggregateFunction o, collector
296
339
  collector
297
340
  end
298
341
 
@@ -345,27 +388,28 @@ module ArelExtensions
345
388
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
346
389
  sign_length = ArelExtensions::Nodes::Length.new([sign])
347
390
 
348
- if o.scientific_notation
349
- number = ArelExtensions::Nodes::Concat.new([
350
- Arel::Nodes::NamedFunction.new('TRIM',[
351
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
352
- col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
353
- Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
354
- ])]),
355
- o.type,
356
- Arel::Nodes::NamedFunction.new('TRIM',[
357
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
358
- col.abs.log10.floor,
359
- Arel::Nodes.build_quoted('FM'+nines_before)
360
- ])])
361
- ])
362
- else
363
- number = Arel::Nodes::NamedFunction.new('TRIM',[
364
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
365
- Arel::Nodes.build_quoted(col.abs),
366
- Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
367
- ])])
368
- end
391
+ number =
392
+ if o.scientific_notation
393
+ ArelExtensions::Nodes::Concat.new([
394
+ Arel::Nodes::NamedFunction.new('TRIM',[
395
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
396
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
397
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
398
+ ])]),
399
+ o.type,
400
+ Arel::Nodes::NamedFunction.new('TRIM',[
401
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
402
+ col.abs.log10.floor,
403
+ Arel::Nodes.build_quoted('FM'+nines_before)
404
+ ])])
405
+ ])
406
+ else
407
+ Arel::Nodes::NamedFunction.new('TRIM',[
408
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
409
+ Arel::Nodes.build_quoted(col.abs),
410
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
411
+ ])])
412
+ end
369
413
 
370
414
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
371
415
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -420,6 +464,7 @@ module ArelExtensions
420
464
  collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
421
465
  visit o.left, collector
422
466
  collector << ")"
467
+ visit_Aggregate_For_AggregateFunction o, collector
423
468
  collector
424
469
  end
425
470
 
@@ -427,6 +472,7 @@ module ArelExtensions
427
472
  collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
428
473
  visit o.left, collector
429
474
  collector << ")"
475
+ visit_Aggregate_For_AggregateFunction o, collector
430
476
  collector
431
477
  end
432
478
 
@@ -438,7 +484,7 @@ module ArelExtensions
438
484
  if i != 0
439
485
  collector << Arel::Visitors::MySQL::COMMA
440
486
  end
441
- collector = visit v, collector
487
+ collector = visit v, collector
442
488
  end
443
489
  collector << '])'
444
490
  when Hash
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::SQLite.class_eval do
3
+ class Arel::Visitors::SQLite
4
4
  Arel::Visitors::SQLite::DATE_MAPPING = {'d' => '%d', 'm' => '%m', 'w' => '%W', 'y' => '%Y', 'wd' => '%w', 'M' => '%M', 'h' => '%H', 'mn' => '%M', 's' => '%S'}
5
5
  Arel::Visitors::SQLite::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
6
6
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
@@ -193,18 +193,28 @@ module ArelExtensions
193
193
  collector
194
194
  end
195
195
 
196
- # CASE WHEN ROUND(3.42,1) > round(3.42) THEN round(3.42) ELSE round(3.42)-1 END
197
- # OR CAST(3.14 AS INTEGER)
196
+ # CAST(
197
+ # CASE
198
+ # WHEN 3.42 >= 0 THEN CAST(3.42 AS INT)
199
+ # WHEN CAST(3.42 AS INT) = 3.42 THEN CAST(3.42 AS INT)
200
+ # ELSE CAST((3.42 - 1.0) AS INT)
201
+ # END
202
+ # AS FLOAT
203
+ # )
198
204
  def visit_ArelExtensions_Nodes_Floor o, collector
199
- collector << "CASE WHEN ROUND("
205
+ collector << "CAST(CASE WHEN "
200
206
  collector = visit o.left, collector
201
- collector << ", 1) > ROUND("
207
+ collector << " >= 0 THEN CAST("
202
208
  collector = visit o.left, collector
203
- collector << ") THEN ROUND("
209
+ collector << " AS INT) WHEN CAST("
204
210
  collector = visit o.left, collector
205
- collector << ") ELSE ROUND("
211
+ collector << " AS INT) = "
206
212
  collector = visit o.left, collector
207
- collector << ") - 1 END"
213
+ collector << " THEN CAST("
214
+ collector = visit o.left, collector
215
+ collector << " AS INT) ELSE CAST(("
216
+ collector = visit o.left, collector
217
+ collector << " - 1.0) AS INT) END AS FLOAT)"
208
218
  collector
209
219
  end
210
220
 
@@ -225,9 +235,8 @@ module ArelExtensions
225
235
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
226
236
  o.left.each_with_index do |row, idx|
227
237
  collector << 'SELECT '
228
- v = Arel::Nodes::Values.new(row, o.cols)
229
- len = v.expressions.length - 1
230
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
238
+ len = row.length - 1
239
+ row.zip(o.cols).each_with_index { |(value, attr), i|
231
240
  case value
232
241
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
233
242
  collector = visit value.as(attr.name), collector
@@ -249,19 +258,24 @@ module ArelExtensions
249
258
  o.left.each_with_index do |row, idx|
250
259
  collector << 'SELECT '
251
260
  len = row.length - 1
252
- row.each_with_index { |value, i|
253
- attr = o.cols[i]
254
- case value
255
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
256
- collector = visit value.as(attr.name), collector
257
- else
258
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
259
- if idx == 0
260
- collector << " AS "
261
- collector << quote(attr.name)
261
+ row.zip(o.cols).each_with_index { |(value, attr), i|
262
+ case value
263
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
264
+ collector = visit value.as(attr.name), collector
265
+ when Integer
266
+ collector << value.to_s
267
+ if idx == 0
268
+ collector << " AS "
269
+ collector << quote(attr.name)
270
+ end
271
+ else
272
+ collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
273
+ if idx == 0
274
+ collector << " AS "
275
+ collector << quote(attr.name)
276
+ end
262
277
  end
263
- end
264
- collector << Arel::Visitors::SQLite::COMMA unless i == len
278
+ collector << Arel::Visitors::SQLite::COMMA unless i == len
265
279
  }
266
280
  collector << ' UNION ALL ' unless idx == o.left.length - 1
267
281
  end
@@ -270,32 +284,36 @@ module ArelExtensions
270
284
  end
271
285
 
272
286
  def visit_ArelExtensions_Nodes_Union o, collector
273
- if o.left.is_a?(Arel::SelectManager)
274
- collector = visit o.left.ast, collector
275
- else
276
- collector = visit o.left, collector
277
- end
287
+ collector =
288
+ if o.left.is_a?(Arel::SelectManager)
289
+ visit o.left.ast, collector
290
+ else
291
+ visit o.left, collector
292
+ end
278
293
  collector << " UNION "
279
- if o.right.is_a?(Arel::SelectManager)
280
- collector = visit o.right.ast, collector
281
- else
282
- collector = visit o.right, collector
283
- end
294
+ collector =
295
+ if o.right.is_a?(Arel::SelectManager)
296
+ visit o.right.ast, collector
297
+ else
298
+ visit o.right, collector
299
+ end
284
300
  collector
285
301
  end
286
302
 
287
303
  def visit_ArelExtensions_Nodes_UnionAll o, collector
288
- if o.left.is_a?(Arel::SelectManager)
289
- collector = visit o.left.ast, collector
290
- else
291
- collector = visit o.left, collector
292
- end
304
+ collector =
305
+ if o.left.is_a?(Arel::SelectManager)
306
+ visit o.left.ast, collector
307
+ else
308
+ visit o.left, collector
309
+ end
293
310
  collector << " UNION ALL "
294
- if o.right.is_a?(Arel::SelectManager)
295
- collector = visit o.right.ast, collector
296
- else
297
- collector = visit o.right, collector
298
- end
311
+ collector =
312
+ if o.right.is_a?(Arel::SelectManager)
313
+ visit o.right.ast, collector
314
+ else
315
+ visit o.right, collector
316
+ end
299
317
  collector
300
318
  end
301
319
 
@@ -346,16 +364,6 @@ module ArelExtensions
346
364
  collector
347
365
  end
348
366
 
349
-
350
- alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
351
- def visit_Arel_Nodes_SelectStatement o, collector
352
- if !collector.value.blank? && o.limit.blank?
353
- o = o.dup
354
- o.orders = []
355
- end
356
- old_visit_Arel_Nodes_SelectStatement(o,collector)
357
- end
358
-
359
367
  alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
360
368
  def visit_Arel_Nodes_As o, collector
361
369
  if o.left.is_a?(Arel::Nodes::Binary)
@@ -1,7 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::ToSql.class_eval do
4
- Arel::Visitors::ToSql::COMMA = ", "
3
+ class Arel::Visitors::ToSql
4
+ Arel::Visitors::ToSql::COMMA = ', ' unless defined?(Arel::Visitors::ToSql::COMMA)
5
5
 
6
6
  # Math Functions
7
7
  def visit_ArelExtensions_Nodes_Abs o, collector
@@ -53,14 +53,14 @@ module ArelExtensions
53
53
  collector << ")"
54
54
  collector
55
55
  end
56
-
56
+
57
57
  def visit_ArelExtensions_Nodes_Log10 o, collector
58
58
  collector << "LOG10("
59
59
  collector = visit o.left, collector
60
60
  collector << ")"
61
61
  collector
62
62
  end
63
-
63
+
64
64
  def visit_ArelExtensions_Nodes_Power o, collector
65
65
  collector << "POW("
66
66
  o.expressions.each_with_index { |arg, i|
@@ -71,6 +71,13 @@ module ArelExtensions
71
71
  collector
72
72
  end
73
73
 
74
+ def visit_ArelExtensions_Nodes_Sum o, collector
75
+ collector << "SUM("
76
+ collector = visit o.expr, collector
77
+ collector << ")"
78
+ collector
79
+ end
80
+
74
81
  # String functions
75
82
  def visit_ArelExtensions_Nodes_Concat o, collector
76
83
  collector << "CONCAT("
@@ -85,9 +92,9 @@ module ArelExtensions
85
92
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
86
93
  collector << "GROUP_CONCAT("
87
94
  collector = visit o.left, collector
88
- if o.right && o.right != 'NULL'
95
+ if o.separator && o.separator != 'NULL'
89
96
  collector << Arel::Visitors::ToSql::COMMA
90
- collector = visit o.right, collector
97
+ collector = visit o.separator, collector
91
98
  end
92
99
  collector << ")"
93
100
  collector
@@ -128,14 +135,26 @@ module ArelExtensions
128
135
 
129
136
  def visit_ArelExtensions_Nodes_Replace o, collector
130
137
  collector << "REPLACE("
131
- o.expressions.each_with_index { |arg, i|
132
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
133
- collector = visit arg, collector
134
- }
138
+ visit o.left, collector
139
+ collector << Arel::Visitors::ToSql::COMMA
140
+ visit o.pattern, collector
141
+ collector << Arel::Visitors::ToSql::COMMA
142
+ visit o.substitute, collector
143
+ collector << ")"
144
+ collector
145
+ end
146
+
147
+ def visit_ArelExtensions_Nodes_RegexpReplace o, collector
148
+ collector << "REGEXP_REPLACE("
149
+ visit o.left, collector
150
+ collector << Arel::Visitors::ToSql::COMMA
151
+ visit Arel::Nodes.build_quoted(o.pattern.to_s), collector
152
+ collector << Arel::Visitors::ToSql::COMMA
153
+ visit o.substitute, collector
135
154
  collector << ")"
136
155
  collector
137
156
  end
138
-
157
+
139
158
  def visit_ArelExtensions_Nodes_Repeat o, collector
140
159
  collector << "REPEAT("
141
160
  o.expressions.each_with_index { |arg, i|
@@ -270,12 +289,12 @@ module ArelExtensions
270
289
  as_attr = Arel::Nodes::SqlLiteral.new('int')
271
290
  when :decimal, :float, :number
272
291
  as_attr = Arel::Nodes::SqlLiteral.new('float')
273
- when :datetime
292
+ when :datetime
274
293
  as_attr = Arel::Nodes::SqlLiteral.new('datetime')
275
294
  when :time
276
295
  as_attr = Arel::Nodes::SqlLiteral.new('time')
277
- when :binary
278
- as_attr = Arel::Nodes::SqlLiteral.new('binary')
296
+ when :binary
297
+ as_attr = Arel::Nodes::SqlLiteral.new('binary')
279
298
  else
280
299
  as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
281
300
  end
@@ -306,7 +325,7 @@ module ArelExtensions
306
325
  collector << ")"
307
326
  collector
308
327
  end
309
-
328
+
310
329
  def visit_ArelExtensions_Nodes_DateSub o, collector
311
330
  collector << "DATE_SUB("
312
331
  collector = visit o.left, collector
@@ -385,7 +404,7 @@ module ArelExtensions
385
404
  collector = visit o.left, collector
386
405
  collector << ") THEN "
387
406
  collector = visit o.right, collector
388
- if o.expressions[2]
407
+ if o.expressions[2]
389
408
  collector << " ELSE "
390
409
  collector = visit o.expressions[2], collector
391
410
  end
@@ -409,16 +428,15 @@ module ArelExtensions
409
428
  row_nb = o.left.length
410
429
  o.left.each_with_index do |row, idx|
411
430
  collector << '('
412
- v = Arel::Nodes::Values.new(row, o.cols)
413
- len = v.expressions.length - 1
414
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
415
- case value
416
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
417
- collector = visit value, collector
418
- else
419
- collector << quote(value, attr && column_for(attr)).to_s
420
- end
421
- collector << Arel::Visitors::ToSql::COMMA unless i == len
431
+ len = row.length - 1
432
+ row.zip(o.cols).each_with_index { |(value, attr), i|
433
+ case value
434
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
435
+ collector = visit value, collector
436
+ else
437
+ collector << quote(value, attr && column_for(attr)).to_s
438
+ end
439
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
422
440
  }
423
441
  collector << (idx == row_nb-1 ? ')' : '), ')
424
442
  end
@@ -431,15 +449,16 @@ module ArelExtensions
431
449
  o.left.each_with_index do |row, idx|
432
450
  collector << '('
433
451
  len = row.length - 1
434
- row.each_with_index { |value, i|
435
- attr = o.cols[i]
436
- case value
437
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
438
- collector = visit value, collector
439
- else
440
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
441
- end
442
- collector << Arel::Visitors::ToSql::COMMA unless i == len
452
+ row.zip(o.cols).each_with_index { |(value, attr), i|
453
+ case value
454
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
455
+ collector = visit value, collector
456
+ when Integer
457
+ collector << value.to_s
458
+ else
459
+ collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
460
+ end
461
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
443
462
  }
444
463
  collector << (idx == row_nb-1 ? ')' : '), ')
445
464
  end
@@ -453,7 +472,7 @@ module ArelExtensions
453
472
  collector = visit o.right, collector
454
473
  collector
455
474
  end
456
-
475
+
457
476
  def visit_ArelExtensions_Nodes_UnionAll o, collector
458
477
  collector = visit o.left, collector
459
478
  collector << " UNION ALL "
@@ -490,25 +509,25 @@ module ArelExtensions
490
509
  visit Arel::Nodes.build_quoted(o.expr), collector
491
510
  end
492
511
 
493
- def visit_ArelExtensions_Nodes_FormattedNumber o, collector
512
+ def visit_ArelExtensions_Nodes_FormattedNumber o, collector
494
513
  visit o.left, collector
495
514
  end
496
-
497
- remove_method(:visit_Arel_Nodes_LessThan) rescue nil
515
+
516
+ remove_method(:visit_Arel_Nodes_LessThan) rescue nil
498
517
  def visit_Arel_Nodes_LessThan o, collector
499
518
  collector = visit o.left, collector
500
519
  collector << " < "
501
520
  visit o.right, collector
502
521
  end
503
-
504
- def visit_ArelExtensions_Nodes_Std o, collector
522
+
523
+ def visit_ArelExtensions_Nodes_Std o, collector
505
524
  collector << "STD("
506
525
  visit o.left, collector
507
526
  collector << ")"
508
527
  collector
509
528
  end
510
-
511
- def visit_ArelExtensions_Nodes_Variance o, collector
529
+
530
+ def visit_ArelExtensions_Nodes_Variance o, collector
512
531
  collector << "VARIANCE("
513
532
  visit o.left, collector
514
533
  collector << ")"
@@ -524,11 +543,13 @@ module ArelExtensions
524
543
  collector
525
544
  end
526
545
 
546
+ # Boolean logic.
547
+
527
548
  alias_method :old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And
528
549
  def visit_Arel_Nodes_And o, collector
529
550
  case o.children.length
530
551
  when 0
531
- collector << '1=1' # but this should not happen
552
+ collector << '1 = 1' # but this should not happen
532
553
  when 1
533
554
  collector = visit o.children[0], collector
534
555
  else
@@ -544,10 +565,11 @@ module ArelExtensions
544
565
  collector
545
566
  end
546
567
 
547
- def visit_ArelExtensions_Nodes_Or o, collector
568
+ alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
569
+ def visit_Arel_Nodes_Or o, collector
548
570
  case o.children.length
549
571
  when 0
550
- collector << '0=1' # but this should not happen
572
+ collector << '1 = 0' # but this should not happen
551
573
  when 1
552
574
  collector = visit o.children[0], collector
553
575
  else
@@ -563,16 +585,6 @@ module ArelExtensions
563
585
  collector
564
586
  end
565
587
 
566
- alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
567
- def visit_Arel_Nodes_Or o, collector
568
- collector << '('
569
- collector = visit o.left, collector
570
- collector << ') OR ('
571
- collector = visit o.right, collector
572
- collector << ')'
573
- collector
574
- end
575
-
576
588
  def visit_ArelExtensions_Nodes_Json o,collector
577
589
  case o.dict
578
590
  when Array
@@ -612,7 +624,7 @@ module ArelExtensions
612
624
 
613
625
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
614
626
  if o.as_array
615
- res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ',o.orders) : o.dict.group_concat(', ')) + ']'
627
+ res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ', order: Array(o.orders)) : o.dict.group_concat(', ')).coalesce('') + ']'
616
628
  collector = visit res, collector
617
629
  else
618
630
  res = Arel::Nodes.build_quoted('{')
@@ -627,7 +639,7 @@ module ArelExtensions
627
639
  else
628
640
  kv += v
629
641
  end
630
- res = res + kv.group_concat(', ',orders)
642
+ res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
631
643
  end
632
644
  res = res + '}'
633
645
  collector = visit res, collector