arel_extensions 2.0.9 → 2.0.14

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -0
  3. data/Gemfile +10 -10
  4. data/Rakefile +4 -4
  5. data/gemfiles/rails3.gemfile +9 -9
  6. data/gemfiles/rails4.gemfile +13 -13
  7. data/gemfiles/rails5_0.gemfile +13 -13
  8. data/gemfiles/rails5_1_4.gemfile +13 -13
  9. data/gemfiles/rails5_2.gemfile +13 -13
  10. data/gemfiles/rails6.gemfile +13 -13
  11. data/lib/arel_extensions.rb +3 -3
  12. data/lib/arel_extensions/attributes.rb +0 -0
  13. data/lib/arel_extensions/boolean_functions.rb +21 -5
  14. data/lib/arel_extensions/common_sql_functions.rb +2 -4
  15. data/lib/arel_extensions/comparators.rb +11 -14
  16. data/lib/arel_extensions/date_duration.rb +4 -5
  17. data/lib/arel_extensions/insert_manager.rb +16 -17
  18. data/lib/arel_extensions/math.rb +8 -9
  19. data/lib/arel_extensions/math_functions.rb +15 -17
  20. data/lib/arel_extensions/nodes/abs.rb +0 -1
  21. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -1
  22. data/lib/arel_extensions/nodes/blank.rb +0 -1
  23. data/lib/arel_extensions/nodes/case.rb +3 -4
  24. data/lib/arel_extensions/nodes/cast.rb +4 -2
  25. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  26. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  27. data/lib/arel_extensions/nodes/coalesce.rb +0 -1
  28. data/lib/arel_extensions/nodes/collate.rb +0 -1
  29. data/lib/arel_extensions/nodes/concat.rb +1 -3
  30. data/lib/arel_extensions/nodes/date_diff.rb +7 -8
  31. data/lib/arel_extensions/nodes/duration.rb +0 -1
  32. data/lib/arel_extensions/nodes/find_in_set.rb +0 -1
  33. data/lib/arel_extensions/nodes/floor.rb +1 -1
  34. data/lib/arel_extensions/nodes/format.rb +27 -1
  35. data/lib/arel_extensions/nodes/formatted_number.rb +0 -1
  36. data/lib/arel_extensions/nodes/function.rb +18 -15
  37. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  38. data/lib/arel_extensions/nodes/json.rb +39 -30
  39. data/lib/arel_extensions/nodes/length.rb +0 -1
  40. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  41. data/lib/arel_extensions/nodes/locate.rb +0 -1
  42. data/lib/arel_extensions/nodes/log10.rb +1 -2
  43. data/lib/arel_extensions/nodes/matches.rb +0 -2
  44. data/lib/arel_extensions/nodes/md5.rb +0 -1
  45. data/lib/arel_extensions/nodes/power.rb +0 -1
  46. data/lib/arel_extensions/nodes/rand.rb +0 -1
  47. data/lib/arel_extensions/nodes/repeat.rb +0 -2
  48. data/lib/arel_extensions/nodes/replace.rb +0 -2
  49. data/lib/arel_extensions/nodes/round.rb +0 -1
  50. data/lib/arel_extensions/nodes/soundex.rb +0 -1
  51. data/lib/arel_extensions/nodes/std.rb +0 -1
  52. data/lib/arel_extensions/nodes/substring.rb +0 -1
  53. data/lib/arel_extensions/nodes/sum.rb +0 -0
  54. data/lib/arel_extensions/nodes/then.rb +0 -0
  55. data/lib/arel_extensions/nodes/trim.rb +0 -2
  56. data/lib/arel_extensions/nodes/union.rb +0 -2
  57. data/lib/arel_extensions/nodes/union_all.rb +0 -2
  58. data/lib/arel_extensions/nodes/wday.rb +0 -4
  59. data/lib/arel_extensions/null_functions.rb +3 -5
  60. data/lib/arel_extensions/predications.rb +5 -6
  61. data/lib/arel_extensions/railtie.rb +5 -5
  62. data/lib/arel_extensions/set_functions.rb +0 -2
  63. data/lib/arel_extensions/string_functions.rb +21 -22
  64. data/lib/arel_extensions/tasks.rb +1 -1
  65. data/lib/arel_extensions/version.rb +1 -1
  66. data/lib/arel_extensions/visitors.rb +9 -7
  67. data/lib/arel_extensions/visitors/convert_format.rb +37 -0
  68. data/lib/arel_extensions/visitors/ibm_db.rb +4 -11
  69. data/lib/arel_extensions/visitors/mssql.rb +48 -44
  70. data/lib/arel_extensions/visitors/mysql.rb +65 -67
  71. data/lib/arel_extensions/visitors/oracle.rb +58 -55
  72. data/lib/arel_extensions/visitors/oracle12.rb +2 -3
  73. data/lib/arel_extensions/visitors/postgresql.rb +41 -34
  74. data/lib/arel_extensions/visitors/sqlite.rb +23 -18
  75. data/lib/arel_extensions/visitors/to_sql.rb +69 -61
  76. data/test/arelx_test_helper.rb +0 -2
  77. data/test/real_db_test.rb +27 -42
  78. data/test/support/fake_record.rb +1 -1
  79. data/test/test_comparators.rb +0 -4
  80. data/test/visitors/test_bulk_insert_oracle.rb +0 -1
  81. data/test/visitors/test_bulk_insert_sqlite.rb +0 -2
  82. data/test/visitors/test_oracle.rb +1 -2
  83. data/test/visitors/test_to_sql.rb +16 -25
  84. data/test/with_ar/all_agnostic_test.rb +135 -139
  85. data/test/with_ar/insert_agnostic_test.rb +0 -2
  86. data/test/with_ar/test_bulk_sqlite.rb +0 -4
  87. data/test/with_ar/test_math_sqlite.rb +4 -8
  88. data/test/with_ar/test_string_mysql.rb +1 -5
  89. data/test/with_ar/test_string_sqlite.rb +1 -5
  90. data/version_v1.rb +1 -1
  91. data/version_v2.rb +1 -1
  92. metadata +3 -2
