arel_extensions 1.2.23 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -7
  3. data/.travis.yml +91 -61
  4. data/Gemfile +20 -15
  5. data/README.md +12 -17
  6. data/Rakefile +29 -40
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +3 -3
  9. data/functions.html +3 -3
  10. data/gemfiles/rails3.gemfile +9 -9
  11. data/gemfiles/rails4.gemfile +13 -13
  12. data/gemfiles/rails5_0.gemfile +13 -13
  13. data/gemfiles/rails5_1_4.gemfile +13 -13
  14. data/gemfiles/rails5_2.gemfile +13 -13
  15. data/init/mssql.sql +4 -4
  16. data/init/mysql.sql +38 -38
  17. data/init/postgresql.sql +21 -21
  18. data/lib/arel_extensions.rb +19 -69
  19. data/lib/arel_extensions/attributes.rb +1 -0
  20. data/lib/arel_extensions/boolean_functions.rb +14 -55
  21. data/lib/arel_extensions/common_sql_functions.rb +8 -7
  22. data/lib/arel_extensions/comparators.rb +15 -14
  23. data/lib/arel_extensions/date_duration.rb +5 -4
  24. data/lib/arel_extensions/insert_manager.rb +16 -17
  25. data/lib/arel_extensions/math.rb +12 -11
  26. data/lib/arel_extensions/math_functions.rb +22 -29
  27. data/lib/arel_extensions/nodes.rb +1 -1
  28. data/lib/arel_extensions/nodes/abs.rb +1 -0
  29. data/lib/arel_extensions/nodes/blank.rb +1 -0
  30. data/lib/arel_extensions/nodes/case.rb +8 -11
  31. data/lib/arel_extensions/nodes/cast.rb +2 -4
  32. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  33. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  34. data/lib/arel_extensions/nodes/coalesce.rb +3 -2
  35. data/lib/arel_extensions/nodes/collate.rb +2 -1
  36. data/lib/arel_extensions/nodes/concat.rb +16 -7
  37. data/lib/arel_extensions/nodes/date_diff.rb +13 -10
  38. data/lib/arel_extensions/nodes/duration.rb +3 -0
  39. data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
  40. data/lib/arel_extensions/nodes/floor.rb +1 -1
  41. data/lib/arel_extensions/nodes/format.rb +8 -34
  42. data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
  43. data/lib/arel_extensions/nodes/function.rb +16 -25
  44. data/lib/arel_extensions/nodes/json.rb +36 -43
  45. data/lib/arel_extensions/nodes/length.rb +1 -0
  46. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  47. data/lib/arel_extensions/nodes/locate.rb +1 -0
  48. data/lib/arel_extensions/nodes/log10.rb +2 -1
  49. data/lib/arel_extensions/nodes/matches.rb +6 -4
  50. data/lib/arel_extensions/nodes/md5.rb +1 -0
  51. data/lib/arel_extensions/nodes/power.rb +5 -5
  52. data/lib/arel_extensions/nodes/rand.rb +1 -0
  53. data/lib/arel_extensions/nodes/repeat.rb +4 -2
  54. data/lib/arel_extensions/nodes/replace.rb +6 -22
  55. data/lib/arel_extensions/nodes/round.rb +6 -5
  56. data/lib/arel_extensions/nodes/soundex.rb +15 -15
  57. data/lib/arel_extensions/nodes/std.rb +21 -18
  58. data/lib/arel_extensions/nodes/substring.rb +16 -8
  59. data/lib/arel_extensions/nodes/then.rb +0 -0
  60. data/lib/arel_extensions/nodes/trim.rb +5 -3
  61. data/lib/arel_extensions/nodes/union.rb +5 -2
  62. data/lib/arel_extensions/nodes/union_all.rb +3 -0
  63. data/lib/arel_extensions/nodes/wday.rb +4 -0
  64. data/lib/arel_extensions/null_functions.rb +7 -5
  65. data/lib/arel_extensions/predications.rb +34 -35
  66. data/lib/arel_extensions/railtie.rb +5 -5
  67. data/lib/arel_extensions/set_functions.rb +4 -2
  68. data/lib/arel_extensions/string_functions.rb +22 -43
  69. data/lib/arel_extensions/tasks.rb +5 -5
  70. data/lib/arel_extensions/version.rb +1 -1
  71. data/lib/arel_extensions/visitors.rb +60 -68
  72. data/lib/arel_extensions/visitors/ibm_db.rb +12 -5
  73. data/lib/arel_extensions/visitors/mssql.rb +57 -63
  74. data/lib/arel_extensions/visitors/mysql.rb +98 -149
  75. data/lib/arel_extensions/visitors/oracle.rb +68 -71
  76. data/lib/arel_extensions/visitors/oracle12.rb +15 -2
  77. data/lib/arel_extensions/visitors/postgresql.rb +63 -116
  78. data/lib/arel_extensions/visitors/sqlite.rb +70 -83
  79. data/lib/arel_extensions/visitors/to_sql.rb +109 -141
  80. data/test/database.yml +0 -2
  81. data/test/helper.rb +18 -0
  82. data/test/real_db_test.rb +43 -28
  83. data/test/support/fake_record.rb +2 -2
  84. data/test/test_comparators.rb +12 -9
  85. data/test/visitors/test_bulk_insert_oracle.rb +8 -8
  86. data/test/visitors/test_bulk_insert_sqlite.rb +10 -9
  87. data/test/visitors/test_bulk_insert_to_sql.rb +10 -8
  88. data/test/visitors/test_oracle.rb +42 -42
  89. data/test/visitors/test_to_sql.rb +196 -361
  90. data/test/with_ar/all_agnostic_test.rb +160 -195
  91. data/test/with_ar/insert_agnostic_test.rb +4 -3
  92. data/test/with_ar/test_bulk_sqlite.rb +9 -6
  93. data/test/with_ar/test_math_sqlite.rb +12 -8
  94. data/test/with_ar/test_string_mysql.rb +11 -5
  95. data/test/with_ar/test_string_sqlite.rb +12 -4
  96. metadata +11 -22
  97. data/.github/workflows/ruby.yml +0 -102
  98. data/gemfiles/rails6.gemfile +0 -30
  99. data/gemfiles/rails6_1.gemfile +0 -30
  100. data/gemspecs/arel_extensions-v1.gemspec +0 -28
  101. data/gemspecs/arel_extensions-v2.gemspec +0 -28
  102. data/generate_gems.sh +0 -15
  103. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
  104. data/lib/arel_extensions/nodes/sum.rb +0 -7
  105. data/lib/arel_extensions/visitors/convert_format.rb +0 -37
  106. data/test/arelx_test_helper.rb +0 -26
  107. data/version_v1.rb +0 -3
  108. data/version_v2.rb +0 -3
