arel_extensions 2.0.21 → 2.2.2

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 (138) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -2
  3. data/.github/workflows/publish.yml +29 -0
  4. data/.github/workflows/release.yml +30 -0
  5. data/.github/workflows/ruby.yml +377 -80
  6. data/.gitignore +7 -6
  7. data/.rubocop.yml +62 -1
  8. data/CONTRIBUTING.md +102 -0
  9. data/Gemfile +2 -23
  10. data/NEWS.md +89 -0
  11. data/README.md +228 -84
  12. data/Rakefile +11 -4
  13. data/TODO +0 -1
  14. data/appveyor.yml +60 -22
  15. data/arel_extensions.gemspec +11 -12
  16. data/bin/build +15 -0
  17. data/bin/compose +6 -0
  18. data/bin/publish +8 -0
  19. data/dev/arelx.dockerfile +44 -0
  20. data/dev/compose.yaml +71 -0
  21. data/dev/postgres.dockerfile +5 -0
  22. data/dev/rbenv +189 -0
  23. data/gemfiles/rails3.gemfile +10 -10
  24. data/gemfiles/rails4_2.gemfile +38 -0
  25. data/gemfiles/rails5.gemfile +29 -0
  26. data/gemfiles/rails5_1_4.gemfile +13 -13
  27. data/gemfiles/rails5_2.gemfile +16 -14
  28. data/gemfiles/rails6.gemfile +18 -15
  29. data/gemfiles/rails6_1.gemfile +18 -15
  30. data/gemfiles/rails7.gemfile +33 -0
  31. data/gemfiles/rails7_1.gemfile +33 -0
  32. data/gemfiles/rails7_2.gemfile +33 -0
  33. data/gemspecs/arel_extensions-v1.gemspec +12 -13
  34. data/gemspecs/arel_extensions-v2.gemspec +11 -12
  35. data/init/mssql.sql +0 -0
  36. data/init/mysql.sql +0 -0
  37. data/init/oracle.sql +0 -0
  38. data/init/postgresql.sql +0 -0
  39. data/init/sqlite.sql +0 -0
  40. data/lib/arel_extensions/aliases.rb +14 -0
  41. data/lib/arel_extensions/attributes.rb +10 -2
  42. data/lib/arel_extensions/boolean_functions.rb +2 -4
  43. data/lib/arel_extensions/common_sql_functions.rb +12 -12
  44. data/lib/arel_extensions/comparators.rb +14 -14
  45. data/lib/arel_extensions/date_duration.rb +14 -9
  46. data/lib/arel_extensions/helpers.rb +62 -0
  47. data/lib/arel_extensions/insert_manager.rb +19 -17
  48. data/lib/arel_extensions/math.rb +48 -45
  49. data/lib/arel_extensions/math_functions.rb +18 -18
  50. data/lib/arel_extensions/nodes/abs.rb +0 -0
  51. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -0
  52. data/lib/arel_extensions/nodes/blank.rb +1 -1
  53. data/lib/arel_extensions/nodes/case.rb +10 -12
  54. data/lib/arel_extensions/nodes/cast.rb +6 -6
  55. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  56. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  57. data/lib/arel_extensions/nodes/coalesce.rb +1 -1
  58. data/lib/arel_extensions/nodes/collate.rb +9 -9
  59. data/lib/arel_extensions/nodes/concat.rb +2 -2
  60. data/lib/arel_extensions/nodes/date_diff.rb +33 -14
  61. data/lib/arel_extensions/nodes/duration.rb +0 -0
  62. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  63. data/lib/arel_extensions/nodes/floor.rb +0 -0
  64. data/lib/arel_extensions/nodes/format.rb +3 -2
  65. data/lib/arel_extensions/nodes/formatted_date.rb +42 -0
  66. data/lib/arel_extensions/nodes/formatted_number.rb +2 -2
  67. data/lib/arel_extensions/nodes/function.rb +22 -26
  68. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  69. data/lib/arel_extensions/nodes/json.rb +15 -9
  70. data/lib/arel_extensions/nodes/length.rb +6 -0
  71. data/lib/arel_extensions/nodes/levenshtein_distance.rb +1 -1
  72. data/lib/arel_extensions/nodes/locate.rb +1 -1
  73. data/lib/arel_extensions/nodes/log10.rb +0 -0
  74. data/lib/arel_extensions/nodes/matches.rb +1 -1
  75. data/lib/arel_extensions/nodes/md5.rb +0 -0
  76. data/lib/arel_extensions/nodes/power.rb +0 -0
  77. data/lib/arel_extensions/nodes/rand.rb +0 -0
  78. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  79. data/lib/arel_extensions/nodes/replace.rb +2 -10
  80. data/lib/arel_extensions/nodes/rollup.rb +36 -0
  81. data/lib/arel_extensions/nodes/round.rb +0 -0
  82. data/lib/arel_extensions/nodes/select.rb +10 -0
  83. data/lib/arel_extensions/nodes/soundex.rb +2 -2
  84. data/lib/arel_extensions/nodes/std.rb +0 -0
  85. data/lib/arel_extensions/nodes/substring.rb +1 -1
  86. data/lib/arel_extensions/nodes/sum.rb +0 -0
  87. data/lib/arel_extensions/nodes/then.rb +1 -1
  88. data/lib/arel_extensions/nodes/trim.rb +2 -2
  89. data/lib/arel_extensions/nodes/union.rb +5 -5
  90. data/lib/arel_extensions/nodes/union_all.rb +4 -4
  91. data/lib/arel_extensions/nodes/wday.rb +0 -0
  92. data/lib/arel_extensions/nodes.rb +0 -0
  93. data/lib/arel_extensions/null_functions.rb +16 -0
  94. data/lib/arel_extensions/predications.rb +10 -10
  95. data/lib/arel_extensions/railtie.rb +1 -1
  96. data/lib/arel_extensions/set_functions.rb +3 -3
  97. data/lib/arel_extensions/string_functions.rb +19 -10
  98. data/lib/arel_extensions/tasks.rb +2 -2
  99. data/lib/arel_extensions/version.rb +1 -1
  100. data/lib/arel_extensions/visitors/convert_format.rb +0 -0
  101. data/lib/arel_extensions/visitors/ibm_db.rb +20 -20
  102. data/lib/arel_extensions/visitors/mssql.rb +394 -169
  103. data/lib/arel_extensions/visitors/mysql.rb +238 -151
  104. data/lib/arel_extensions/visitors/oracle.rb +170 -131
  105. data/lib/arel_extensions/visitors/oracle12.rb +16 -16
  106. data/lib/arel_extensions/visitors/postgresql.rb +170 -140
  107. data/lib/arel_extensions/visitors/sqlite.rb +88 -87
  108. data/lib/arel_extensions/visitors/to_sql.rb +185 -156
  109. data/lib/arel_extensions/visitors.rb +73 -60
  110. data/lib/arel_extensions.rb +173 -36
  111. data/test/arelx_test_helper.rb +49 -1
  112. data/test/database.yml +13 -7
  113. data/test/real_db_test.rb +101 -83
  114. data/test/support/fake_record.rb +8 -2
  115. data/test/test_comparators.rb +5 -5
  116. data/test/visitors/test_bulk_insert_oracle.rb +5 -5
  117. data/test/visitors/test_bulk_insert_sqlite.rb +5 -5
  118. data/test/visitors/test_bulk_insert_to_sql.rb +5 -5
  119. data/test/visitors/test_oracle.rb +14 -14
  120. data/test/visitors/test_to_sql.rb +121 -93
  121. data/test/with_ar/all_agnostic_test.rb +630 -320
  122. data/test/with_ar/insert_agnostic_test.rb +25 -18
  123. data/test/with_ar/test_bulk_sqlite.rb +11 -7
  124. data/test/with_ar/test_math_sqlite.rb +18 -14
  125. data/test/with_ar/test_string_mysql.rb +26 -22
  126. data/test/with_ar/test_string_sqlite.rb +26 -22
  127. data/version_v1.rb +1 -1
  128. data/version_v2.rb +1 -1
  129. metadata +24 -26
  130. data/.travis/oracle/download.js +0 -152
  131. data/.travis/oracle/download.sh +0 -30
  132. data/.travis/oracle/download_ojdbc.js +0 -116
  133. data/.travis/oracle/install.sh +0 -34
  134. data/.travis/setup_accounts.sh +0 -9
  135. data/.travis/sqlite3/extension-functions.sh +0 -6
  136. data/.travis.yml +0 -193
  137. data/gemfiles/rails4.gemfile +0 -29
  138. data/gemfiles/rails5_0.gemfile +0 -29