@@ -1,20 +1,24 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  class Arel::Visitors::MySQL
4
- Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
- Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
4
+ DATE_MAPPING = {
5
+ 'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY',
6
+ 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
7
+ }.freeze
8
+
9
+ DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
6
10
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
7
11
  '%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
8
12
  '%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
9
13
  '%M' => '%i', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => ''
10
- }
14
+ }.freeze
11
15
 
12
16
 
13
- #Math functions
17
+ # Math functions
14
18
  def visit_ArelExtensions_Nodes_Log10 o, collector
15
19
  collector << "LOG10("
16
20
  o.expressions.each_with_index { |arg, i|
17
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
21
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
18
22
  collector = visit arg, collector
19
23
  }
20
24
  collector << ")"
@@ -24,14 +28,14 @@ module ArelExtensions
24
28
  def visit_ArelExtensions_Nodes_Power o, collector
25
29
  collector << "POW("
26
30
  o.expressions.each_with_index { |arg, i|
27
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
31
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
28
32
  collector = visit arg, collector
29
33
  }
30
34
  collector << ")"
31
35
  collector
32
36
  end
33
37
 
34
- #String functions
38
+ # String functions
35
39
  def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
36
40
  collector << 'LOWER('
37
41
  collector = visit o.left, collector
@@ -112,10 +116,10 @@ module ArelExtensions
112
116
  collector = visit o.expressions.first, collector
113
117
  collector <<
114
118
  if o.ai
115
- " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
116
- #doesn't work in latin1
119
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
120
+ # doesn't work in latin1
117
121
  elsif o.ci
118
- " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
122
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
119
123
  else
120
124
  " COLLATE #{charset}_bin"
121
125
  end
@@ -125,7 +129,7 @@ module ArelExtensions
125
129
  def visit_ArelExtensions_Nodes_Concat o, collector
126
130
  collector << "CONCAT("
