arel_extensions 1.2.13 → 1.2.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) 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/arel_extensions.gemspec +1 -1
  6. data/gemfiles/rails3.gemfile +9 -9
  7. data/gemfiles/rails4.gemfile +13 -13
  8. data/gemfiles/rails5_0.gemfile +13 -13
  9. data/gemfiles/rails5_1_4.gemfile +13 -13
  10. data/gemfiles/rails5_2.gemfile +13 -13
  11. data/gemfiles/rails6.gemfile +13 -13
  12. data/lib/arel_extensions.rb +3 -3
  13. data/lib/arel_extensions/attributes.rb +0 -0
  14. data/lib/arel_extensions/boolean_functions.rb +21 -5
  15. data/lib/arel_extensions/common_sql_functions.rb +2 -4
  16. data/lib/arel_extensions/comparators.rb +11 -14
  17. data/lib/arel_extensions/date_duration.rb +4 -5
  18. data/lib/arel_extensions/insert_manager.rb +16 -17
  19. data/lib/arel_extensions/math.rb +8 -9
  20. data/lib/arel_extensions/math_functions.rb +15 -17
  21. data/lib/arel_extensions/nodes/abs.rb +0 -1
  22. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -1
  23. data/lib/arel_extensions/nodes/blank.rb +0 -1
  24. data/lib/arel_extensions/nodes/case.rb +3 -4
  25. data/lib/arel_extensions/nodes/cast.rb +4 -2
  26. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  27. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  28. data/lib/arel_extensions/nodes/coalesce.rb +0 -1
  29. data/lib/arel_extensions/nodes/collate.rb +0 -1
  30. data/lib/arel_extensions/nodes/concat.rb +1 -3
  31. data/lib/arel_extensions/nodes/date_diff.rb +7 -8
  32. data/lib/arel_extensions/nodes/duration.rb +0 -1
  33. data/lib/arel_extensions/nodes/find_in_set.rb +0 -1
  34. data/lib/arel_extensions/nodes/floor.rb +1 -1
  35. data/lib/arel_extensions/nodes/format.rb +27 -1
  36. data/lib/arel_extensions/nodes/formatted_number.rb +0 -1
  37. data/lib/arel_extensions/nodes/function.rb +18 -15
  38. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  39. data/lib/arel_extensions/nodes/json.rb +39 -30
  40. data/lib/arel_extensions/nodes/length.rb +0 -1
  41. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  42. data/lib/arel_extensions/nodes/locate.rb +0 -1
  43. data/lib/arel_extensions/nodes/log10.rb +1 -2
  44. data/lib/arel_extensions/nodes/matches.rb +0 -2
  45. data/lib/arel_extensions/nodes/md5.rb +0 -1
  46. data/lib/arel_extensions/nodes/power.rb +0 -1
  47. data/lib/arel_extensions/nodes/rand.rb +0 -1
  48. data/lib/arel_extensions/nodes/repeat.rb +0 -2
  49. data/lib/arel_extensions/nodes/replace.rb +0 -2
  50. data/lib/arel_extensions/nodes/round.rb +0 -1
  51. data/lib/arel_extensions/nodes/soundex.rb +0 -1
  52. data/lib/arel_extensions/nodes/std.rb +0 -1
  53. data/lib/arel_extensions/nodes/substring.rb +0 -1
  54. data/lib/arel_extensions/nodes/sum.rb +0 -0
  55. data/lib/arel_extensions/nodes/then.rb +0 -0
  56. data/lib/arel_extensions/nodes/trim.rb +0 -2
  57. data/lib/arel_extensions/nodes/union.rb +0 -2
  58. data/lib/arel_extensions/nodes/union_all.rb +0 -2
  59. data/lib/arel_extensions/nodes/wday.rb +0 -4
  60. data/lib/arel_extensions/null_functions.rb +3 -5
  61. data/lib/arel_extensions/predications.rb +5 -6
  62. data/lib/arel_extensions/railtie.rb +5 -5
  63. data/lib/arel_extensions/set_functions.rb +0 -2
  64. data/lib/arel_extensions/string_functions.rb +21 -22
  65. data/lib/arel_extensions/tasks.rb +1 -1
  66. data/lib/arel_extensions/version.rb +1 -1
  67. data/lib/arel_extensions/visitors.rb +68 -60
  68. data/lib/arel_extensions/visitors/convert_format.rb +37 -0
  69. data/lib/arel_extensions/visitors/ibm_db.rb +4 -11
  70. data/lib/arel_extensions/visitors/mssql.rb +49 -44
  71. data/lib/arel_extensions/visitors/mysql.rb +65 -67
  72. data/lib/arel_extensions/visitors/oracle.rb +58 -55
  73. data/lib/arel_extensions/visitors/oracle12.rb +2 -3
  74. data/lib/arel_extensions/visitors/postgresql.rb +41 -34
  75. data/lib/arel_extensions/visitors/sqlite.rb +23 -18
  76. data/lib/arel_extensions/visitors/to_sql.rb +69 -61
  77. data/test/arelx_test_helper.rb +0 -2
  78. data/test/real_db_test.rb +27 -42
  79. data/test/support/fake_record.rb +1 -1
  80. data/test/test_comparators.rb +0 -4
  81. data/test/visitors/test_bulk_insert_oracle.rb +0 -1
  82. data/test/visitors/test_bulk_insert_sqlite.rb +0 -2
  83. data/test/visitors/test_oracle.rb +1 -2
  84. data/test/visitors/test_to_sql.rb +16 -25
  85. data/test/with_ar/all_agnostic_test.rb +135 -139
  86. data/test/with_ar/insert_agnostic_test.rb +0 -2
  87. data/test/with_ar/test_bulk_sqlite.rb +0 -4
  88. data/test/with_ar/test_math_sqlite.rb +4 -8
  89. data/test/with_ar/test_string_mysql.rb +1 -5
  90. data/test/with_ar/test_string_sqlite.rb +1 -5
  91. data/version_v1.rb +1 -1
  92. data/version_v2.rb +1 -1
  93. metadata +4 -3