@@ -6,30 +6,31 @@ module ArelExtensions
6
6
  DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
7
7
  DATE_FORMAT_DIRECTIVES = {
8
8
  '%Y' => 'YYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
9
- '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
9
+ '%V' => 'IW', '%G' => 'IYYY', # ISO week number and year of week
10
+ '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%a' => 'Dy', '%A' => 'Day', # day, weekday
10
11
  '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
11
12
  '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
12
13
  }
13
- NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
14
+ NUMBER_COMMA_MAPPING = {'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '}
14
15
 
15
16
  def visit_ArelExtensions_Nodes_Log10 o, collector
16
- collector << "LOG("
17
- o.expressions.each_with_index { |arg, i|
18
- collector << Arel::Visitors::ToSql::COMMA if i != 0
19
- collector = visit arg, collector
20
- }
21
- collector << ",10)"
22
- collector
17
+ collector << 'LOG('
18
+ o.expressions.each_with_index { |arg, i|
19
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
20
+ collector = visit arg, collector
21
+ }
22
+ collector << ',10)'
23
+ collector
23
24
  end
24
25
 
25
26
  def visit_ArelExtensions_Nodes_Power o, collector
26
- collector << "POWER("
27
- o.expressions.each_with_index { |arg, i|
28
- collector << Arel::Visitors::ToSql::COMMA if i != 0
29
- collector = visit arg, collector
30
- }
31
- collector << ")"
32
- collector
27
+ collector << 'POWER('
28
+ o.expressions.each_with_index { |arg, i|
29
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
30
+ collector = visit arg, collector
31
+ }
32
+ collector << ')'
33
+ collector
33
34
  end