127
131
  o.expressions.each_with_index { |arg, i|
128
- collector << Arel::Visitors::MySQL::COMMA unless i == 0
132
+ collector << COMMA if i != 0
129
133
  if (arg.is_a?(Numeric)) || (arg.is_a?(Arel::Attributes::Attribute))
130
134
  collector << "CAST("
131
135
  collector = visit arg, collector
@@ -144,7 +148,7 @@ module ArelExtensions
144
148
  if !o.order.blank?
145
149
  collector << ' ORDER BY '
146
150
  o.order.each_with_index do |order,i|
147
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
151
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
148
152
  collector = visit order, collector
149
153
  end
150
154
  end
@@ -165,7 +169,7 @@ module ArelExtensions
165
169
  collector
166
170
  end
167
171
 
168
- def visit_ArelExtensions_Nodes_Ltrim o , collector
172
+ def visit_ArelExtensions_Nodes_Ltrim o, collector
169
173
  collector << 'TRIM(LEADING '
170
174
  collector = visit o.right, collector
171
175
  collector << " FROM "
@@ -174,7 +178,7 @@ module ArelExtensions
174
178
  collector
175
179
  end
176
180
 
177
- def visit_ArelExtensions_Nodes_Rtrim o , collector
181
+ def visit_ArelExtensions_Nodes_Rtrim o, collector
178
182
  collector << 'TRIM(TRAILING '
179
183
  collector = visit o.right, collector
180
184
  collector << " FROM "
@@ -186,7 +190,7 @@ module ArelExtensions
186
190
  def visit_ArelExtensions_Nodes_Repeat o, collector
187
191
  collector << "REPEAT("
188
192
  o.expressions.each_with_index { |arg, i|
189
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
193
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
190
194
  collector = visit arg, collector
191
195
  }
192
196
  collector << ")"
@@ -202,13 +206,12 @@ module ArelExtensions
202
206
 
203
207
  def visit_ArelExtensions_Nodes_Format o, collector
204
208
  case o.col_type
205
- when :date, :datetime
209
+ when :date, :datetime, :time
210
+ fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
206
211
  collector << "DATE_FORMAT("
207
212
  collector = visit o.left, collector
208
- collector << Arel::Visitors::MySQL::COMMA
209
- f = o.iso_format.dup
210
- Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
211
- collector = visit Arel::Nodes.build_quoted(f), collector
213
+ collector << COMMA
214
+ collector = visit Arel::Nodes.build_quoted(fmt), collector
212
215
  collector << ")"
213
216
  when :integer, :float, :decimal
214
217
  collector << "FORMAT("
@@ -225,14 +228,15 @@ module ArelExtensions
225
228
  end
226
229
 
227
230
  def visit_ArelExtensions_Nodes_DateDiff o, collector
228
- if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
229
- collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
230
- 'TIMESTAMPDIFF(SECOND, '
231
- else
232
- 'DATEDIFF('
233
- end
231
+ case o.right_node_type
232
+ when :ruby_date, :ruby_time, :date, :datetime, :time
233
+ collector <<
234
+ case o.left_node_type
235
+ when :ruby_time, :datetime, :time then 'TIMESTAMPDIFF(SECOND, '
236
+ else 'DATEDIFF('
237
+ end
234
238
  collector = visit o.right, collector
235
- collector << Arel::Visitors::MySQL::COMMA
239
+ collector << COMMA
236
240
  collector = visit o.left, collector
237
241
  collector << ")"
238
242
  else
@@ -256,13 +260,12 @@ module ArelExtensions
256
260
  def visit_ArelExtensions_Nodes_DateAdd o, collector
257
261
  collector << "DATE_ADD("
258
262
  collector = visit o.left, collector
259
- collector << Arel::Visitors::MySQL::COMMA
263
+ collector << COMMA
260
264
  collector = visit o.mysql_value(o.right), collector
261
265
  collector << ")"
262
266
  collector
263
267
  end
264
268
 
265
-
266
269
  def visit_ArelExtensions_Nodes_Duration o, collector
267
270
  if o.left == 'wd'
268
271
  collector << "(WEEKDAY("
@@ -276,13 +279,13 @@ module ArelExtensions
276
279
  when 'h','mn','s'
277
280
  interval = 'SECOND'
278
281
  when /i\z/
279
- interval = Arel::Visitors::MySQL::DATE_MAPPING[o.left[0..-2]]
282
+ interval = DATE_MAPPING[o.left[0..-2]]
280
283
  else
281
284
  interval = nil
282
285
  end
283
286
  end
284
287
  collector << " INTERVAL " if o.with_interval && interval
285
- collector << "#{Arel::Visitors::MySQL::DATE_MAPPING[o.left]}("
288
+ collector << "#{DATE_MAPPING[o.left]}("
286
289
  collector = visit o.right, collector
287
290
  collector << ")"
288
291
  collector << " #{interval} " if o.with_interval && interval
@@ -290,7 +293,6 @@ module ArelExtensions
290
293
  collector
291
294
  end
292
295
 
293
-
294
296
  def visit_ArelExtensions_Nodes_IsNull o, collector
295
297
  collector << "ISNULL("
296
298
  collector = visit o.expr, collector
@@ -316,30 +318,25 @@ module ArelExtensions
316
318
  collector << "CAST("
317
319
  collector = visit o.left, collector
318
320
  collector << " AS "
319
- case o.as_attr
320
- when :string
321
- as_attr = Arel::Nodes::SqlLiteral.new('char')
322
- when :time
323
- as_attr = Arel::Nodes::SqlLiteral.new('time')
324
- when :int
325
- as_attr = Arel::Nodes::SqlLiteral.new('signed')
326
- when :number, :decimal
327
- as_attr = Arel::Nodes::SqlLiteral.new('decimal(20,6)')
328
- when :datetime
329
- as_attr = Arel::Nodes::SqlLiteral.new('datetime')
330
- when :date
331
- as_attr = Arel::Nodes::SqlLiteral.new('date')
332
- when :binary
333
- as_attr = Arel::Nodes::SqlLiteral.new('binary')
334
- else
335
- as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
336
- end
321
+ as_attr =
322
+ Arel::Nodes::SqlLiteral.new(
323
+ case o.as_attr
324
+ when :string then 'char'
325
+ when :time then 'time'
326
+ when :int then 'signed'
327
+ when :number, :decimal then 'decimal(20,6)'
328
+ when :datetime then 'datetime'
329
+ when :date then 'date'
330
+ when :binary then 'binary'
331
+ else o.as_attr.to_s
332
+ end
333
+ )
337
334
  collector = visit as_attr, collector
338
335
  collector << ")"
339
336
  collector
340
337
  end
341
338
 
342
- alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
339
+ alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
343
340
  def visit_Arel_Nodes_SelectStatement o, collector
344
341
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
345
342
  o = o.dup
@@ -348,7 +345,7 @@ module ArelExtensions
348
345
  old_visit_Arel_Nodes_SelectStatement(o,collector)
349
346
  end
350
347
 
351
- alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
348
+ alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
352
349
  def visit_Arel_Nodes_As o, collector
353
350
  if o.left.is_a?(Arel::Nodes::Binary)
354
351
  collector << '('
@@ -447,9 +444,9 @@ module ArelExtensions
447
444
  collector
448
445
  end
449
446
 
450
- # JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
447
+ # JSON if implemented only after 10.2.3 (aggregations after 10.5.0) in MariaDb and 5.7 (aggregations after 5.7.22) in MySql
451
448
  def json_supported?
452
- version_supported?('10.2.3', '5.7.0')
449
+ version_supported?('10.5.0', '5.7.22')
453
450
  end
454
451
 
455
452
  def window_supported?
@@ -467,21 +464,22 @@ module ArelExtensions
467
464
  conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
468
465
  conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
469
466
  !conn.send(:mariadb?) && \
470
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
471
- conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
472
- conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
467
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
468
+ conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
469
+ conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
473
470
  # ideally we should parse the instance_variable @full_version because @version contains only the supposedly
474
471
  # corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
475
472
  end
476
473
 
477
474
  def visit_ArelExtensions_Nodes_Json o,collector
478
475
  return super if !json_supported?
476
+
479
477
  case o.dict
480
478
  when Array
481
479
  collector << 'JSON_ARRAY('
482
480
  o.dict.each.with_index do |v,i|
483
481
  if i != 0
484
- collector << Arel::Visitors::MySQL::COMMA
482
+ collector << COMMA
485
483
  end
486
484
  collector = visit v, collector
487
485
  end
@@ -490,10 +488,10 @@ module ArelExtensions
490
488
  collector << 'JSON_OBJECT('
491
489
  o.dict.each.with_index do |(k,v),i|
492
490
  if i != 0
493
- collector << Arel::Visitors::MySQL::COMMA
491
+ collector << COMMA
494
492
  end
495
493
  collector = visit k, collector
496
- collector << Arel::Visitors::MySQL::COMMA
494
+ collector << COMMA
497
495
  collector = visit v, collector
498
496
  end
499
497
  collector << ')'
@@ -507,7 +505,7 @@ module ArelExtensions
507
505
  collector << 'JSON_MERGE_PATCH('
508
506
  o.expressions.each.with_index do |v,i|
509
507
  if i != 0
510
- collector << Arel::Visitors::MySQL::COMMA
508
+ collector << COMMA
511
509
  end
512
510
  collector = visit v, collector
513
511
  end
@@ -518,7 +516,7 @@ module ArelExtensions
518
516
  def visit_ArelExtensions_Nodes_JsonGet o,collector
519
517
  collector << 'JSON_EXTRACT('
520
518
  collector = visit o.dict, collector
521
- collector << Arel::Visitors::MySQL::COMMA
519
+ collector << COMMA
522
520
  if o.key.is_a?(Integer)
523
521
  collector << "\"$[#{o.key}]\""
524
522
  else
@@ -531,13 +529,13 @@ module ArelExtensions
531
529
  def visit_ArelExtensions_Nodes_JsonSet o,collector
532
530
  collector << 'JSON_SET('
533
531
  collector = visit o.dict, collector
534
- collector << Arel::Visitors::MySQL::COMMA
532
+ collector << COMMA
535
533
  if o.key.is_a?(Integer)
536
534
  collector << "\"$[#{o.key}]\""
537
535
  else
538
536
  collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
539
537
  end
540
- collector << Arel::Visitors::MySQL::COMMA
538
+ collector << COMMA
541
539
  collector = visit o.value, collector
542
540
  collector << ')'
543
541
  collector
@@ -545,6 +543,7 @@ module ArelExtensions
545
543
 
546
544
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
547
545
  return super if !json_supported?
546
+
548
547
  if o.as_array
549
548
  collector << 'JSON_ARRAYAGG('
550
549
  collector = visit o.dict, collector
@@ -555,11 +554,11 @@ module ArelExtensions
555
554
  collector << 'JSON_MERGE_PATCH(' if o.dict.length > 1
556
555
  o.dict.each.with_index do |(k,v),i|
557
556
  if i != 0
558
- collector << Arel::Visitors::MySQL::COMMA
557
+ collector << COMMA
559
558
  end
560
559
  collector << 'JSON_OBJECTAGG('
561
560
  collector = visit k, collector
562
- collector << Arel::Visitors::MySQL::COMMA
561
+ collector << COMMA
563
562
  collector = visit v, collector
564
563
  collector << ')'
565
564
  end
@@ -572,7 +571,6 @@ module ArelExtensions
572
571
  end
573
572
  collector
574
573
  end
575
-
576
574
  end
577
575
  end
578
576
  end
@@ -1,22 +1,21 @@
1
- #require 'oracle_visitor'
1
+ # require 'oracle_visitor'
2
2
  module ArelExtensions
3
3
  module Visitors
4
4
  class Arel::Visitors::Oracle
5
-
6
5
  SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
7
- Arel::Visitors::Oracle::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
8
- Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES = {
6
+ DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
7
+ DATE_FORMAT_DIRECTIVES = {
9
8
  '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
10
9
  '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
11
10
  '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
12
11
  '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
13
12
  }
14
- Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
13
+ NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
15
14
 
16
15
  def visit_ArelExtensions_Nodes_Log10 o, collector
17
16
  collector << "LOG("
18
17
  o.expressions.each_with_index { |arg, i|
19
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
18
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
20
19
  collector = visit arg, collector
21
20
  }
22
21
  collector << ",10)"
@@ -26,7 +25,7 @@ module ArelExtensions
26
25
  def visit_ArelExtensions_Nodes_Power o, collector
27
26
  collector << "POWER("
28
27
  o.expressions.each_with_index { |arg, i|
29
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
28
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
30
29
  collector = visit arg, collector
31
30
  }
32
31
  collector << ")"
@@ -93,7 +92,6 @@ module ArelExtensions
93
92
  end
94
93
  end
95
94
 
96
-
97
95
  def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
98
96
  collector << 'LOWER('
99
97
  collector = visit o.left, collector
@@ -112,25 +110,25 @@ module ArelExtensions
112
110
  if o.ai
113
111
  collector << "NLSSORT("
114
112
  collector = visit o.expressions.first, collector
115
- collector << Arel::Visitors::Oracle::COMMA
113
+ collector << COMMA
116
114
  collector << "'NLS_SORT = BINARY_AI NLS_COMP = LINGUISTIC'"
117
115
  collector << ")"
118
116
  elsif o.ci
119
117
  collector << "NLSSORT("
120
118
  collector = visit o.expressions.first, collector
121
- collector << Arel::Visitors::Oracle::COMMA
119
+ collector << COMMA
122
120
  collector << "'NLS_SORT = BINARY_CI NLS_COMP = LINGUISTIC'"
123
121
  collector << ")"
124
122
  else
125
123
  collector = visit o.expressions.first, collector
126
124
  end
127
- collector
125
+ collector
128
126
  end
129
127
 
130
128
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
131
129
  collector << "(LISTAGG("
132
130
  collector = visit o.left, collector
133
- collector << Arel::Visitors::Oracle::COMMA
131
+ collector << COMMA
134
132
  collector =
135
133
  if o.separator && o.separator != 'NULL'
136
134
  visit o.separator, collector
@@ -140,7 +138,7 @@ module ArelExtensions
140
138
  collector << ") WITHIN GROUP (ORDER BY "
141
139
  if !o.order.blank?
142
140
  o.order.each_with_index do |order,i|
143
- collector << Arel::Visitors::Oracle::COMMA unless i == 0
141
+ collector << COMMA if i != 0
144
142
  collector = visit order, collector
145
143
  end
146
144
  else
@@ -153,7 +151,7 @@ module ArelExtensions
153
151
  def visit_ArelExtensions_Nodes_Coalesce o, collector
154
152
  collector << "COALESCE("
155
153
  o.expressions.each_with_index { |arg, i|
156
- collector << Arel::Visitors::Oracle::COMMA unless i == 0
154
+ collector << COMMA if i != 0
157
155
  if i > 0 && o.left_node_type == :text
158
156
  if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
159
157
  collector << "NULL"
@@ -196,7 +194,7 @@ module ArelExtensions
196
194
  collector << 'TO_DATE(' if lc
197
195
  collector = visit o.left, collector
198
196
  collector << ')' if lc
199
- collector << Arel::Visitors::Oracle::COMMA
197
+ collector << COMMA
200
198
  collector << "'DDD') = "
201
199
  collector << 'TO_DATE(' if lc
202
200
  collector = visit o.left, collector
@@ -222,8 +220,8 @@ module ArelExtensions
222
220
  when 'wd', 'w'
223
221
  collector << "TO_CHAR("
224
222
  collector = visit o.right, collector
225
- collector << Arel::Visitors::Oracle::COMMA
226
- collector = visit Arel::Nodes.build_quoted(Arel::Visitors::Oracle::DATE_MAPPING[o.left]), collector
223
+ collector << COMMA
224
+ collector = visit Arel::Nodes.build_quoted(DATE_MAPPING[o.left]), collector
227
225
  else
228
226
  right = case o.left
229
227
  when 'd','m','y'
@@ -233,7 +231,7 @@ module ArelExtensions
233
231
  interval = 'SECOND'
234
232
  o.right.cast(:datetime)
235
233
  when /i\z/
236
- interval = Arel::Visitors::Oracle::DATE_MAPPING[o.left[0..-2]]
234
+ interval = DATE_MAPPING[o.left[0..-2]]
237
235
  collector << '('
238
236
  collector = visit o.right, collector
239
237
  collector << ") * (INTERVAL '1' #{interval})"
@@ -242,7 +240,7 @@ module ArelExtensions
242
240
  interval = nil
243
241
  o.right
244
242
  end
245
- collector << "EXTRACT(#{Arel::Visitors::Oracle::DATE_MAPPING[o.left]} FROM "
243
+ collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
246
244
  collector = visit right, collector
247
245
  end
248
246
  collector << ")"
@@ -257,6 +255,16 @@ module ArelExtensions
257
255
  collector = visit o.left, collector
258
256
  collector << ")"
259
257
  return collector
258
+ when :text
259
+ collector << "TO_CLOB("
260
+ collector = visit o.left, collector
261
+ collector << ")"
262
+ return collector
263
+ when :ntext
264
+ collector << "TO_NCLOB("
265
+ collector = visit o.left, collector
266
+ collector << ")"
267
+ return collector
260
268
  when :time
261
269
  if (o.left.respond_to?(:return_type) && o.left.return_type == :string) || o.left.is_a?(Arel::Nodes::Quoted)
262
270
  collector << "TO_DATE("
@@ -322,7 +330,7 @@ module ArelExtensions
322
330
  collector << "DBMS_RANDOM.VALUE("
323
331
  if o.left && o.right
324
332
  collector = visit o.left, collector
325
- collector << Arel::Visitors::Oracle::COMMA
333
+ collector << COMMA
326
334
  collector = visit o.right, collector
327
335
  end
328
336
  collector << ")"
@@ -332,7 +340,7 @@ module ArelExtensions
332
340
  def visit_Arel_Nodes_Regexp o, collector
333
341
  collector << " REGEXP_LIKE("
334
342
  collector = visit o.left, collector
335
- collector << Arel::Visitors::Oracle::COMMA
343
+ collector << COMMA
336
344
  collector = visit o.right, collector
337
345
  collector << ')'
338
346
  collector
@@ -341,7 +349,7 @@ module ArelExtensions
341
349
  def visit_Arel_Nodes_NotRegexp o, collector
342
350
  collector << " NOT REGEXP_LIKE("
343
351
  collector = visit o.left, collector
344
- collector << Arel::Visitors::Oracle::COMMA
352
+ collector << COMMA
345
353
  collector = visit o.right, collector
346
354
  collector << ')'
347
355
  collector
@@ -350,7 +358,7 @@ module ArelExtensions
350
358
  def visit_ArelExtensions_Nodes_Locate o, collector
351
359
  collector << "INSTR("
352
360
  o.expressions.each_with_index { |arg, i|
353
- collector << Arel::Visitors::Oracle::COMMA unless i == 0
361
+ collector << COMMA if i != 0
354
362
  collector = visit arg, collector
355
363
  }
356
364
  collector << ")"
@@ -360,7 +368,7 @@ module ArelExtensions
360
368
  def visit_ArelExtensions_Nodes_Substring o, collector
361
369
  collector << "SUBSTR("
362
370
  o.expressions.each_with_index { |arg, i|
363
- collector << Arel::Visitors::Oracle::COMMA unless i == 0
371
+ collector << COMMA if i != 0
364
372
  collector = visit arg, collector
365
373
  }
366
374
  collector << ")"
@@ -379,11 +387,11 @@ module ArelExtensions
379
387
  if o.type_of_attribute(o.left) == :text
380
388
  collector << 'dbms_lob.SUBSTR('
381
389
  collector = visit o.left, collector
382
- collector << Arel::Visitors::Oracle::COMMA
390
+ collector << COMMA
383
391
  collector << 'COALESCE(dbms_lob.GETLENGTH('
384
392
  collector = visit o.left, collector
385
393
  collector << "), 0)"
386
- collector << Arel::Visitors::Oracle::COMMA
394
+ collector << COMMA
387
395
  collector << '1)'
388
396
  else
389
397
  collector = visit o.left, collector
@@ -430,28 +438,25 @@ module ArelExtensions
430
438
  def visit_ArelExtensions_Nodes_DateAdd o, collector
431
439
  collector << '('
432
440
  collector = visit o.left, collector
433
- collector << ' + '# (o.right.value >= 0 ? ' + ' : ' - ')
441
+ collector << ' + ' # (o.right.value >= 0 ? ' + ' : ' - ')
434
442
  collector = visit o.oracle_value(o.right), collector
435
443
  collector << ')'
436
444
  collector
437
445
  end
438
446
 
439
447
  def visit_ArelExtensions_Nodes_Format o, collector
448
+ fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
440
449
  collector << "TO_CHAR("
441
450
  collector = visit o.left, collector
442
- collector << Arel::Visitors::Oracle::COMMA
443
-
444
- f = o.iso_format.gsub(/\ (\w+)/, ' "\1"')
445
- Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
446
- collector = visit Arel::Nodes.build_quoted(f), collector
447
-
451
+ collector << COMMA
452
+ collector = visit Arel::Nodes.build_quoted(fmt), collector
448
453
  collector << ")"
449
454
  collector
450
455
  end
451
456
 
452
457
  def visit_ArelExtensions_Nodes_Repeat o, collector
453
458
  collector << "LPAD("
454
- collector = visit o.expressions[0], collector #can't put empty string, otherwise it wouldn't work
459
+ collector = visit o.expressions[0], collector # can't put empty string, otherwise it wouldn't work
455
460
  collector << Arel::Visitors::ToSql::COMMA
456
461
  collector = visit o.expressions[1], collector
457
462
  collector << Arel::Visitors::ToSql::COMMA
@@ -460,24 +465,24 @@ module ArelExtensions
460
465
  collector
461
466
  end
462
467
 
463
- # add primary_key if not present, avoid zip
468
+ # add primary_key if not present, avoid zip
464
469
  if Arel::VERSION.to_i < 7
465
470
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
466
471
  collector << "("
467
472
  o.left.each_with_index do |row, idx| # values
468
473
  collector << " UNION ALL " if idx != 0
469
- collector << "(SELECT "
470
- len = row.length - 1
471
- row.zip(o.cols).each_with_index { |(value, attr), i|
472
- case value
473
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
474
- collector = visit value, collector
475
- else
476
- collector << quote(value, attr && column_for(attr)).to_s
477
- end
478
- collector << Arel::Visitors::Oracle::COMMA unless i == len
479
- }
480
- collector << ' FROM DUAL)'
474
+ collector << "(SELECT "
475
+ len = row.length - 1
476
+ row.zip(o.cols).each_with_index { |(value, attr), i|
477
+ case value
478
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
479
+ collector = visit value, collector
480
+ else
481
+ collector << quote(value, attr && column_for(attr)).to_s
482
+ end
483
+ collector << COMMA unless i == len
484
+ }
485
+ collector << ' FROM DUAL)'
481
486
  end
482
487
  collector << ")"
483
488
  collector
@@ -498,7 +503,7 @@ module ArelExtensions
498
503
  else
499
504
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
500
505
  end
501
- collector << Arel::Visitors::Oracle::COMMA unless i == len
506
+ collector << COMMA unless i == len
502
507
  }
503
508
  collector << ' FROM DUAL)'
504
509
  end
@@ -557,7 +562,7 @@ module ArelExtensions
557
562
  end
558
563
 
559
564
 
560
- alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
565
+ alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
561
566
  def visit_Arel_Nodes_SelectStatement o, collector
562
567
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
563
568
  o = o.dup
@@ -566,7 +571,7 @@ module ArelExtensions
566
571
  old_visit_Arel_Nodes_SelectStatement(o,collector)
567
572
  end
568
573
 
569
- alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
574
+ alias_method(:old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias) rescue nil
570
575
  def visit_Arel_Nodes_TableAlias o, collector
571
576
  if o.name.length > 30
572
577
  o = Arel::Table.new(o.table_name).alias(Base64.urlsafe_encode64(Digest::MD5.new.digest(o.name)).tr('=', '').tr('-', '_'))
@@ -574,7 +579,7 @@ module ArelExtensions
574
579
  old_visit_Arel_Nodes_TableAlias(o,collector)
575
580
  end
576
581
 
577
- alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
582
+ alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
578
583
  def visit_Arel_Nodes_As o, collector
579
584
  if o.left.is_a?(Arel::Nodes::Binary)
580
585
  collector << '('
@@ -594,7 +599,7 @@ module ArelExtensions
594
599
  visit_Arel_Nodes_As o, collector
595
600
  end
596
601
 
597
- alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
602
+ alias_method(:old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute) rescue nil
598
603
  def visit_Arel_Attributes_Attribute o, collector
599
604
  join_name = o.relation.table_alias || o.relation.name
600
605
  if join_name.length > 30
@@ -603,10 +608,9 @@ module ArelExtensions
603
608
  collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
604
609
  end
605
610
 
606
-
607
611
  def visit_ArelExtensions_Nodes_FormattedNumber o, collector
608
612
  col = o.left.coalesce(0)
609
- comma = Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING[o.locale] || '.,'
613
+ comma = NUMBER_COMMA_MAPPING[o.locale] || '.,'
610
614
  comma_in_format = o.precision == 0 ? '' : 'D'
611
615
  nines_after = (1..o.precision-1).map{'9'}.join('')+'0'
612
616
  if comma.length == 1
@@ -683,7 +687,6 @@ module ArelExtensions
683
687
  collector << ')'
684
688
  collector
685
689
  end
686
-
687
690
  end
688
691
  end
689
692
  end