arel_extensions 1.2.3 → 1.2.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +59 -91
  4. data/Gemfile +2 -2
  5. data/README.md +17 -12
  6. data/Rakefile +38 -27
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +1 -1
  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 +26 -24
  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 -36
  68. data/lib/arel_extensions/visitors/oracle.rb +16 -16
  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 +52 -44
  72. data/lib/arel_extensions/visitors/to_sql.rb +71 -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 +4 -0
  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 +13 -7
  91. data/test/helper.rb +0 -18
@@ -1,7 +1,7 @@
1
1
  #require 'oracle_visitor'
2
2
  module ArelExtensions
3
3
  module Visitors
4
- Arel::Visitors::Oracle.class_eval do
4
+ class Arel::Visitors::Oracle
5
5
 
6
6
  SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
7
7
  Arel::Visitors::Oracle::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
@@ -131,14 +131,15 @@ module ArelExtensions
131
131
  collector << "(LISTAGG("
132
132
  collector = visit o.left, collector
133
133
  collector << Arel::Visitors::Oracle::COMMA
134
- if o.right && o.right != 'NULL'
135
- collector = visit o.right, collector
136
- else
137
- collector = visit Arel::Nodes.build_quoted(','), collector
138
- end
134
+ collector =
135
+ if o.separator && o.separator != 'NULL'
136
+ visit o.separator, collector
137
+ else
138
+ visit Arel::Nodes.build_quoted(','), collector
139
+ end
139
140
  collector << ") WITHIN GROUP (ORDER BY "
140
- if !o.orders.blank?
141
- o.orders.each_with_index do |order,i|
141
+ if !o.order.blank?
142
+ o.order.each_with_index do |order,i|
142
143
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
143
144
  collector = visit order, collector
144
145
  end