34
35
 
35
36
  def visit_ArelExtensions_Nodes_Concat o, collector
@@ -107,54 +108,59 @@ module ArelExtensions
107
108
  end
108
109
 
109
110
  def visit_ArelExtensions_Nodes_Collate o, collector
110
- if o.ai
111
- collector << "NLSSORT("
112
- collector = visit o.expressions.first, collector
113
- collector << COMMA
114
- collector << "'NLS_SORT = BINARY_AI NLS_COMP = LINGUISTIC'"
115
- collector << ")"
116
- elsif o.ci
117
- collector << "NLSSORT("
118
- collector = visit o.expressions.first, collector
119
- collector << COMMA
120
- collector << "'NLS_SORT = BINARY_CI NLS_COMP = LINGUISTIC'"
121
- collector << ")"
122
- else
123
- collector = visit o.expressions.first, collector
124
- end
111
+ if o.ai
112
+ collector << 'NLSSORT('
113
+ collector = visit o.expressions.first, collector
114
+ collector << COMMA
115
+ collector << "'NLS_SORT = BINARY_AI NLS_COMP = LINGUISTIC'"
116
+ collector << ')'
117
+ elsif o.ci
118
+ collector << 'NLSSORT('
119
+ collector = visit o.expressions.first, collector
120
+ collector << COMMA
121
+ collector << "'NLS_SORT = BINARY_CI NLS_COMP = LINGUISTIC'"
122
+ collector << ')'
123
+ else
124
+ collector = visit o.expressions.first, collector
125
+ end
125
126
  collector
126
127
  end
127
128
 
129
+ def visit_Arel_Nodes_RollUp(o, collector)
130
+ collector << "ROLLUP"
131
+ grouping_array_or_grouping_element o, collector
132
+ end
133
+
128
134
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
129
- collector << "(LISTAGG("
135
+ collector << '(LISTAGG('
130
136
  collector = visit o.left, collector
131
137
  collector << COMMA
132
138
  collector =
133
139
  if o.separator && o.separator != 'NULL'
134
140
  visit o.separator, collector
135
141
  else
136
- visit Arel::Nodes.build_quoted(','), collector
142
+ visit Arel.quoted(','), collector
137
143
  end
138
- collector << ") WITHIN GROUP (ORDER BY "
144
+ collector << ') WITHIN GROUP (ORDER BY '
139
145
  if !o.order.blank?
140
- o.order.each_with_index do |order,i|
146
+ o.order.each_with_index do |order, i|
141
147
  collector << COMMA if i != 0
142
148
  collector = visit order, collector
143
149
  end
144
150
  else
145
151
  collector = visit o.left, collector
146
152
  end
147
- collector << "))"
153
+ collector << '))'
148
154
  collector
149
155
  end
150
156
 
151
157
  def visit_ArelExtensions_Nodes_Coalesce o, collector