@@ -1,6 +1,5 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
-
4
3
  Arel::Visitors.send(:remove_const,'Oracle12') if Arel::Visitors.const_defined?('Oracle12')
5
4
  Arel::Visitors.const_set('Oracle12',Class.new(Arel::Visitors::Oracle)).class_eval do
6
5
  def visit_Arel_Nodes_SelectStatement(o, collector)
@@ -12,6 +11,7 @@ module ArelExtensions
12
11
  `SELECT FOR UPDATE and FETCH FIRST n ROWS` generates ORA-02014.`
13
12
  MSG
14
13
  end
14
+
15
15
  super
16
16
  end
17
17
 
@@ -84,7 +84,7 @@ module ArelExtensions
84
84
  collector << 'FORMAT JSON'
85
85
  end
86
86
  collector << ')'
87
- when String,Numeric,TrueClass,FalseClass
87
+ when String, Numeric, TrueClass, FalseClass
88
88
  collector = visit Arel::Nodes.build_quoted("#{o.dict}"), collector
89
89
  collector << ' FORMAT JSON'
90
90
  when NilClass
@@ -97,7 +97,6 @@ module ArelExtensions
97
97
  end
98
98
  collector
99
99
  end
100
-
101
100
  end
102
101
  end
103
102
  end
@@ -1,20 +1,29 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  class Arel::Visitors::PostgreSQL
4
- Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
- Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
6
- '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
4
+ DATE_MAPPING = {
5
+ 'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW',
6
+ 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
7
+ }.freeze
8
+
9
+ DATE_FORMAT_DIRECTIVES = {
10
+ '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY',
11
+ '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
7
12
  '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
8
13
  '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
9
- '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
10
- }
11
- Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
14
+ '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz', # seconds, subseconds
15
+ '%%' => '%',
16
+ }.freeze
17
+
18
+ NUMBER_COMMA_MAPPING = {
19
+ 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '
20
+ }.freeze
12
21
 
13
22
  def visit_ArelExtensions_Nodes_Rand o, collector
14
23
  collector << "RANDOM("
15
- if(o.left != nil && o.right != nil)
24
+ if (o.left != nil && o.right != nil)
16
25
  collector = visit o.left, collector
17
- collector << Arel::Visitors::PostgreSQL::COMMA
26
+ collector << COMMA
18
27
  collector = isit o.right, collector
19
28
  end
20
29
  collector << ")"
@@ -24,7 +33,7 @@ module ArelExtensions
24
33
  def visit_ArelExtensions_Nodes_Power o, collector
25
34
  collector << "POWER("
26
35
  o.expressions.each_with_index { |arg, i|
27
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
36
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
28
37
  collector = visit arg, collector
29
38
  }
30
39
  collector << ")"
@@ -34,7 +43,7 @@ module ArelExtensions
34
43
  def visit_ArelExtensions_Nodes_Log10 o, collector
35
44
  collector << "LOG("
36
45
  o.expressions.each_with_index { |arg, i|
37
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
46
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
38
47
  collector = visit arg, collector
39
48
  }
40
49
  collector << ")"
@@ -68,7 +77,7 @@ module ArelExtensions
68
77
  collector
69
78
  end
70
79
 
71
- alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
80
+ alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
72
81
  def visit_Arel_Nodes_As o, collector
73
82
  if o.left.is_a?(Arel::Nodes::Binary)
74
83
  collector << '('
@@ -89,14 +98,14 @@ module ArelExtensions
89
98
  if !o.group.blank?
90
99
  collector << " PARTITION BY "
91
100
  o.group.each_with_index do |group, i|
92
- collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
101
+ collector << COMMA if i != 0
93
102
  visit group, collector
94
103
  end
95
104
  end
96
105
  if !o.order.blank?
97
106
  collector << " ORDER BY "
98
107
  o.order.each_with_index do |order, i|
99
- collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
108
+ collector << COMMA if i != 0
100
109
  visit order, collector
101
110
  end
102
111
  end
@@ -111,7 +120,7 @@ module ArelExtensions
111
120
  if o.order && !o.order.blank?
112
121
  collector << " ORDER BY"
113
122
  o.order.each_with_index do |order, i|
114
- collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
123
+ collector << COMMA if i != 0
115
124
  collector << " "
116
125
  visit order, collector
117
126
  end
@@ -119,7 +128,7 @@ module ArelExtensions
119
128
  collector << ")"
120
129
  o.order = nil
121
130
  visit_Aggregate_For_AggregateFunction o, collector
122
- collector << Arel::Visitors::PostgreSQL::COMMA
131
+ collector << COMMA
123
132
  collector =
124
133
  if o.separator && o.separator != 'NULL'
125
134
  visit o.separator, collector
@@ -158,14 +167,11 @@ module ArelExtensions
158
167
  end
159
168
 
160
169
  def visit_ArelExtensions_Nodes_Format o, collector
170
+ fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
161
171
  collector << "TO_CHAR("
162
172
  collector = visit o.left, collector
163
- collector << Arel::Visitors::PostgreSQL::COMMA
164
-
165
- f = o.iso_format.dup
166
- Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
167
- collector = visit Arel::Nodes.build_quoted(f), collector
168
-
173
+ collector << COMMA
174
+ collector = visit Arel::Nodes.build_quoted(fmt), collector
169
175
  collector << ")"
170
176
  collector
171
177
  end
@@ -173,7 +179,7 @@ module ArelExtensions
173
179
  def visit_ArelExtensions_Nodes_Repeat o, collector
174
180
  collector << "REPEAT("
175
181
  o.expressions.each_with_index { |arg, i|
176
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
182
+ collector << Arel::Visitors::ToSql::COMMA if i != 0
177
183
  collector = visit arg, collector
178
184
  }
179
185
  collector << ")"
@@ -231,7 +237,7 @@ module ArelExtensions
231
237
 
232
238
  def visit_ArelExtensions_Nodes_DateAdd o, collector
233
239
  collector = visit o.left, collector
234
- collector << ' + ' #(o.right.value >= 0 ? ' + ' : ' - ')
240
+ collector << ' + ' # (o.right.value >= 0 ? ' + ' : ' - ')
235
241
  collector = visit o.postgresql_value(o.right), collector
236
242
  collector
237
243
  end
@@ -245,7 +251,7 @@ module ArelExtensions
245
251
  end
246
252
  collector = visit o.right, collector
247
253
  collector << (o.right_node_type == :date ? '::date' : '::timestamp')
248
- collector << Arel::Visitors::PostgreSQL::COMMA
254
+ collector << COMMA
249
255
  collector = visit o.left, collector
250
256
  collector << (o.left_node_type == :date ? '::date' : '::timestamp')
251
257
  collector << ")"
@@ -273,11 +279,11 @@ module ArelExtensions
273
279
  collector << "("
274
280
  collector = visit o.right, collector
275
281
  collector << ")"
276
- collector << " * (INTERVAL '1' #{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left[0..-2]]})"
282
+ collector << " * (INTERVAL '1' #{DATE_MAPPING[o.left[0..-2]]})"
277
283
  return collector
278
284
  end
279
285
  end
280
- collector << "EXTRACT(#{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left]} FROM "
286
+ collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
281
287
  collector = visit o.right, collector
282
288
  collector << ")"
283
289
  collector << " * (INTERVAL '1' #{interval})" if interval && o.with_interval
@@ -296,7 +302,7 @@ module ArelExtensions
296
302
  def visit_ArelExtensions_Nodes_Substring o, collector
297
303
  collector << "SUBSTR("
298
304
  o.expressions.each_with_index { |arg, i|
299
- collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
305
+ collector << COMMA if i != 0
300
306
  collector = visit arg, collector
301
307
  }
302
308
  collector << ")"
@@ -308,7 +314,7 @@ module ArelExtensions
308
314
  visit o.left, collector
309
315
  collector << Arel::Visitors::ToSql::COMMA
310
316
  tab = o.pattern.inspect+ 'g' # Make it always global
311
- pattern = tab.split('/')[1..-2].join('/')
317
+ pattern = tab.split('/')[1..-2].join('/')
312
318
  flags = tab.split('/')[-1]
313
319
  visit Arel::Nodes.build_quoted(pattern), collector
314
320
  collector << Arel::Visitors::ToSql::COMMA
@@ -350,6 +356,8 @@ module ArelExtensions
350
356
  as_attr = case o.as_attr
351
357
  when :string
352
358
  Arel::Nodes::SqlLiteral.new('varchar')
359
+ when :text, :ntext
360
+ Arel::Nodes::SqlLiteral.new('text')
353
361
  when :time
354
362
  Arel::Nodes::SqlLiteral.new('time')
355
363
  when :int
@@ -378,8 +386,8 @@ module ArelExtensions
378
386
 
379
387
  def visit_ArelExtensions_Nodes_FormattedNumber o, collector
380
388
  col = o.left.coalesce(0)
381
- comma = o.precision == 0 ? '' : (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][0] || '.')
382
- thousand_separator = Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][1] || (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
389
+ comma = o.precision == 0 ? '' : (NUMBER_COMMA_MAPPING[o.locale][0] || '.')
390
+ thousand_separator = NUMBER_COMMA_MAPPING[o.locale][1] || (NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
383
391
  nines_after = (1..o.precision).map{'9'}.join('')
384
392
  nines_before = ("999#{thousand_separator}"*4+"990")
385
393
 
@@ -433,7 +441,7 @@ module ArelExtensions
433
441
  end
434
442
 
435
443
 
436
- alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
444
+ alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
437
445
  def visit_Arel_Nodes_SelectStatement o, collector
438
446
 
439
447
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
@@ -443,7 +451,7 @@ module ArelExtensions
443
451
  old_visit_Arel_Nodes_SelectStatement(o,collector)
444
452
  end
445
453
 
446
- alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
454
+ alias_method(:old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias) rescue nil
447
455
  def visit_Arel_Nodes_TableAlias o, collector
448
456
  if o.name.length > 63
449
457
  o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
@@ -451,7 +459,7 @@ module ArelExtensions
451
459
  old_visit_Arel_Nodes_TableAlias(o,collector)
452
460
  end
453
461
 
454
- alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
462
+ alias_method(:old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute) rescue nil
455
463
  def visit_Arel_Attributes_Attribute o, collector
456
464
  join_name = o.relation.table_alias || o.relation.name
457
465
  if join_name.length > 63
@@ -569,7 +577,6 @@ module ArelExtensions
569
577
  end
570
578
  collector
571
579
  end
572
-
573
580
  end
574
581
  end
575
582
  end
@@ -1,16 +1,23 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  class Arel::Visitors::SQLite
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
- Arel::Visitors::SQLite::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
4
+ DATE_MAPPING = {
5
+ 'd' => '%d', 'm' => '%m', 'w' => '%W', 'y' => '%Y', 'wd' => '%w', 'M' => '%M',
6
+ 'h' => '%H', 'mn' => '%M', 's' => '%S'
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' => '%M', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => '' # seconds, subseconds
10
- }
11
- Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING = { 'fr_FR' => {',' => ' ','.' =>','} }
14
+ }.freeze
15
+
16
+ NUMBER_COMMA_MAPPING = {
17
+ 'fr_FR' => {',' => ' ', '.' =>','}
18
+ }.freeze
12
19
 
13
- #String functions
20
+ # String functions
14
21
  def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
15
22
  collector = visit o.left.ci_collate, collector
16
23
  collector << ' LIKE '
@@ -73,7 +80,6 @@ module ArelExtensions
73
80
  collector
74
81
  end
75
82
 
76
-
77
83
  def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
78
84
  collector = visit o.left.lower, collector
79
85
  collector << ' NOT LIKE '
@@ -90,14 +96,15 @@ module ArelExtensions
90
96
  def visit_ArelExtensions_Nodes_DateAdd o, collector
91
97
  collector << "date("
92
98
  collector = visit o.expressions.first, collector
93
- collector << Arel::Visitors::SQLite::COMMA
99
+ collector << COMMA
94
100
  collector = visit o.sqlite_value, collector
95
101
  collector << ")"
96
102
  collector
97
103
  end
98
104
 
99
105
  def visit_ArelExtensions_Nodes_DateDiff o, collector
100
- if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
106
+ case o.left_node_type
107
+ when :ruby_time, :datetime, :time
101
108
  collector << "strftime('%s', "
102
109
  collector = visit o.left, collector
103
110
  collector << ") - strftime('%s', "
@@ -113,17 +120,16 @@ module ArelExtensions
113
120
  end
114
121
 
115
122
  def visit_ArelExtensions_Nodes_Duration o, collector
116
- collector << "strftime('#{Arel::Visitors::SQLite::DATE_MAPPING[o.left]}'#{Arel::Visitors::SQLite::COMMA}"
123
+ collector << "strftime('#{DATE_MAPPING[o.left]}'#{COMMA}"
117
124
  collector = visit o.right, collector
118
125
  collector << ")"
119
126
  collector
120
127
  end
121
128
 
122
-
123
129
  def visit_ArelExtensions_Nodes_Locate o, collector
124
130
  collector << "instr("
125
131
  collector = visit o.expr, collector
126
- collector << Arel::Visitors::SQLite::COMMA
132
+ collector << COMMA
127
133
  collector = visit o.right, collector
128
134
  collector << ")"
129
135
  collector
@@ -142,7 +148,7 @@ module ArelExtensions
142
148
  def visit_ArelExtensions_Nodes_Substring o, collector
143
149
  collector << "SUBSTR("
144
150
  o.expressions.each_with_index { |arg, i|
145
- collector << Arel::Visitors::SQLite::COMMA unless i == 0
151
+ collector << COMMA if i != 0
146
152
  collector = visit arg, collector
147
153
  }
148
154
  collector << ")"
@@ -165,7 +171,7 @@ module ArelExtensions
165
171
  collector << "RANDOM("
166
172
  if o.left != nil && o.right != nil
167
173
  collector = visit o.left, collector
168
- collector << Arel::Visitors::SQLite::COMMA
174
+ collector << COMMA
169
175
  collector = visit o.right, collector
170
176
  end
171
177
  collector << ")"
@@ -247,7 +253,7 @@ module ArelExtensions
247
253
  collector << quote(attr.name)
248
254
  end
249
255
  end
250
- collector << Arel::Visitors::SQLite::COMMA unless i == len
256
+ collector << COMMA unless i == len
251
257
  }
252
258
  collector << ' UNION ALL ' unless idx == o.left.length - 1
253
259
  end
@@ -275,7 +281,7 @@ module ArelExtensions
275
281
  collector << quote(attr.name)
276
282
  end
277
283
  end
278
- collector << Arel::Visitors::SQLite::COMMA unless i == len
284
+ collector << COMMA unless i == len
279
285
  }
280
286
  collector << ' UNION ALL ' unless idx == o.left.length - 1
281
287
  end
@@ -364,7 +370,7 @@ module ArelExtensions
364
370
  collector
365
371
  end
366
372
 
367
- alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
373
+ alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
368
374
  def visit_Arel_Nodes_As o, collector
369
375
  if o.left.is_a?(Arel::Nodes::Binary)
370
376
  collector << '('
@@ -381,14 +387,13 @@ module ArelExtensions
381
387
 
382
388
  def visit_ArelExtensions_Nodes_FormattedNumber o, collector
383
389
  format = Arel::Nodes::NamedFunction.new('printf',[Arel::Nodes.build_quoted(o.original_string),o.left])
384
- locale_map = Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING[o.locale]
390
+ locale_map = NUMBER_COMMA_MAPPING[o.locale]
385
391
  if locale_map
386
392
  format = format.replace(',',locale_map[',']).replace('.',locale_map['.'])
387
393
  end
388
394
  visit format, collector
389
395
  collector
390
396
  end
391
-
392
397
  end
393
398
  end
394
399
  end
@@ -1,13 +1,13 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  class Arel::Visitors::ToSql
4
- Arel::Visitors::ToSql::COMMA = ', ' unless defined?(Arel::Visitors::ToSql::COMMA)
4
+ COMMA = ', ' unless defined?(COMMA)
5
5
 
6
6
  # Math Functions
7
7
  def visit_ArelExtensions_Nodes_Abs o, collector
8
8
  collector << "ABS("
9
9
  o.expressions.each_with_index { |arg, i|
10
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
10
+ collector << COMMA if i != 0
11
11
  collector = visit arg, collector
12
12
  }
13
13
  collector << ")"
@@ -17,7 +17,7 @@ module ArelExtensions
17
17
  def visit_ArelExtensions_Nodes_Ceil o, collector
18
18
  collector << "CEIL("
19
19
  o.expressions.each_with_index { |arg, i|
20
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
20
+ collector << COMMA if i != 0
21
21
  collector = visit arg, collector
22
22
  }
23
23
  collector << ")"
@@ -27,7 +27,7 @@ module ArelExtensions
27
27
  def visit_ArelExtensions_Nodes_Floor o, collector
28
28
  collector << "FLOOR("
29
29
  o.expressions.each_with_index { |arg, i|
30
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
30
+ collector << COMMA if i != 0
31
31
  collector = visit arg, collector
32
32
  }
33
33
  collector << ")"
@@ -37,7 +37,7 @@ module ArelExtensions
37
37
  def visit_ArelExtensions_Nodes_Rand o, collector
38
38
  collector << "RAND("
39
39
  o.expressions.each_with_index { |arg, i|
40
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
40
+ collector << COMMA if i != 0
41
41
  collector = visit arg, collector
42
42
  }
43
43
  collector << ")"
@@ -47,7 +47,7 @@ module ArelExtensions
47
47
  def visit_ArelExtensions_Nodes_Round o, collector
48
48
  collector << "ROUND("
49
49
  o.expressions.each_with_index { |arg, i|
50
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
50
+ collector << COMMA if i != 0
51
51
  collector = visit arg, collector
52
52
  }
53
53
  collector << ")"
@@ -64,7 +64,7 @@ module ArelExtensions
64
64
  def visit_ArelExtensions_Nodes_Power o, collector
65
65
  collector << "POW("
66
66
  o.expressions.each_with_index { |arg, i|
67
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
67
+ collector << COMMA if i != 0
68
68
  collector = visit arg, collector
69
69
  }
70
70
  collector << ")"
@@ -81,9 +81,9 @@ module ArelExtensions
81
81
  # String functions
82
82
  def visit_ArelExtensions_Nodes_Concat o, collector
83
83
  collector << "CONCAT("
84
- o.expressions.each_with_index { |arg, i|
85
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
86
- collector = visit arg, collector
84
+ o.expressions.each_with_index { |arg, i|
85
+ collector << COMMA if i != 0
86
+ collector = visit arg, collector
87
87
  }
88
88
  collector << ")"
89
89
  collector
@@ -93,7 +93,7 @@ module ArelExtensions
93
93
  collector << "GROUP_CONCAT("
94
94
  collector = visit o.left, collector
95
95
  if o.separator && o.separator != 'NULL'
96
- collector << Arel::Visitors::ToSql::COMMA
96
+ collector << COMMA
97
97
  collector = visit o.separator, collector
98
98
  end
99
99
  collector << ")"
@@ -117,7 +117,7 @@ module ArelExtensions
117
117
  def visit_ArelExtensions_Nodes_Locate o, collector
118
118
  collector << "LOCATE("
119
119
  collector = visit o.right, collector
120
- collector << Arel::Visitors::ToSql::COMMA
120
+ collector << COMMA
121
121
  collector = visit o.left, collector
122
122
  collector << ")"
123
123
  collector
@@ -126,7 +126,7 @@ module ArelExtensions
126
126
  def visit_ArelExtensions_Nodes_Substring o, collector
127
127
  collector << "SUBSTRING("
128
128
  o.expressions.each_with_index { |arg, i|
129
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
129
+ collector << COMMA if i != 0
130
130
  collector = visit arg, collector
131
131
  }
132
132
  collector << ")"
@@ -136,9 +136,9 @@ module ArelExtensions
136
136
  def visit_ArelExtensions_Nodes_Replace o, collector
137
137
  collector << "REPLACE("
138
138
  visit o.left, collector
139
- collector << Arel::Visitors::ToSql::COMMA
139
+ collector << COMMA
140
140
  visit o.pattern, collector
141
- collector << Arel::Visitors::ToSql::COMMA
141
+ collector << COMMA
142
142
  visit o.substitute, collector
143
143
  collector << ")"
144
144
  collector
@@ -147,9 +147,9 @@ module ArelExtensions
147
147
  def visit_ArelExtensions_Nodes_RegexpReplace o, collector
148
148
  collector << "REGEXP_REPLACE("
149
149
  visit o.left, collector
150
- collector << Arel::Visitors::ToSql::COMMA
150
+ collector << COMMA
151
151
  visit Arel::Nodes.build_quoted(o.pattern.to_s), collector
152
- collector << Arel::Visitors::ToSql::COMMA
152
+ collector << COMMA
153
153
  visit o.substitute, collector
154
154
  collector << ")"
155
155
  collector
@@ -158,7 +158,7 @@ module ArelExtensions
158
158
  def visit_ArelExtensions_Nodes_Repeat o, collector
159
159
  collector << "REPEAT("
160
160
  o.expressions.each_with_index { |arg, i|
161
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
161
+ collector << COMMA if i != 0
162
162
  collector = visit arg, collector
163
163
  }
164
164
  collector << ")"
@@ -168,7 +168,7 @@ module ArelExtensions
168
168
  def visit_ArelExtensions_Nodes_FindInSet o, collector
169
169
  collector << "FIND_IN_SET("
170
170
  o.expressions.each_with_index { |arg, i|
171
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
171
+ collector << COMMA if i != 0
172
172
  collector = visit arg, collector
173
173
  }
174
174
  collector << ")"
@@ -178,7 +178,7 @@ module ArelExtensions
178
178
  def visit_ArelExtensions_Nodes_Soundex o, collector
179
179
  collector << "SOUNDEX("
180
180
  o.expressions.each_with_index { |arg, i|
181
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
181
+ collector << COMMA if i != 0
182
182
  collector = visit arg, collector
183
183
  }
184
184
  collector << ")"
@@ -188,7 +188,7 @@ module ArelExtensions
188
188
  def visit_ArelExtensions_Nodes_Downcase o, collector
189
189
  collector << "LOWER("
190
190
  o.expressions.each_with_index { |arg, i|
191
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
191
+ collector << COMMA if i != 0
192
192
  collector = visit arg, collector
193
193
  }
194
194
  collector << ")"
@@ -198,7 +198,7 @@ module ArelExtensions
198
198
  def visit_ArelExtensions_Nodes_Upcase o, collector
199
199
  collector << "UPPER("
200
200
  o.expressions.each_with_index { |arg, i|
201
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
201
+ collector << COMMA if i != 0
202
202
  collector = visit arg, collector
203
203
  }
204
204
  collector << ")"
@@ -208,7 +208,7 @@ module ArelExtensions
208
208
  def visit_ArelExtensions_Nodes_Trim o, collector
209
209
  collector << "TRIM("
210
210
  o.expressions.each_with_index { |arg, i|
211
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
211
+ collector << COMMA if i != 0
212
212
  collector = visit arg, collector
213
213
  }
214
214
  collector << ")"
@@ -218,7 +218,7 @@ module ArelExtensions
218
218
  def visit_ArelExtensions_Nodes_Ltrim o, collector
219
219
  collector << "LTRIM("
220
220
  o.expressions.each_with_index { |arg, i|
221
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
221
+ collector << COMMA if i != 0
222
222
  collector = visit arg, collector
223
223
  }
224
224
  collector << ")"
@@ -228,7 +228,7 @@ module ArelExtensions
228
228
  def visit_ArelExtensions_Nodes_Rtrim o, collector
229
229
  collector << "RTRIM("
230
230
  o.expressions.each_with_index { |arg, i|
231
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
231
+ collector << COMMA if i != 0
232
232
  collector = visit arg, collector
233
233
  }
234
234
  collector << ")"
@@ -236,21 +236,20 @@ module ArelExtensions
236
236
  end
237
237
 
238
238
  def visit_ArelExtensions_Nodes_Blank o, collector
239
- #visit o.left.coalesce('').trim.length.eq(0), collector
239
+ # visit o.left.coalesce('').trim.length.eq(0), collector
240
240
  collector << 'LENGTH(TRIM(COALESCE('
241
241
  collector = visit o.expr, collector
242
- collector << Arel::Visitors::ToSql::COMMA
242
+ collector << COMMA
243
243
  collector = visit Arel::Nodes.build_quoted(''), collector
244
244
  collector << "))) = 0"
245
245
  collector
246
246
  end
247
247
 
248
-
249
248
  def visit_ArelExtensions_Nodes_NotBlank o, collector
250
- #visit o.left.coalesce('').trim.length.gt(0), collector
249
+ # visit o.left.coalesce('').trim.length.gt(0), collector
251
250
  collector << 'LENGTH(TRIM(COALESCE('
252
251
  collector = visit o.expr, collector
253
- collector << Arel::Visitors::ToSql::COMMA
252
+ collector << COMMA
254
253
  collector = visit Arel::Nodes.build_quoted(''), collector
255
254
  collector << "))) > 0"
256
255
  collector
@@ -261,13 +260,13 @@ module ArelExtensions
261
260
  when :date, :datetime, :time
262
261
  collector << "STRFTIME("
263
262
  collector = visit o.right, collector
264
- collector << Arel::Visitors::ToSql::COMMA
263
+ collector << COMMA
265
264
  collector = visit o.left, collector
266
265
  collector << ")"
267
266
  when :integer, :float, :decimal
268
267
  collector << "FORMAT("
269
268
  collector = visit o.left, collector
270
- collector << Arel::Visitors::ToSql::COMMA
269
+ collector << COMMA
271
270
  collector = visit o.right, collector
272
271
  collector << ")"
273
272
  else
@@ -276,7 +275,7 @@ module ArelExtensions
276
275
  collector
277
276
  end
278
277
 
279
- #comparators
278
+ # comparators
280
279
 
281
280
  def visit_ArelExtensions_Nodes_Cast o, collector
282
281
  collector << "CAST("
@@ -295,6 +294,8 @@ module ArelExtensions
295
294
  as_attr = Arel::Nodes::SqlLiteral.new('time')
296
295
  when :binary
297
296
  as_attr = Arel::Nodes::SqlLiteral.new('binary')
297
+ when :text, :ntext
298
+ as_attr = Arel::Nodes::SqlLiteral.new('text')
298
299
  else
299
300
  as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
300
301
  end
@@ -306,7 +307,7 @@ module ArelExtensions
306
307
  def visit_ArelExtensions_Nodes_Coalesce o, collector
307
308
  collector << "COALESCE("
308
309
  o.expressions.each_with_index { |arg, i|
309
- collector << Arel::Visitors::ToSql::COMMA unless i == 0
310
+ collector << COMMA if i != 0
310
311
  collector = visit arg, collector
311
312
  }
312
313
  collector << ")"
@@ -320,7 +321,7 @@ module ArelExtensions
320
321
  'DATEDIFF('
321
322
  end
322
323
  collector = visit o.left, collector
323
- collector << Arel::Visitors::ToSql::COMMA
324
+ collector << COMMA
324
325
  collector = visit o.right, collector
325
326
  collector << ")"
326
327
  collector
@@ -329,13 +330,13 @@ module ArelExtensions
329
330
  def visit_ArelExtensions_Nodes_DateSub o, collector
330
331
  collector << "DATE_SUB("
331
332
  collector = visit o.left, collector
332
- collector << Arel::Visitors::ToSql::COMMA
333
+ collector << COMMA
333
334
  collector = visit o.right, collector
334
335
  collector << ")"
335
336
  collector
336
337
  end
337
338
 
338
- # override
339
+ # override
339
340
  remove_method(:visit_Arel_Nodes_As) rescue nil # if Arel::Visitors::ToSql.method_defined?(:visit_Arel_Nodes_As)
340
341
  def visit_Arel_Nodes_As o, collector
341
342
  if o.left.is_a?(Arel::Nodes::Binary)
@@ -416,7 +417,7 @@ module ArelExtensions
416
417
  def visit_ArelExtensions_Nodes_DateAdd o, collector
417
418
  collector << "DATE_ADD("
418
419
  collector = visit o.left, collector
419
- collector << Arel::Visitors::ToSql::COMMA
420
+ collector << COMMA
420
421
  collector = visit o.sqlite_value(o.right), collector
421
422
  collector << ')'
422
423
  collector
@@ -436,7 +437,7 @@ module ArelExtensions
436
437
  else
437
438
  collector << quote(value, attr && column_for(attr)).to_s
438
439
  end
439
- collector << Arel::Visitors::ToSql::COMMA unless i == len
440
+ collector << COMMA unless i == len
440
441
  }
441
442
  collector << (idx == row_nb-1 ? ')' : '), ')
442
443
  end
@@ -458,7 +459,7 @@ module ArelExtensions
458
459
  else
459
460
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
460
461
  end
461
- collector << Arel::Visitors::ToSql::COMMA unless i == len
462
+ collector << COMMA unless i == len
462
463
  }
463
464
  collector << (idx == row_nb-1 ? ')' : '), ')
464
465
  end
@@ -537,7 +538,7 @@ module ArelExtensions
537
538
  def visit_ArelExtensions_Nodes_LevenshteinDistance o, collector
538
539
  collector << "LEVENSHTEIN_DISTANCE("
539
540
  collector = visit o.left, collector
540
- collector << Arel::Visitors::ToSql::COMMA
541
+ collector << COMMA
541
542
  collector = visit o.right, collector
542
543
  collector << ')'
543
544
  collector
@@ -545,7 +546,7 @@ module ArelExtensions
545
546
 
546
547
  # Boolean logic.
547
548
 
548
- alias_method :old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And
549
+ alias_method(:old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And) rescue nil
549
550
  def visit_Arel_Nodes_And o, collector
550
551
  case o.children.length
551
552
  when 0
@@ -565,7 +566,7 @@ module ArelExtensions
565
566
  collector
566
567
  end
567
568
 
568
- alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
569
+ alias_method(:old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or) rescue nil
569
570
  def visit_Arel_Nodes_Or o, collector
570
571
  case o.children.length
571
572
  when 0
@@ -585,6 +586,26 @@ module ArelExtensions
585
586
  collector
586
587
  end
587
588
 
589
+ def json_value(o,v)
590
+ case o.type_of_node(v)
591
+ when :string
592
+ Arel.when(v.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + v.replace('\\','\\\\').replace('"','\"') + '"')
593
+ when :date
594
+ s = v.format('%Y-%m-%d')
595
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
596
+ when :datetime
597
+ s = v.format('%Y-%m-%dT%H:%M:%S')
598
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
599
+ when :time
600
+ s = v.format('%H:%M:%S')
601
+ Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
602
+ when :nil
603
+ Arel::Nodes.build_quoted("null")
604
+ else
605
+ ArelExtensions::Nodes::Cast.new([v, :string]).coalesce("null")
606
+ end
607
+ end
608
+
588
609
  def visit_ArelExtensions_Nodes_Json o,collector
589
610
  case o.dict
590
611
  when Array
@@ -593,11 +614,7 @@ module ArelExtensions
593
614
  if i != 0
594
615
  res += ', '
595
616
  end
596
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.return_type == :string)
597
- res = res + '"' + v + '"'
598
- else
599
- res += v
600
- end
617
+ res += json_value(o,v)
601
618
  end
602
619
  res += ']'
603
620
  collector = visit res, collector
@@ -607,12 +624,8 @@ module ArelExtensions
607
624
  if i != 0
608
625
  res += ', '
609
626
  end
610
- res += Arel::Nodes.build_quoted('"')+k + '": '
611
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
612
- res = res + '"' + v + '"'
613
- else
614
- res += v
615
- end
627
+ res += Arel::Nodes.build_quoted('"') + ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("").replace('\\','\\\\').replace('"','\"') + '": '
628
+ res += json_value(o,v)
616
629
  end
617
630
  res += '}'
618
631
  collector = visit res, collector
@@ -633,12 +646,8 @@ module ArelExtensions
633
646
  if i != 0
634
647
  res = res + ', '
635
648
  end
636
- kv = Arel::Nodes.build_quoted('"')+k + '": '
637
- if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
638
- kv = kv + '"' + v + '"'
639
- else
640
- kv += v
641
- end
649
+ kv = Arel::Nodes.build_quoted('"') + ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("").replace('\\','\\\\').replace('"','\"') + '": '
650
+ kv += json_value(o,v)
642
651
  res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
643
652
  end
644
653
  res = res + '}'
@@ -646,7 +655,6 @@ module ArelExtensions
646
655
  end
647
656
  collector
648
657
  end
649
-
650
658
  end
651
659
  end
652
660
  end