@@ -1,23 +1,16 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- class Arel::Visitors::SQLite
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
3
+ Arel::Visitors::SQLite.class_eval do
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
10
6
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
11
7
  '%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
12
8
  '%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
13
9
  '%M' => '%M', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => '' # seconds, subseconds
14
- }.freeze
15
-
16
- NUMBER_COMMA_MAPPING = {
17
- 'fr_FR' => {',' => ' ', '.' =>','}
18
- }.freeze
10
+ }
11
+ Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING = { 'fr_FR' => {',' => ' ','.' =>','} }
19
12
 
20
- # String functions
13
+ #String functions
21
14
  def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
22
15
  collector = visit o.left.ci_collate, collector
23
16
  collector << ' LIKE '
@@ -80,6 +73,7 @@ module ArelExtensions
80
73
  collector
81
74
  end
82
75
 
76
+
83
77
  def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
84
78
  collector = visit o.left.lower, collector
85
79
  collector << ' NOT LIKE '
@@ -96,15 +90,14 @@ module ArelExtensions
96
90
  def visit_ArelExtensions_Nodes_DateAdd o, collector
97
91
  collector << "date("
98
92
  collector = visit o.expressions.first, collector
99
- collector << COMMA
93
+ collector << Arel::Visitors::SQLite::COMMA
100
94
  collector = visit o.sqlite_value, collector
101
95
  collector << ")"
102
96
  collector
103
97
  end
104
98
 
105
99
  def visit_ArelExtensions_Nodes_DateDiff o, collector
106
- case o.left_node_type
107
- when :ruby_time, :datetime, :time
100
+ if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
108
101
  collector << "strftime('%s', "
109
102
  collector = visit o.left, collector
110
103
  collector << ") - strftime('%s', "
@@ -120,16 +113,17 @@ module ArelExtensions
120
113
  end
121
114
 
122
115
  def visit_ArelExtensions_Nodes_Duration o, collector
123
- collector << "strftime('#{DATE_MAPPING[o.left]}'#{COMMA}"
116
+ collector << "strftime('#{Arel::Visitors::SQLite::DATE_MAPPING[o.left]}'#{Arel::Visitors::SQLite::COMMA}"
124
117
  collector = visit o.right, collector
125
118
  collector << ")"
126
119
  collector
127
120
  end
128
121
 
122
+
129
123
  def visit_ArelExtensions_Nodes_Locate o, collector
130
124
  collector << "instr("
131
125
  collector = visit o.expr, collector
132
- collector << COMMA
126
+ collector << Arel::Visitors::SQLite::COMMA
133
127
  collector = visit o.right, collector
134
128
  collector << ")"
135
129
  collector
@@ -148,7 +142,7 @@ module ArelExtensions
148
142
  def visit_ArelExtensions_Nodes_Substring o, collector
149
143
  collector << "SUBSTR("
150
144
  o.expressions.each_with_index { |arg, i|
151
- collector << COMMA if i != 0
145
+ collector << Arel::Visitors::SQLite::COMMA unless i == 0
152
146
  collector = visit arg, collector
153
147
  }
154
148
  collector << ")"
@@ -171,7 +165,7 @@ module ArelExtensions
171
165
  collector << "RANDOM("
172
166
  if o.left != nil && o.right != nil