152
- collector << "COALESCE("
158
+ collector << 'COALESCE('
153
159
  o.expressions.each_with_index { |arg, i|
154
160
  collector << COMMA if i != 0
155
161
  if i > 0 && o.left_node_type == :text
156
162
  if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
157
- collector << "NULL"
163
+ collector << 'NULL'
158
164
  else
159
165
  collector << 'TO_CLOB('
160
166
  collector = visit arg, collector
@@ -164,12 +170,12 @@ module ArelExtensions
164
170
  collector = visit arg, collector
165
171
  end
166
172
  }
167
- collector << ")"
173
+ collector << ')'
168
174
  collector
169
175
  end
170
176
 
171
177
  def visit_ArelExtensions_Nodes_MD5 o, collector
172
- collector << "LOWER (RAWTOHEX (DBMS_OBFUSCATION_TOOLKIT.md5(input => UTL_I18N.STRING_TO_RAW("
178
+ collector << 'LOWER (RAWTOHEX (DBMS_OBFUSCATION_TOOLKIT.md5(input => UTL_I18N.STRING_TO_RAW('
173
179
  collector = visit o.left, collector
174
180
  collector << ", 'AL32UTF8'))))"
175
181
  collector
@@ -184,7 +190,7 @@ module ArelExtensions
184
190
  collector << 'TO_DATE(' if lc
185
191
  collector = visit o.left, collector
186
192
  collector << ')' if lc
187
- collector << " - "
193
+ collector << ' - '
188
194
  collector << 'TO_DATE(' if rc
189
195
  collector = visit o.right, collector
190
196
  collector << ')' if rc
@@ -218,16 +224,16 @@ module ArelExtensions
218
224
  def visit_ArelExtensions_Nodes_Duration o, collector
219
225
  case o.left
220
226
  when 'wd', 'w'
221
- collector << "TO_CHAR("
227
+ collector << 'TO_CHAR('
222
228
  collector = visit o.right, collector
223
229
  collector << COMMA
224
- collector = visit Arel::Nodes.build_quoted(DATE_MAPPING[o.left]), collector
230
+ collector = visit Arel.quoted(DATE_MAPPING[o.left]), collector
225
231
  else
226
232
  right = case o.left
227
- when 'd','m','y'
233
+ when 'd', 'm', 'y'
228
234
  interval = 'DAY'
229
235
  o.right.cast(:date)
230
- when 'h','mn','s'
236
+ when 'h', 'mn', 's'
231
237
  interval = 'SECOND'
232
238
  o.right.cast(:datetime)
233
239
  when /i\z/
@@ -243,7 +249,7 @@ module ArelExtensions
243
249
  collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
244
250
  collector = visit right, collector
245
251
  end
246
- collector << ")"
252
+ collector << ')'
247
253
  collector << " * (INTERVAL '1' #{interval})" if interval && o.with_interval
248
254
  collector
249
255
  end
@@ -251,45 +257,45 @@ module ArelExtensions
251
257
  def visit_ArelExtensions_Nodes_Cast o, collector
252
258
  case o.as_attr
253
259
  when :string
254
- collector << "TO_CHAR("
260
+ collector << 'TO_CHAR('
255
261
  collector = visit o.left, collector
256
- collector << ")"
262
+ collector << ')'
257
263
  return collector
258
264
  when :text
259
- collector << "TO_CLOB("
265
+ collector << 'TO_CLOB('
260
266
  collector = visit o.left, collector
261
- collector << ")"
267
+ collector << ')'
262
268
  return collector
263
269
  when :ntext
264
- collector << "TO_NCLOB("
270
+ collector << 'TO_NCLOB('
265
271
  collector = visit o.left, collector
266
- collector << ")"
272
+ collector << ')'
267
273
  return collector
268
274
  when :time
269
275
  if (o.left.respond_to?(:return_type) && o.left.return_type == :string) || o.left.is_a?(Arel::Nodes::Quoted)
270
- collector << "TO_DATE("
276
+ collector << 'TO_DATE('
271
277
  collector = visit o.left, collector
272
278
  collector << ",'HH24:MI:SS')"
273
279
  else
274
- collector << "TO_DATE(TO_CHAR("
280
+ collector << 'TO_DATE(TO_CHAR('
275
281
  collector = visit o.left, collector
276
282
  collector << ",'HH24:MI:SS'),'HH24:MI:SS')"
277
283
  end
278
284
  return collector
279
285
  when :number, :decimal
280
- collector << "TO_NUMBER("
286
+ collector << 'TO_NUMBER('
281
287
  collector = visit o.left, collector