@@ -154,7 +155,7 @@ module ArelExtensions
154
155
  o.expressions.each_with_index { |arg, i|
155
156
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
156
157
  if i > 0 && o.left_node_type == :text
157
- if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
+ if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
159
  collector << "NULL"
159
160
  else
160
161
  collector << 'TO_CLOB('
@@ -466,14 +467,12 @@ module ArelExtensions
466
467
  o.left.each_with_index do |row, idx| # values
467
468
  collector << " UNION ALL " if idx != 0
468
469
  collector << "(SELECT "
469
- v = Arel::Nodes::Values.new(row, o.cols)
470
- len = v.expressions.length - 1
471
- v.expressions.each_with_index { |value, i|
470
+ len = row.length - 1
471
+ row.zip(o.cols).each_with_index { |(value, attr), i|
472
472
  case value
473
473
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
474
474
  collector = visit value, collector
475
475
  else
476
- attr = v.columns[i]
477
476
  collector << quote(value, attr && column_for(attr)).to_s
478
477
  end
479
478
  collector << Arel::Visitors::Oracle::COMMA unless i == len
@@ -489,12 +488,13 @@ module ArelExtensions
489
488
  o.left.each_with_index do |row, idx|
490
489
  collector << " UNION ALL " if idx != 0
491
490
  collector << "(SELECT "
492
- v = Arel::Nodes::Values.new(row, o.cols)
493
- len = v.expressions.length - 1
494
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
491
+ len = row.length - 1
492
+ row.zip(o.cols).each_with_index { |(value, attr), i|
495
493
  case value
496
494
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
497
495
  collector = visit value, collector
496
+ when Integer
497
+ collector << value.to_s
498
498
  else
499
499
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
500
500
  end
@@ -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("
210
+ collector = visit o.left, collector
211
+ collector << " AS INT) = "
212
+ collector = visit o.left, collector
213
+ collector << " THEN CAST("
204
214
  collector = visit o.left, collector
205
- collector << ") ELSE ROUND("
215
+ collector << " AS INT) ELSE CAST(("
206
216
  collector = visit o.left, collector
207
- collector << ") - 1 END"
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
@@ -248,12 +257,17 @@ module ArelExtensions
248
257
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
249
258
  o.left.each_with_index do |row, idx|
250
259
  collector << 'SELECT '
251
- v = Arel::Nodes::Values.new(row, o.cols)
252
- len = v.expressions.length - 1
253
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
260
+ len = row.length - 1
261
+ row.zip(o.cols).each_with_index { |(value, attr), i|
254
262
  case value
255
263
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
256
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
257
271
  else
258
272
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
259
273
  if idx == 0
@@ -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,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::ToSql.class_eval do
3
+ class Arel::Visitors::ToSql
4
+ Arel::Visitors::ToSql::COMMA = ', ' unless defined?(Arel::Visitors::ToSql::COMMA)
4
5
 
5
6
  # Math Functions
6
7
  def visit_ArelExtensions_Nodes_Abs o, collector
@@ -52,14 +53,14 @@ module ArelExtensions
52
53
  collector << ")"
53
54
  collector
54
55
  end
55
-
56
+
56
57
  def visit_ArelExtensions_Nodes_Log10 o, collector
57
58
  collector << "LOG10("
58
59
  collector = visit o.left, collector
59
60
  collector << ")"
60
61
  collector
61
62
  end
62
-
63
+
63
64
  def visit_ArelExtensions_Nodes_Power o, collector
64
65
  collector << "POW("
65
66
  o.expressions.each_with_index { |arg, i|
@@ -70,6 +71,13 @@ module ArelExtensions
70
71
  collector
71
72
  end
72
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
+
73
81
  # String functions
74
82
  def visit_ArelExtensions_Nodes_Concat o, collector
75
83
  collector << "CONCAT("
@@ -84,9 +92,9 @@ module ArelExtensions
84
92
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
85
93
  collector << "GROUP_CONCAT("
86
94
  collector = visit o.left, collector
87
- if o.right && o.right != 'NULL'
95
+ if o.separator && o.separator != 'NULL'
88
96
  collector << Arel::Visitors::ToSql::COMMA
89
- collector = visit o.right, collector
97
+ collector = visit o.separator, collector
90
98
  end
91
99
  collector << ")"
92
100
  collector
@@ -127,14 +135,26 @@ module ArelExtensions
127
135
 
128
136
  def visit_ArelExtensions_Nodes_Replace o, collector
129
137
  collector << "REPLACE("
130
- o.expressions.each_with_index { |arg, i|
131
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
132
- collector = visit arg, collector
133
- }
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
134
143
  collector << ")"
135
144
  collector
136
145
  end
137
-
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
154
+ collector << ")"
155
+ collector
156
+ end
157
+
138
158
  def visit_ArelExtensions_Nodes_Repeat o, collector
139
159
  collector << "REPEAT("
140
160
  o.expressions.each_with_index { |arg, i|
@@ -269,12 +289,12 @@ module ArelExtensions
269
289
  as_attr = Arel::Nodes::SqlLiteral.new('int')
270
290
  when :decimal, :float, :number
271
291
  as_attr = Arel::Nodes::SqlLiteral.new('float')
272
- when :datetime
292
+ when :datetime
273
293
  as_attr = Arel::Nodes::SqlLiteral.new('datetime')
274
294
  when :time
275
295
  as_attr = Arel::Nodes::SqlLiteral.new('time')
276
- when :binary
277
- as_attr = Arel::Nodes::SqlLiteral.new('binary')
296
+ when :binary
297
+ as_attr = Arel::Nodes::SqlLiteral.new('binary')
278
298
  else
279
299
  as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
280
300
  end
@@ -305,7 +325,7 @@ module ArelExtensions
305
325
  collector << ")"
306
326
  collector
307
327
  end
308
-
328
+
309
329
  def visit_ArelExtensions_Nodes_DateSub o, collector
310
330
  collector << "DATE_SUB("
311
331
  collector = visit o.left, collector
@@ -384,7 +404,7 @@ module ArelExtensions
384
404
  collector = visit o.left, collector
385
405
  collector << ") THEN "
386
406
  collector = visit o.right, collector
387
- if o.expressions[2]
407
+ if o.expressions[2]
388
408
  collector << " ELSE "
389
409
  collector = visit o.expressions[2], collector
390
410
  end
@@ -408,16 +428,15 @@ module ArelExtensions
408
428
  row_nb = o.left.length
409
429
  o.left.each_with_index do |row, idx|
410
430
  collector << '('
411
- v = Arel::Nodes::Values.new(row, o.cols)
412
- len = v.expressions.length - 1
413
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
414
- case value
415
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
416
- collector = visit value, collector
417
- else
418
- collector << quote(value, attr && column_for(attr)).to_s
419
- end
420
- 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
421
440
  }
422
441
  collector << (idx == row_nb-1 ? ')' : '), ')
423
442
  end
@@ -429,16 +448,17 @@ module ArelExtensions
429
448
  row_nb = o.left.length
430
449
  o.left.each_with_index do |row, idx|
431
450
  collector << '('
432
- v = Arel::Nodes::Values.new(row, o.cols)
433
- len = v.expressions.length - 1
434
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
435
- case value
436
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
437
- collector = visit value, collector
438
- else
439
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
440
- end
441
- collector << Arel::Visitors::ToSql::COMMA unless i == len
451
+ len = row.length - 1
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
442
462
  }
443
463
  collector << (idx == row_nb-1 ? ')' : '), ')
444
464
  end
@@ -452,7 +472,7 @@ module ArelExtensions
452
472
  collector = visit o.right, collector
453
473
  collector
454
474
  end
455
-
475
+
456
476
  def visit_ArelExtensions_Nodes_UnionAll o, collector
457
477
  collector = visit o.left, collector
458
478
  collector << " UNION ALL "
@@ -489,25 +509,25 @@ module ArelExtensions
489
509
  visit Arel::Nodes.build_quoted(o.expr), collector
490
510
  end
491
511
 
492
- def visit_ArelExtensions_Nodes_FormattedNumber o, collector
512
+ def visit_ArelExtensions_Nodes_FormattedNumber o, collector
493
513
  visit o.left, collector
494
514
  end
495
-
496
- remove_method(:visit_Arel_Nodes_LessThan) rescue nil
515
+
516
+ remove_method(:visit_Arel_Nodes_LessThan) rescue nil
497
517
  def visit_Arel_Nodes_LessThan o, collector
498
518
  collector = visit o.left, collector
499
519
  collector << " < "
500
520
  visit o.right, collector
501
521
  end
502
-
503
- def visit_ArelExtensions_Nodes_Std o, collector
522
+
523
+ def visit_ArelExtensions_Nodes_Std o, collector
504
524
  collector << "STD("
505
525
  visit o.left, collector
506
526
  collector << ")"
507
527
  collector
508
528
  end
509
-
510
- def visit_ArelExtensions_Nodes_Variance o, collector
529
+
530
+ def visit_ArelExtensions_Nodes_Variance o, collector
511
531
  collector << "VARIANCE("
512
532
  visit o.left, collector
513
533
  collector << ")"
@@ -523,11 +543,13 @@ module ArelExtensions
523
543
  collector
524
544
  end
525
545
 
546
+ # Boolean logic.
547
+
526
548
  alias_method :old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And
527
549
  def visit_Arel_Nodes_And o, collector
528
550
  case o.children.length
529
551
  when 0
530
- collector << '1=1' # but this should not happen
552
+ collector << '1 = 1' # but this should not happen
531
553
  when 1
532
554
  collector = visit o.children[0], collector
533
555
  else
@@ -543,10 +565,11 @@ module ArelExtensions
543
565
  collector
544
566
  end
545
567
 
546
- 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
547
570
  case o.children.length
548
571
  when 0
549
- collector << '0=1' # but this should not happen
572
+ collector << '1 = 0' # but this should not happen
550
573
  when 1
551
574
  collector = visit o.children[0], collector
552
575
  else
@@ -562,16 +585,6 @@ module ArelExtensions
562
585
  collector
563
586
  end
564
587
 
565
- alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
566
- def visit_Arel_Nodes_Or o, collector
567
- collector << '('
568
- collector = visit o.left, collector
569
- collector << ') OR ('
570
- collector = visit o.right, collector
571
- collector << ')'
572
- collector
573
- end
574
-
575
588
  def visit_ArelExtensions_Nodes_Json o,collector
576
589
  case o.dict
577
590
  when Array
@@ -611,7 +624,7 @@ module ArelExtensions
611
624
 
612
625
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
613
626
  if o.as_array
614
- 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('') + ']'
615
628
  collector = visit res, collector
616
629
  else
617
630
  res = Arel::Nodes.build_quoted('{')
@@ -626,7 +639,7 @@ module ArelExtensions
626
639
  else
627
640
  kv += v
628
641
  end
629
- res = res + kv.group_concat(', ',orders)
642
+ res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
630
643
  end
631
644
  res = res + '}'
632
645
  collector = visit res, collector