173
167
  collector = visit o.left, collector
174
- collector << COMMA
168
+ collector << Arel::Visitors::SQLite::COMMA
175
169
  collector = visit o.right, collector
176
170
  end
177
171
  collector << ")"
@@ -199,28 +193,18 @@ module ArelExtensions
199
193
  collector
200
194
  end
201
195
 
202
- # CAST(
203
- # CASE
204
- # WHEN 3.42 >= 0 THEN CAST(3.42 AS INT)
205
- # WHEN CAST(3.42 AS INT) = 3.42 THEN CAST(3.42 AS INT)
206
- # ELSE CAST((3.42 - 1.0) AS INT)
207
- # END
208
- # AS FLOAT
209
- # )
196
+ # CASE WHEN ROUND(3.42,1) > round(3.42) THEN round(3.42) ELSE round(3.42)-1 END
197
+ # OR CAST(3.14 AS INTEGER)
210
198
  def visit_ArelExtensions_Nodes_Floor o, collector
211
- collector << "CAST(CASE WHEN "
212
- collector = visit o.left, collector
213
- collector << " >= 0 THEN CAST("
214
- collector = visit o.left, collector
215
- collector << " AS INT) WHEN CAST("
199
+ collector << "CASE WHEN ROUND("
216
200
  collector = visit o.left, collector
217
- collector << " AS INT) = "
201
+ collector << ", 1) > ROUND("
218
202
  collector = visit o.left, collector
219
- collector << " THEN CAST("
203
+ collector << ") THEN ROUND("
220
204
  collector = visit o.left, collector
221
- collector << " AS INT) ELSE CAST(("
205
+ collector << ") ELSE ROUND("
222
206
  collector = visit o.left, collector
223
- collector << " - 1.0) AS INT) END AS FLOAT)"
207
+ collector << ") - 1 END"
224
208
  collector
225
209
  end
226
210
 
@@ -241,8 +225,9 @@ module ArelExtensions
241
225
  def visit_ArelExtensions_InsertManager_BulkValues o, collector
242
226
  o.left.each_with_index do |row, idx|
243
227
  collector << 'SELECT '
244
- len = row.length - 1
245
- row.zip(o.cols).each_with_index { |(value, attr), i|
228
+ v = Arel::Nodes::Values.new(row, o.cols)
229
+ len = v.expressions.length - 1
230
+ v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
246
231
  case value
247
232
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
248
233
  collector = visit value.as(attr.name), collector
@@ -253,7 +238,7 @@ module ArelExtensions
253
238
  collector << quote(attr.name)
254
239
  end
255
240
  end
256
- collector << COMMA unless i == len
241
+ collector << Arel::Visitors::SQLite::COMMA unless i == len
257
242
  }
258
243
  collector << ' UNION ALL ' unless idx == o.left.length - 1
259
244
  end
@@ -264,24 +249,19 @@ module ArelExtensions
264
249
  o.left.each_with_index do |row, idx|
265
250
  collector << 'SELECT '
266
251
  len = row.length - 1