282
- collector << ")"
288
+ collector << ')'
283
289
  return collector
284
290
  when :datetime
285
291
  as_attr = Arel::Nodes::SqlLiteral.new('timestamp')
286
292
  when :date
287
293
  if (o.left.respond_to?(:return_type) && o.left.return_type == :string) || o.left.is_a?(Arel::Nodes::Quoted)
288
- collector << "TO_DATE("
294
+ collector << 'TO_DATE('
289
295
  collector = visit o.left, collector
290
296
  collector << ",'YYYY-MM-DD')"
291
297
  else
292
- collector << "TO_DATE(TO_CHAR("
298
+ collector << 'TO_DATE(TO_CHAR('
293
299
  collector = visit o.left, collector
294
300
  collector << ",'YYYY-MM-DD'),'YYYY-MM-DD')"
295
301
  end
@@ -299,18 +305,18 @@ module ArelExtensions
299
305
  else
300
306
  as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
301
307
  end
302
- collector << "CAST("
308
+ collector << 'CAST('
303
309
  collector = visit o.left, collector
304
- collector << " AS "
310
+ collector << ' AS '
305
311
  collector = visit as_attr, collector
306
- collector << ")"
312
+ collector << ')'
307
313
  collector
308
314
  end
309
315
 
310
316
  def visit_ArelExtensions_Nodes_Length o, collector
311
- collector << "LENGTH("
317
+ collector << "LENGTH#{o.bytewise ? 'B' : ''}("
312
318
  collector = visit o.expr, collector
313
- collector << ")"
319
+ collector << ')'
314
320
  collector
315
321
  end
316
322
 
@@ -327,18 +333,18 @@ module ArelExtensions
327
333
  end
328
334
 
329
335
  def visit_ArelExtensions_Nodes_Rand o, collector
330
- collector << "DBMS_RANDOM.VALUE("
336
+ collector << 'DBMS_RANDOM.VALUE('
331
337
  if o.left && o.right
332
338
  collector = visit o.left, collector
333
339
  collector << COMMA
334
340
  collector = visit o.right, collector
335
341
  end
336
- collector << ")"
342
+ collector << ')'
337
343
  collector
338
344
  end
339
345
 
340
346
  def visit_Arel_Nodes_Regexp o, collector
341
- collector << " REGEXP_LIKE("
347
+ collector << ' REGEXP_LIKE('
342
348
  collector = visit o.left, collector
343
349
  collector << COMMA
344
350
  collector = visit o.right, collector
@@ -347,7 +353,7 @@ module ArelExtensions
347
353
  end
348
354
 
349
355
  def visit_Arel_Nodes_NotRegexp o, collector
350
- collector << " NOT REGEXP_LIKE("
356
+ collector << ' NOT REGEXP_LIKE('
351
357
  collector = visit o.left, collector
352
358
  collector << COMMA
353
359
  collector = visit o.right, collector
@@ -356,22 +362,22 @@ module ArelExtensions
356
362
  end
357
363
 
358
364
  def visit_ArelExtensions_Nodes_Locate o, collector
359
- collector << "INSTR("
365
+ collector << 'INSTR('
360
366
  o.expressions.each_with_index { |arg, i|
361
367
  collector << COMMA if i != 0
362
368
  collector = visit arg, collector
363
369
  }
364
- collector << ")"
370
+ collector << ')'
365
371
  collector
366
372
  end
367
373
 
368
374
  def visit_ArelExtensions_Nodes_Substring o, collector
369
- collector << "SUBSTR("
375
+ collector << 'SUBSTR('
370
376
  o.expressions.each_with_index { |arg, i|
371
377
  collector << COMMA if i != 0
372
378
  collector = visit arg, collector
373
379
  }
374
- collector << ")"
380
+ collector << ')'
375
381
  collector
376
382
  end
377
383
 
@@ -390,14 +396,14 @@ module ArelExtensions
390
396
  collector << COMMA
391
397
  collector << 'COALESCE(dbms_lob.GETLENGTH('
392
398
  collector = visit o.left, collector
393
- collector << "), 0)"
399
+ collector << '), 0)'
394
400
  collector << COMMA
395
401
  collector << '1)'
396
402
  else
397
403
  collector = visit o.left, collector
398
404
  end
399
405
  collector << ')' if o.left.is_a? ArelExtensions::Nodes::Trim
400
- collector << ")"
406
+ collector << ')'
401
407
  collector
402
408
  end
403
409
 
@@ -410,7 +416,7 @@ module ArelExtensions
410
416
  end
411
417
  collector << ' FROM '
412
418
  collector = visit o.left, collector
413
- collector << ")"
419
+ collector << ')'
414
420
  collector
415
421
  end
416
422
 
@@ -423,7 +429,7 @@ module ArelExtensions
423
429
  end
424
430
  collector << ' FROM '
425
431
  collector = visit o.left, collector
426
- collector << ")"
432
+ collector << ')'
427
433
  collector
428
434
  end
429
435
 
@@ -445,35 +451,51 @@ module ArelExtensions
445
451
  end
446
452
 
447
453
  def visit_ArelExtensions_Nodes_Format o, collector
454
+ visit_ArelExtensions_Nodes_FormattedDate o, collector
455
+ end
456
+
457
+ def visit_ArelExtensions_Nodes_FormattedDate o, collector
448
458
  fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
449
- collector << "TO_CHAR("
459
+ collector << 'TO_CHAR('
460
+ collector << 'CAST(' if o.time_zone
450
461
  collector = visit o.left, collector
462
+ case o.time_zone
463
+ when Hash
464
+ src_tz, dst_tz = o.time_zone.first
465
+ collector << ' as timestamp) at time zone '
466
+ collector = visit Arel.quoted(src_tz), collector
467
+ collector < ' at time zone '
468
+ collector = visit Arel.quoted(dst_tz), collector
469
+ when String
470
+ collector << ' as timestamp) at time zone '
471
+ collector = visit Arel.quoted(o.time_zone), collector
472
+ end
451
473
  collector << COMMA
452
- collector = visit Arel::Nodes.build_quoted(fmt), collector
453
- collector << ")"
474
+ collector = visit Arel.quoted(fmt), collector
475
+ collector << ')'
454
476
  collector
455
477
  end
456
478
 
457
479
  def visit_ArelExtensions_Nodes_Repeat o, collector
458
- collector << "LPAD("
480
+ collector << 'LPAD('
459
481
  collector = visit o.expressions[0], collector # can't put empty string, otherwise it wouldn't work
460
482
  collector << Arel::Visitors::ToSql::COMMA
461
483
  collector = visit o.expressions[1], collector
462
484
  collector << Arel::Visitors::ToSql::COMMA
463
485
  collector = visit o.expressions[0], collector
464
- collector << ")"
486
+ collector << ')'
465
487
  collector
466
488
  end
467
489
 
468
490
  # add primary_key if not present, avoid zip
469
491
  if Arel::VERSION.to_i < 7
470
492
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
471
- collector << "("
493
+ collector << '('
472
494
  o.left.each_with_index do |row, idx| # values
473
- collector << " UNION ALL " if idx != 0
474
- collector << "(SELECT "
475
- len = row.length - 1
476
- row.zip(o.cols).each_with_index { |(value, attr), i|
495
+ collector << ' UNION ALL ' if idx != 0
496
+ collector << '(SELECT '
497
+ len = row.length - 1
498
+ row.zip(o.cols).each_with_index { |(value, attr), i|
477
499
  case value
478
500
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
479
501
  collector = visit value, collector
@@ -481,18 +503,18 @@ module ArelExtensions
481
503
  collector << quote(value, attr && column_for(attr)).to_s
482
504
  end
483
505
  collector << COMMA unless i == len
484
- }
485
- collector << ' FROM DUAL)'
506
+ }
507
+ collector << ' FROM DUAL)'
486
508
  end
487
- collector << ")"
509
+ collector << ')'
488
510
  collector
489
511
  end
490
512
  else
491
513
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
492
- collector << "("
514
+ collector << '('
493
515
  o.left.each_with_index do |row, idx|
494
- collector << " UNION ALL " if idx != 0
495
- collector << "(SELECT "
516
+ collector << ' UNION ALL ' if idx != 0
517
+ collector << '(SELECT '
496
518
  len = row.length - 1
497
519
  row.zip(o.cols).each_with_index { |(value, attr), i|
498
520
  case value
@@ -507,7 +529,7 @@ module ArelExtensions
507
529
  }
508
530
  collector << ' FROM DUAL)'
509
531
  end
510
- collector << ")"
532
+ collector << ')'
511
533
  collector
512
534
  end
513
535
  end
@@ -517,7 +539,7 @@ module ArelExtensions
517
539
  if element.is_a?(Time)