267
- row.zip(o.cols).each_with_index { |(value, attr), i|
268
- case value
269
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
270
- collector = visit value.as(attr.name), collector
271
- when Integer
272
- collector << value.to_s
273
- if idx == 0
274
- collector << " AS "
275
- collector << quote(attr.name)
276
- end
277
- else
278
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
279
- if idx == 0
280
- collector << " AS "
281
- collector << quote(attr.name)
282
- end
252
+ row.each_with_index { |value, i|
253
+ attr = o.cols[i]
254
+ case value
255
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
256
+ collector = visit value.as(attr.name), collector
257
+ else
258
+ collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
259
+ if idx == 0
260
+ collector << " AS "
261
+ collector << quote(attr.name)
283
262
  end
284
- collector << COMMA unless i == len
263
+ end
264
+ collector << Arel::Visitors::SQLite::COMMA unless i == len
285
265
  }
286
266
  collector << ' UNION ALL ' unless idx == o.left.length - 1
287
267
  end
@@ -290,36 +270,32 @@ module ArelExtensions
290
270
  end
291
271
 
292
272
  def visit_ArelExtensions_Nodes_Union o, collector
293
- collector =
294
- if o.left.is_a?(Arel::SelectManager)
295
- visit o.left.ast, collector
296
- else
297
- visit o.left, collector
298
- end
273
+ if o.left.is_a?(Arel::SelectManager)
274
+ collector = visit o.left.ast, collector
275
+ else
276
+ collector = visit o.left, collector
277
+ end
299
278
  collector << " UNION "
300
- collector =
301
- if o.right.is_a?(Arel::SelectManager)
302
- visit o.right.ast, collector
303
- else
304
- visit o.right, collector
305
- end
279
+ if o.right.is_a?(Arel::SelectManager)
280
+ collector = visit o.right.ast, collector
281
+ else
282
+ collector = visit o.right, collector
283
+ end
306
284
  collector
307
285
  end
308
286
 
309
287
  def visit_ArelExtensions_Nodes_UnionAll o, collector
310
- collector =
311
- if o.left.is_a?(Arel::SelectManager)
312
- visit o.left.ast, collector
313
- else
314
- visit o.left, collector
315
- end
288
+ if o.left.is_a?(Arel::SelectManager)
289
+ collector = visit o.left.ast, collector
290
+ else
291
+ collector = visit o.left, collector
292
+ end
316
293
  collector << " UNION ALL "
317
- collector =
318
- if o.right.is_a?(Arel::SelectManager)
319
- visit o.right.ast, collector
320
- else
321
- visit o.right, collector
322
- end
294
+ if o.right.is_a?(Arel::SelectManager)
295
+ collector = visit o.right.ast, collector
296
+ else
297
+ collector = visit o.right, collector
298
+ end
323
299
  collector
324
300
  end
325
301
 
@@ -370,7 +346,17 @@ module ArelExtensions
370
346
  collector
371
347
  end
372
348
 
373
- alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
349
+
350
+ alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
351
+ def visit_Arel_Nodes_SelectStatement o, collector
352
+ if !collector.value.blank? && o.limit.blank?
353
+ o = o.dup
354
+ o.orders = []
355
+ end
356
+ old_visit_Arel_Nodes_SelectStatement(o,collector)
357
+ end
358
+
359
+ alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
374
360
  def visit_Arel_Nodes_As o, collector
375
361
  if o.left.is_a?(Arel::Nodes::Binary)
376
362
  collector << '('
@@ -387,13 +373,14 @@ module ArelExtensions
387
373
 
388
374
  def visit_ArelExtensions_Nodes_FormattedNumber o, collector
389
375
  format = Arel::Nodes::NamedFunction.new('printf',[Arel::Nodes.build_quoted(o.original_string),o.left])
390
- locale_map = NUMBER_COMMA_MAPPING[o.locale]
376
+ locale_map = Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING[o.locale]
391
377
  if locale_map
392
378
  format = format.replace(',',locale_map[',']).replace('.',locale_map['.'])
393
379
  end
394
380
  visit format, collector
395
381
  collector
396
382
  end
383
+
397
384
  end
398
385
  end
399
386
  end
@@ -1,22 +1,13 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- class Arel::Visitors::ToSql
4
- COMMA = ', ' unless defined?(COMMA)
5
-
6
- # Escape properly the string expression expr.
7
- # Take care of escaping.
8
- def make_json_string expr
9
- Arel::Nodes.build_quoted('"') \
10
- + expr
11
- .replace('\\','\\\\').replace('"','\"').replace("\n", '\n') \
12
- + '"'
13
- end
3
+ Arel::Visitors::ToSql.class_eval do
4
+ Arel::Visitors::ToSql::COMMA = ", "
14
5
 
15
6
  # Math Functions
16
7
  def visit_ArelExtensions_Nodes_Abs o, collector
17
8
  collector << "ABS("
18
9
  o.expressions.each_with_index { |arg, i|
19
- collector << COMMA if i != 0
10
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
20
11
  collector = visit arg, collector
21
12
  }
22
13
  collector << ")"
@@ -26,7 +17,7 @@ module ArelExtensions
26
17
  def visit_ArelExtensions_Nodes_Ceil o, collector
27
18
  collector << "CEIL("
28
19
  o.expressions.each_with_index { |arg, i|
29
- collector << COMMA if i != 0
20
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
30
21
  collector = visit arg, collector
31
22
  }
32
23
  collector << ")"
@@ -36,7 +27,7 @@ module ArelExtensions
36
27
  def visit_ArelExtensions_Nodes_Floor o, collector
37
28
  collector << "FLOOR("
38
29
  o.expressions.each_with_index { |arg, i|
39
- collector << COMMA if i != 0
30
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
40
31
  collector = visit arg, collector
41
32
  }
42
33
  collector << ")"
@@ -46,7 +37,7 @@ module ArelExtensions
46
37
  def visit_ArelExtensions_Nodes_Rand o, collector
47
38
  collector << "RAND("
48
39
  o.expressions.each_with_index { |arg, i|
49
- collector << COMMA if i != 0
40
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
50
41
  collector = visit arg, collector
51
42
  }
52
43
  collector << ")"
@@ -56,43 +47,36 @@ module ArelExtensions
56
47
  def visit_ArelExtensions_Nodes_Round o, collector
57
48
  collector << "ROUND("
58
49
  o.expressions.each_with_index { |arg, i|
59
- collector << COMMA if i != 0
50
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
60
51
  collector = visit arg, collector
61
52
  }
62
53
  collector << ")"
63
54
  collector
64
55
  end
65
-
56
+
66
57
  def visit_ArelExtensions_Nodes_Log10 o, collector
67
58
  collector << "LOG10("
68
59
  collector = visit o.left, collector
69
60
  collector << ")"
70
61
  collector
71
62
  end
72
-
63
+
73
64
  def visit_ArelExtensions_Nodes_Power o, collector
74
65
  collector << "POW("
75
66
  o.expressions.each_with_index { |arg, i|
76
- collector << COMMA if i != 0
67
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
77
68
  collector = visit arg, collector
78
69
  }
79
70
  collector << ")"
80
71
  collector
81
72
  end
82
73
 
83
- def visit_ArelExtensions_Nodes_Sum o, collector
84
- collector << "SUM("
85
- collector = visit o.expr, collector
86
- collector << ")"
87
- collector
88
- end
89
-
90
74
  # String functions
91
75
  def visit_ArelExtensions_Nodes_Concat o, collector
92
76
  collector << "CONCAT("
93
- o.expressions.each_with_index { |arg, i|
94
- collector << COMMA if i != 0
95
- collector = visit arg, collector
77
+ o.expressions.each_with_index { |arg, i|
78
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
79
+ collector = visit arg, collector
96
80
  }
97
81
  collector << ")"
98
82
  collector
@@ -101,9 +85,9 @@ module ArelExtensions
101
85
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
102
86
  collector << "GROUP_CONCAT("
103
87
  collector = visit o.left, collector
104
- if o.separator && o.separator != 'NULL'
105
- collector << COMMA
106
- collector = visit o.separator, collector
88
+ if o.right && o.right != 'NULL'
89
+ collector << Arel::Visitors::ToSql::COMMA
90
+ collector = visit o.right, collector
107
91
  end
108
92
  collector << ")"
109
93
  collector
@@ -126,7 +110,7 @@ module ArelExtensions
126
110
  def visit_ArelExtensions_Nodes_Locate o, collector
127
111
  collector << "LOCATE("
128
112
  collector = visit o.right, collector
129
- collector << COMMA
113
+ collector << Arel::Visitors::ToSql::COMMA
130
114
  collector = visit o.left, collector
131
115
  collector << ")"
132
116
  collector
@@ -135,7 +119,7 @@ module ArelExtensions
135
119
  def visit_ArelExtensions_Nodes_Substring o, collector
136
120
  collector << "SUBSTRING("
137
121
  o.expressions.each_with_index { |arg, i|
138
- collector << COMMA if i != 0
122
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
139
123
  collector = visit arg, collector
140
124
  }
141
125
  collector << ")"
@@ -144,30 +128,18 @@ module ArelExtensions
144
128
 
145
129
  def visit_ArelExtensions_Nodes_Replace o, collector
146
130
  collector << "REPLACE("
147
- visit o.left, collector
148
- collector << COMMA
149
- visit o.pattern, collector
150
- collector << COMMA
151
- visit o.substitute, collector
152
- collector << ")"
153
- collector
154
- end
155
-
156
- def visit_ArelExtensions_Nodes_RegexpReplace o, collector
157
- collector << "REGEXP_REPLACE("
158
- visit o.left, collector
159
- collector << COMMA
160
- visit Arel::Nodes.build_quoted(o.pattern.to_s), collector
161
- collector << COMMA
162
- visit o.substitute, collector
131
+ o.expressions.each_with_index { |arg, i|
132
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
133
+ collector = visit arg, collector
134
+ }
163
135
  collector << ")"
164
136
  collector
165
137
  end
166
-
138
+
167
139
  def visit_ArelExtensions_Nodes_Repeat o, collector
168
140
  collector << "REPEAT("
169
141
  o.expressions.each_with_index { |arg, i|
170
- collector << COMMA if i != 0
142
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
171
143
  collector = visit arg, collector
172
144
  }
173
145
  collector << ")"
@@ -177,7 +149,7 @@ module ArelExtensions
177
149
  def visit_ArelExtensions_Nodes_FindInSet o, collector
178
150
  collector << "FIND_IN_SET("
179
151
  o.expressions.each_with_index { |arg, i|
180
- collector << COMMA if i != 0
152
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
181
153
  collector = visit arg, collector
182
154
  }
183
155
  collector << ")"
@@ -187,7 +159,7 @@ module ArelExtensions
187
159
  def visit_ArelExtensions_Nodes_Soundex o, collector
188
160
  collector << "SOUNDEX("
189
161
  o.expressions.each_with_index { |arg, i|
190
- collector << COMMA if i != 0
162
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
191
163
  collector = visit arg, collector
192
164
  }
193
165
  collector << ")"
@@ -197,7 +169,7 @@ module ArelExtensions
197
169
  def visit_ArelExtensions_Nodes_Downcase o, collector
198
170
  collector << "LOWER("
199
171
  o.expressions.each_with_index { |arg, i|
200
- collector << COMMA if i != 0
172
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
201
173
  collector = visit arg, collector
202
174
  }
203
175
  collector << ")"
@@ -207,7 +179,7 @@ module ArelExtensions
207
179
  def visit_ArelExtensions_Nodes_Upcase o, collector
208
180
  collector << "UPPER("
209
181
  o.expressions.each_with_index { |arg, i|
210
- collector << COMMA if i != 0
182
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
211
183
  collector = visit arg, collector
212
184
  }
213
185
  collector << ")"
@@ -217,7 +189,7 @@ module ArelExtensions
217
189
  def visit_ArelExtensions_Nodes_Trim o, collector
218
190
  collector << "TRIM("
219
191
  o.expressions.each_with_index { |arg, i|
220
- collector << COMMA if i != 0
192
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
221
193
  collector = visit arg, collector
222
194
  }
223
195
  collector << ")"
@@ -227,7 +199,7 @@ module ArelExtensions
227
199
  def visit_ArelExtensions_Nodes_Ltrim o, collector
228
200
  collector << "LTRIM("
229
201
  o.expressions.each_with_index { |arg, i|
230
- collector << COMMA if i != 0
202
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
231
203
  collector = visit arg, collector
232
204
  }
233
205
  collector << ")"
@@ -237,7 +209,7 @@ module ArelExtensions
237
209
  def visit_ArelExtensions_Nodes_Rtrim o, collector
238
210
  collector << "RTRIM("
239
211
  o.expressions.each_with_index { |arg, i|
240
- collector << COMMA if i != 0
212
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
241
213
  collector = visit arg, collector
242
214
  }
243
215
  collector << ")"
@@ -245,20 +217,21 @@ module ArelExtensions
245
217
  end
246
218
 
247
219
  def visit_ArelExtensions_Nodes_Blank o, collector
248
- # visit o.left.coalesce('').trim.length.eq(0), collector
220
+ #visit o.left.coalesce('').trim.length.eq(0), collector
249
221
  collector << 'LENGTH(TRIM(COALESCE('
250
222
  collector = visit o.expr, collector
251
- collector << COMMA
223
+ collector << Arel::Visitors::ToSql::COMMA
252
224
  collector = visit Arel::Nodes.build_quoted(''), collector
253
225
  collector << "))) = 0"
254
226
  collector
255
227
  end
256
228
 
229
+
257
230
  def visit_ArelExtensions_Nodes_NotBlank o, collector
258
- # visit o.left.coalesce('').trim.length.gt(0), collector
231
+ #visit o.left.coalesce('').trim.length.gt(0), collector
259
232
  collector << 'LENGTH(TRIM(COALESCE('
260
233
  collector = visit o.expr, collector
261
- collector << COMMA
234
+ collector << Arel::Visitors::ToSql::COMMA
262
235
  collector = visit Arel::Nodes.build_quoted(''), collector
263
236
  collector << "))) > 0"
264
237
  collector
@@ -269,13 +242,13 @@ module ArelExtensions
269
242
  when :date, :datetime, :time
270
243
  collector << "STRFTIME("
271
244
  collector = visit o.right, collector
272
- collector << COMMA
245
+ collector << Arel::Visitors::ToSql::COMMA
273
246
  collector = visit o.left, collector
274
247
  collector << ")"
275
248
  when :integer, :float, :decimal
276
249
  collector << "FORMAT("
277
250
  collector = visit o.left, collector
278
- collector << COMMA
251
+ collector << Arel::Visitors::ToSql::COMMA
279
252
  collector = visit o.right, collector
280
253
  collector << ")"
281
254
  else
@@ -284,7 +257,7 @@ module ArelExtensions
284
257
  collector
285
258
  end
286
259
 
287
- # comparators
260
+ #comparators
288
261
 
289
262
  def visit_ArelExtensions_Nodes_Cast o, collector
290
263
  collector << "CAST("
@@ -297,14 +270,12 @@ module ArelExtensions
297
270
  as_attr = Arel::Nodes::SqlLiteral.new('int')
298
271
  when :decimal, :float, :number
299
272
  as_attr = Arel::Nodes::SqlLiteral.new('float')
300
- when :datetime
273
+ when :datetime
301
274
  as_attr = Arel::Nodes::SqlLiteral.new('datetime')
302
275
  when :time
303
276
  as_attr = Arel::Nodes::SqlLiteral.new('time')
304
- when :binary
305
- as_attr = Arel::Nodes::SqlLiteral.new('binary')
306
- when :text, :ntext
307
- as_attr = Arel::Nodes::SqlLiteral.new('text')
277
+ when :binary
278
+ as_attr = Arel::Nodes::SqlLiteral.new('binary')
308
279
  else
309
280
  as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
310
281
  end
@@ -316,7 +287,7 @@ module ArelExtensions
316
287
  def visit_ArelExtensions_Nodes_Coalesce o, collector
317
288
  collector << "COALESCE("
318
289
  o.expressions.each_with_index { |arg, i|
319
- collector << COMMA if i != 0
290
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
320
291
  collector = visit arg, collector
321
292
  }
322
293
  collector << ")"
@@ -330,27 +301,24 @@ module ArelExtensions
330
301
  'DATEDIFF('
331
302
  end
332
303
  collector = visit o.left, collector
333
- collector << COMMA
304
+ collector << Arel::Visitors::ToSql::COMMA
334
305
  collector = visit o.right, collector
335
306
  collector << ")"
336
307
  collector
337
308
  end
338
-
309
+
339
310
  def visit_ArelExtensions_Nodes_DateSub o, collector
340
311
  collector << "DATE_SUB("
341
312
  collector = visit o.left, collector
342
- collector << COMMA
313
+ collector << Arel::Visitors::ToSql::COMMA
343
314
  collector = visit o.right, collector
344
315
  collector << ")"
345
316
  collector
346
317
  end
347
318
 
348
- # override
319
+ # override
349
320
  remove_method(:visit_Arel_Nodes_As) rescue nil # if Arel::Visitors::ToSql.method_defined?(:visit_Arel_Nodes_As)
350
321
  def visit_Arel_Nodes_As o, collector
351
- if o.left.respond_to?(:alias)
352
- o.left.alias = nil
353
- end
354
322
  if o.left.is_a?(Arel::Nodes::Binary)
355
323
  collector << '('
356
324
  collector = visit o.left, collector
@@ -417,7 +385,7 @@ module ArelExtensions
417
385
  collector = visit o.left, collector
418
386
  collector << ") THEN "
419
387
  collector = visit o.right, collector
420
- if o.expressions[2]
388
+ if o.expressions[2]
421
389
  collector << " ELSE "
422
390
  collector = visit o.expressions[2], collector
423
391
  end
@@ -429,7 +397,7 @@ module ArelExtensions
429
397
  def visit_ArelExtensions_Nodes_DateAdd o, collector
430
398
  collector << "DATE_ADD("
431
399
  collector = visit o.left, collector
432
- collector << COMMA
400
+ collector << Arel::Visitors::ToSql::COMMA
433
401
  collector = visit o.sqlite_value(o.right), collector
434
402
  collector << ')'
435
403
  collector
@@ -441,15 +409,16 @@ module ArelExtensions
441
409
  row_nb = o.left.length
442
410
  o.left.each_with_index do |row, idx|
443
411
  collector << '('
444
- len = row.length - 1
445
- row.zip(o.cols).each_with_index { |(value, attr), i|
446
- case value
447
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
448
- collector = visit value, collector
449
- else
450
- collector << quote(value, attr && column_for(attr)).to_s
451
- end
452
- collector << COMMA unless i == len
412
+ v = Arel::Nodes::Values.new(row, o.cols)
413
+ len = v.expressions.length - 1
414
+ v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
415
+ case value
416
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
417
+ collector = visit value, collector
418
+ else
419
+ collector << quote(value, attr && column_for(attr)).to_s
420
+ end
421
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
453
422
  }
454
423
  collector << (idx == row_nb-1 ? ')' : '), ')
455
424
  end
@@ -462,16 +431,15 @@ module ArelExtensions
462
431
  o.left.each_with_index do |row, idx|
463
432
  collector << '('
464
433
  len = row.length - 1
465
- row.zip(o.cols).each_with_index { |(value, attr), i|
466
- case value
467
- when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
468
- collector = visit value, collector
469
- when Integer
470
- collector << value.to_s
471
- else
472
- collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
473
- end
474
- collector << COMMA unless i == len
434
+ row.each_with_index { |value, i|
435
+ attr = o.cols[i]
436
+ case value
437
+ when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
438
+ collector = visit value, collector
439
+ else
440
+ collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
441
+ end
442
+ collector << Arel::Visitors::ToSql::COMMA unless i == len
475
443
  }
476
444
  collector << (idx == row_nb-1 ? ')' : '), ')
477
445
  end
@@ -485,7 +453,7 @@ module ArelExtensions
485
453
  collector = visit o.right, collector
486
454
  collector
487
455
  end
488
-
456
+
489
457
  def visit_ArelExtensions_Nodes_UnionAll o, collector
490
458
  collector = visit o.left, collector
491
459
  collector << " UNION ALL "
@@ -522,25 +490,25 @@ module ArelExtensions
522
490
  visit Arel::Nodes.build_quoted(o.expr), collector
523
491
  end
524
492
 
525
- def visit_ArelExtensions_Nodes_FormattedNumber o, collector
493
+ def visit_ArelExtensions_Nodes_FormattedNumber o, collector
526
494
  visit o.left, collector
527
495
  end
528
-
529
- remove_method(:visit_Arel_Nodes_LessThan) rescue nil
496
+
497
+ remove_method(:visit_Arel_Nodes_LessThan) rescue nil
530
498
  def visit_Arel_Nodes_LessThan o, collector
531
499
  collector = visit o.left, collector
532
500
  collector << " < "
533
501
  visit o.right, collector
534
502
  end
535
-
536
- def visit_ArelExtensions_Nodes_Std o, collector
503
+
504
+ def visit_ArelExtensions_Nodes_Std o, collector
537
505
  collector << "STD("
538
506
  visit o.left, collector
539
507
  collector << ")"
540
508
  collector
541
509
  end
542
-
543
- def visit_ArelExtensions_Nodes_Variance o, collector
510
+
511
+ def visit_ArelExtensions_Nodes_Variance o, collector
544
512
  collector << "VARIANCE("
545
513
  visit o.left, collector
546
514
  collector << ")"
@@ -550,19 +518,17 @@ module ArelExtensions
550
518
  def visit_ArelExtensions_Nodes_LevenshteinDistance o, collector
551
519
  collector << "LEVENSHTEIN_DISTANCE("
552
520
  collector = visit o.left, collector
553
- collector << COMMA
521
+ collector << Arel::Visitors::ToSql::COMMA
554
522
  collector = visit o.right, collector
555
523
  collector << ')'
556
524
  collector
557
525
  end
558
526
 
559
- # Boolean logic.
560
-
561
- alias_method(:old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And) rescue nil
527
+ alias_method :old_visit_Arel_Nodes_And, :visit_Arel_Nodes_And
562
528
  def visit_Arel_Nodes_And o, collector
563
529
  case o.children.length
564
530
  when 0
565
- collector << '1 = 1' # but this should not happen
531
+ collector << '1=1' # but this should not happen
566
532
  when 1
567
533
  collector = visit o.children[0], collector
568
534
  else
@@ -578,11 +544,10 @@ module ArelExtensions
578
544
  collector
579
545
  end
580
546
 
581
- alias_method(:old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or) rescue nil
582
- def visit_Arel_Nodes_Or o, collector
547
+ def visit_ArelExtensions_Nodes_Or o, collector
583
548
  case o.children.length
584
549
  when 0
585
- collector << '1 = 0' # but this should not happen
550
+ collector << '0=1' # but this should not happen
586
551
  when 1
587
552
  collector = visit o.children[0], collector
588
553
  else
@@ -598,24 +563,14 @@ module ArelExtensions
598
563
  collector
599
564
  end
600
565
 
601
- def json_value(o,v)
602
- case o.type_of_node(v)
603
- when :string
604
- Arel.when(v.is_null).then(Arel::Nodes.build_quoted("null")).else(make_json_string(v))
605
- when :date
606
- s = v.format('%Y-%m-%d')
607
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
608
- when :datetime
609
- s = v.format('%Y-%m-%dT%H:%M:%S')
610
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
611
- when :time
612
- s = v.format('%H:%M:%S')
613
- Arel.when(s.is_null).then(Arel::Nodes.build_quoted("null")).else(Arel::Nodes.build_quoted('"') + s + '"')
614
- when :nil
615
- Arel::Nodes.build_quoted("null")
616
- else
617
- ArelExtensions::Nodes::Cast.new([v, :string]).coalesce("null")
618
- end
566
+ alias_method :old_visit_Arel_Nodes_Or, :visit_Arel_Nodes_Or
567
+ def visit_Arel_Nodes_Or o, collector
568
+ collector << '('
569
+ collector = visit o.left, collector
570
+ collector << ') OR ('
571
+ collector = visit o.right, collector
572
+ collector << ')'
573
+ collector
619
574
  end
620
575
 
621
576
  def visit_ArelExtensions_Nodes_Json o,collector
@@ -626,7 +581,11 @@ module ArelExtensions
626
581
  if i != 0
627
582
  res += ', '
628
583
  end
629
- res += json_value(o,v)
584
+ if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.return_type == :string)
585
+ res = res + '"' + v + '"'
586
+ else
587
+ res += v
588
+ end
630
589
  end
631
590
  res += ']'
632
591
  collector = visit res, collector
@@ -636,8 +595,12 @@ module ArelExtensions
636
595
  if i != 0
637
596
  res += ', '
638
597
  end
639
- res += make_json_string(ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("")) + ': '
640
- res += json_value(o,v)
598
+ res += Arel::Nodes.build_quoted('"')+k + '": '
599
+ if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
600
+ res = res + '"' + v + '"'
601
+ else
602
+ res += v
603
+ end
641
604
  end
642
605
  res += '}'
643
606
  collector = visit res, collector
@@ -649,7 +612,7 @@ module ArelExtensions
649
612
 
650
613
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
651
614
  if o.as_array
652
- res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ', order: Array(o.orders)) : o.dict.group_concat(', ')).coalesce('') + ']'
615
+ res = Arel::Nodes.build_quoted('[') + (o.orders ? o.dict.group_concat(', ',o.orders) : o.dict.group_concat(', ')) + ']'
653
616
  collector = visit res, collector
654
617
  else
655
618
  res = Arel::Nodes.build_quoted('{')
@@ -658,15 +621,20 @@ module ArelExtensions
658
621
  if i != 0
659
622
  res = res + ', '
660
623
  end
661
- kv = make_json_string(ArelExtensions::Nodes::Cast.new([k, :string]).coalesce("")) + ': '
662
- kv += json_value(o,v)
663
- res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
624
+ kv = Arel::Nodes.build_quoted('"')+k + '": '
625
+ if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
626
+ kv = kv + '"' + v + '"'
627
+ else
628
+ kv += v
629
+ end
630
+ res = res + kv.group_concat(', ',orders)
664
631
  end
665
632
  res = res + '}'
666
633
  collector = visit res, collector
667
634
  end
668
635
  collector
669
636
  end
637
+
670
638
  end
671
639
  end
672
640
  end