518
540
  ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
519
541
  elsif element.is_a?(Arel::Attributes::Attribute)
520
- col = Arel::Table.engine.connection.schema_cache.columns_hash(element.relation.table_name)[element.name.to_s]
542
+ col = Arel.column_of(element.relation.table_name, element.name.to_s)
521
543
  if col && (col.type == :time)
522
544
  ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
523
545
  else
@@ -532,7 +554,7 @@ module ArelExtensions
532
554
  remove_method(:visit_Arel_Nodes_GreaterThanOrEqual) rescue nil
533
555
  def visit_Arel_Nodes_GreaterThanOrEqual o, collector
534
556
  collector = visit get_time_converted(o.left), collector
535
- collector << " >= "
557
+ collector << ' >= '
536
558
  collector = visit get_time_converted(o.right), collector
537
559
  collector
538
560
  end
@@ -540,7 +562,7 @@ module ArelExtensions
540
562
  remove_method(:visit_Arel_Nodes_GreaterThan) rescue nil
541
563
  def visit_Arel_Nodes_GreaterThan o, collector
542
564
  collector = visit get_time_converted(o.left), collector
543
- collector << " > "
565
+ collector << ' > '
544
566
  collector = visit get_time_converted(o.right), collector
545
567
  collector
546
568
  end
@@ -548,7 +570,7 @@ module ArelExtensions
548
570
  remove_method(:visit_Arel_Nodes_LessThanOrEqual) rescue nil
549
571
  def visit_Arel_Nodes_LessThanOrEqual o, collector
550
572
  collector = visit get_time_converted(o.left), collector
551
- collector << " <= "
573
+ collector << ' <= '
552
574
  collector = visit get_time_converted(o.right), collector
553
575
  collector
554
576
  end
@@ -556,7 +578,7 @@ module ArelExtensions
556
578
  remove_method(:visit_Arel_Nodes_LessThan) rescue nil
557
579
  def visit_Arel_Nodes_LessThan o, collector
558
580
  collector = visit get_time_converted(o.left), collector
559
- collector << " < "
581
+ collector << ' < '
560
582
  collector = visit get_time_converted(o.right), collector
561
583
  collector
562
584
  end
@@ -568,15 +590,15 @@ module ArelExtensions
568
590
  o = o.dup
569
591
  o.orders = []
570
592
  end
571
- old_visit_Arel_Nodes_SelectStatement(o,collector)
593
+ old_visit_Arel_Nodes_SelectStatement(o, collector)
572
594
  end
573
595
 
574
596
  alias_method(:old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias) rescue nil
575
597
  def visit_Arel_Nodes_TableAlias o, collector
576
598
  if o.name.length > 30
577
- o = Arel::Table.new(o.table_name).alias(Base64.urlsafe_encode64(Digest::MD5.new.digest(o.name)).tr('=', '').tr('-', '_'))
599
+ o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
578
600
  end
579
- old_visit_Arel_Nodes_TableAlias(o,collector)
601
+ old_visit_Arel_Nodes_TableAlias(o, collector)
580
602
  end
581
603
 
582
604
  alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
@@ -588,7 +610,7 @@ module ArelExtensions
588
610
  else
589
611
  collector = visit o.left, collector
590
612
  end
591
- quote = o.right.to_s =~ /(\A["].*["]\z)|\A[a-zA-Z_]*\z/ ? '' : '"'
613
+ quote = /(\A".*"\z)|\A[a-zA-Z_]*\z/.match?(o.right.to_s) ? '' : '"'
592
614
  collector << " AS #{quote}"
593
615
  collector = visit o.right, collector
594
616
  collector << "#{quote}"
@@ -612,47 +634,52 @@ module ArelExtensions
612
634
  col = o.left.coalesce(0)
613
635
  comma = NUMBER_COMMA_MAPPING[o.locale] || '.,'
614
636
  comma_in_format = o.precision == 0 ? '' : 'D'
615
- nines_after = (1..o.precision-1).map{'9'}.join('')+'0'
637
+ nines_after = (1..o.precision - 1).map{'9'}.join('') + '0'
616
638
  if comma.length == 1
617
- options = Arel::Nodes.build_quoted("NLS_NUMERIC_CHARACTERS = '"+comma+" '")
618
- nines_before = ("999"*4+"990")
639
+ options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '#{comma} '")
640
+ nines_before = ('999' * 4 + '990')
619
641
  else
620
- options = Arel::Nodes.build_quoted("NLS_NUMERIC_CHARACTERS = '"+comma+"'")
621
- nines_before = ("999G"*4+"990")
642
+ options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '#{comma}'")
643
+ nines_before = ('999G' * 4 + '990')
622
644
  end
623
- sign = ArelExtensions::Nodes::Case.new.when(col<0).
645
+ sign = Arel.when(col < 0).
624
646
  then('-').
625
647
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
626
648
  sign_length = o.flags.include?('+') || o.flags.include?(' ') ?
627
- Arel::Nodes.build_quoted(1) :
628
- ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
649
+ Arel.quoted(1) :
650
+ Arel.when(col < 0).then(1).else(0)
629
651
 
630
652
  if o.scientific_notation
631
- number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
632
- Arel::Nodes.build_quoted(col.abs),
633
- Arel::Nodes.build_quoted('FM'+nines_before+comma_in_format+nines_after+'EEEE'),
653
+ number = Arel::Nodes::NamedFunction.new('TO_CHAR', [
654
+ Arel.quoted(col.abs),
655
+ Arel.quoted("FM#{nines_before}#{comma_in_format}#{nines_after}EEEE"),
634
656
  options
635
657
  ])
636
658
  if o.type == 'e'
637
- number = number.replace('E','e')
659
+ number = number.replace('E', 'e')
638
660
  end
639
661
  else
640
- number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
641
- Arel::Nodes.build_quoted(col.abs),
642
- Arel::Nodes.build_quoted('FM'+nines_before+comma_in_format+nines_after),
662
+ number = Arel::Nodes::NamedFunction.new('TO_CHAR', [
663
+ Arel.quoted(col.abs),
664
+ Arel.quoted("FM#{nines_before}#{comma_in_format}#{nines_after}"),
643
665
  options
644
666
  ])
645
667
  end
646
668
 
647
- repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
648
- when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
649
- then(Arel::Nodes.build_quoted(
650
- o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
651
- ).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
652
- ).
653
- else('')
654
- before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
655
- middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
669
+ repeated_char =
670
+ if o.width == 0
671
+ Arel.quoted('')
672
+ else
673
+ Arel
674
+ .when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
675
+ .then(Arel.quoted(
676
+ o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
677
+ ).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
678
+ )
679
+ .else('')
680
+ end
681
+ before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
682
+ middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
656
683
  after = o.flags.include?('-') ? repeated_char : ''
657
684
  full_number = ArelExtensions::Nodes::Concat.new([
658
685
  before,
@@ -661,32 +688,44 @@ module ArelExtensions
661
688
  number,
662
689
  after
663
690
  ])
664
- collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
691
+ collector = visit ArelExtensions::Nodes::Concat.new([Arel.quoted(o.prefix), full_number, Arel.quoted(o.suffix)]), collector
665
692
  collector
666
693
  end
667
694
 
668
695
  def visit_ArelExtensions_Nodes_Std o, collector
669
- collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
696
+ collector << (o.unbiased_estimator ? 'STDDEV_SAMP(' : 'STDDEV_POP(')
670
697
  visit o.left, collector
671
- collector << ")"
698
+ collector << ')'
672
699
  collector
673
700
  end
674
701
 
675
702
  def visit_ArelExtensions_Nodes_Variance o, collector
676
- collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
703
+ collector << (o.unbiased_estimator ? 'VAR_SAMP(' : 'VAR_POP(')
677
704
  visit o.left, collector
678
- collector << ")"
705
+ collector << ')'
679
706
  collector
680
707
  end
681
708
 
682
709
  def visit_ArelExtensions_Nodes_LevenshteinDistance o, collector
683
- collector << "UTL_MATCH.edit_distance("
710
+ collector << 'UTL_MATCH.edit_distance('
684
711
  collector = visit o.left, collector
685
712
  collector << Arel::Visitors::ToSql::COMMA
686
713
  collector = visit o.right, collector
687
714
  collector << ')'
688
715
  collector
689
716
  end
717
+
718
+ # Utilized by GroupingSet, Cube & RollUp visitors to
719
+ # handle grouping aggregation semantics
720
+ def grouping_array_or_grouping_element(o, collector)
721
+ if o.expr.is_a? Array
722
+ collector << "( "
723
+ visit o.expr, collector
724
+ collector << " )"
725
+ else
726
+ visit o.expr, collector
727
+ end
728
+ end
690
729
  end
691
730
  end
692
731
  end