arel_extensions 2.4.0 → 2.5.0

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +131 -5
  4. data/Makefile +31 -1
  5. data/NEWS.md +15 -0
  6. data/README.md +11 -2
  7. data/Rakefile +5 -3
  8. data/arel_extensions.gemspec +3 -5
  9. data/gemfiles/rails5.gemfile +15 -8
  10. data/gemfiles/rails5_1_4.gemfile +11 -9
  11. data/gemfiles/rails5_2.gemfile +16 -9
  12. data/gemfiles/rails6.gemfile +13 -7
  13. data/gemfiles/rails6_1.gemfile +13 -7
  14. data/gemfiles/rails7.gemfile +15 -9
  15. data/gemfiles/rails7_1.gemfile +15 -8
  16. data/gemfiles/rails7_2.gemfile +12 -6
  17. data/gemfiles/rails8.gemfile +7 -7
  18. data/gemfiles/rails8_1.gemfile +4 -4
  19. data/gemspecs/arel_extensions-v1.gemspec +3 -5
  20. data/gemspecs/arel_extensions-v2.gemspec +3 -5
  21. data/lib/arel_extensions/aliases.rb +3 -3
  22. data/lib/arel_extensions/attributes.rb +2 -0
  23. data/lib/arel_extensions/boolean_functions.rb +9 -7
  24. data/lib/arel_extensions/common_sql_functions.rb +5 -3
  25. data/lib/arel_extensions/comparators.rb +6 -4
  26. data/lib/arel_extensions/date_duration.rb +2 -0
  27. data/lib/arel_extensions/helpers.rb +17 -17
  28. data/lib/arel_extensions/insert_manager.rb +5 -1
  29. data/lib/arel_extensions/math.rb +40 -44
  30. data/lib/arel_extensions/math_functions.rb +28 -30
  31. data/lib/arel_extensions/nodes/aggregate_function.rb +4 -4
  32. data/lib/arel_extensions/nodes/blank.rb +6 -4
  33. data/lib/arel_extensions/nodes/case.rb +15 -12
  34. data/lib/arel_extensions/nodes/cast.rb +3 -5
  35. data/lib/arel_extensions/nodes/coalesce.rb +1 -1
  36. data/lib/arel_extensions/nodes/collate.rb +1 -1
  37. data/lib/arel_extensions/nodes/concat.rb +6 -6
  38. data/lib/arel_extensions/nodes/date_diff.rb +40 -49
  39. data/lib/arel_extensions/nodes/duration.rb +2 -2
  40. data/lib/arel_extensions/nodes/format.rb +2 -2
  41. data/lib/arel_extensions/nodes/formatted_date.rb +2 -2
  42. data/lib/arel_extensions/nodes/formatted_number.rb +2 -2
  43. data/lib/arel_extensions/nodes/function.rb +6 -4
  44. data/lib/arel_extensions/nodes/is_null.rb +2 -0
  45. data/lib/arel_extensions/nodes/json.rb +27 -15
  46. data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
  47. data/lib/arel_extensions/nodes/locate.rb +1 -1
  48. data/lib/arel_extensions/nodes/power.rb +2 -2
  49. data/lib/arel_extensions/nodes/rand.rb +2 -2
  50. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  51. data/lib/arel_extensions/nodes/replace.rb +3 -3
  52. data/lib/arel_extensions/nodes/rollup.rb +4 -4
  53. data/lib/arel_extensions/nodes/round.rb +3 -3
  54. data/lib/arel_extensions/nodes/select.rb +1 -1
  55. data/lib/arel_extensions/nodes/std.rb +4 -4
  56. data/lib/arel_extensions/nodes/substring.rb +52 -2
  57. data/lib/arel_extensions/nodes/then.rb +1 -1
  58. data/lib/arel_extensions/nodes/trim.rb +2 -2
  59. data/lib/arel_extensions/nodes/union.rb +3 -3
  60. data/lib/arel_extensions/nodes/union_all.rb +3 -3
  61. data/lib/arel_extensions/nodes/wday.rb +2 -2
  62. data/lib/arel_extensions/null_functions.rb +5 -7
  63. data/lib/arel_extensions/predications.rb +22 -18
  64. data/lib/arel_extensions/string_functions.rb +26 -27
  65. data/lib/arel_extensions/version.rb +3 -1
  66. data/lib/arel_extensions/visitors/convert_format.rb +2 -2
  67. data/lib/arel_extensions/visitors/ibm_db.rb +5 -5
  68. data/lib/arel_extensions/visitors/mssql.rb +91 -92
  69. data/lib/arel_extensions/visitors/mysql.rb +89 -69
  70. data/lib/arel_extensions/visitors/oracle.rb +100 -104
  71. data/lib/arel_extensions/visitors/oracle12.rb +5 -6
  72. data/lib/arel_extensions/visitors/postgresql.rb +107 -94
  73. data/lib/arel_extensions/visitors/sqlite.rb +57 -65
  74. data/lib/arel_extensions/visitors/to_sql.rb +84 -74
  75. data/lib/arel_extensions/visitors.rb +6 -6
  76. data/lib/arel_extensions/warning.rb +5 -5
  77. data/lib/arel_extensions.rb +34 -27
  78. data/test/real_db_test.rb +31 -31
  79. data/test/visitors/test_to_sql.rb +2 -2
  80. data/test/with_ar/all_agnostic_test.rb +149 -15
  81. data/version_v1.rb +3 -1
  82. data/version_v2.rb +3 -1
  83. metadata +2 -30
@@ -25,7 +25,7 @@ module ArelExtensions
25
25
  end
26
26
 
27
27
  if private_method_defined?(:visit_Arel_Nodes_SelectCore) || method_defined?(:visit_Arel_Nodes_SelectCore)
28
- alias_method(:old_visit_Arel_Nodes_SelectCore, :visit_Arel_Nodes_SelectCore)
28
+ alias old_visit_Arel_Nodes_SelectCore visit_Arel_Nodes_SelectCore
29
29
  end
30
30
  # The whole purpose of this override is to fix the behavior of RollUp.
31
31
  # All other databases treat RollUp sanely, execpt MySQL which requires
@@ -33,7 +33,7 @@ module ArelExtensions
33
33
  def visit_Arel_Nodes_SelectCore(o, collector)
34
34
  collector << 'SELECT'
35
35
 
36
- collector = collect_optimizer_hints(o, collector) if self.respond_to?(:collect_optimizer_hinsts)
36
+ collector = collect_optimizer_hints(o, collector) if respond_to?(:collect_optimizer_hints, true)
37
37
  collector = maybe_visit o.set_quantifier, collector
38
38
 
39
39
  collect_nodes_for o.projections, collector, ' '
@@ -65,20 +65,20 @@ module ArelExtensions
65
65
  end
66
66
 
67
67
  # Math functions
68
- def visit_ArelExtensions_Nodes_Log10 o, collector
68
+ def visit_ArelExtensions_Nodes_Log10(o, collector)
69
69
  collector << 'LOG10('
70
70
  o.expressions.each_with_index { |arg, i|
71
- collector << Arel::Visitors::ToSql::COMMA if i != 0
71
+ collector << COMMA if i != 0
72
72
  collector = visit arg, collector
73
73
  }
74
74
  collector << ')'
75
75
  collector
76
76
  end
77
77
 
78
- def visit_ArelExtensions_Nodes_Power o, collector
78
+ def visit_ArelExtensions_Nodes_Power(o, collector)
79
79
  collector << 'POW('
80
80
  o.expressions.each_with_index { |arg, i|
81
- collector << Arel::Visitors::ToSql::COMMA if i != 0
81
+ collector << COMMA if i != 0
82
82
  collector = visit arg, collector
83
83
  }
84
84
  collector << ')'
@@ -86,21 +86,21 @@ module ArelExtensions
86
86
  end
87
87
 
88
88
  # String functions
89
- def visit_ArelExtensions_Nodes_ByteSize o, collector
89
+ def visit_ArelExtensions_Nodes_ByteSize(o, collector)
90
90
  collector << 'LENGTH('
91
91
  collector = visit o.expr.coalesce(''), collector
92
92
  collector << ')'
93
93
  collector
94
94
  end
95
95
 
96
- def visit_ArelExtensions_Nodes_CharLength o, collector
96
+ def visit_ArelExtensions_Nodes_CharLength(o, collector)
97
97
  collector << 'CHAR_LENGTH('
98
98
  collector = visit o.expr.coalesce(''), collector
99
99
  collector << ')'
100
100
  collector
101
101
  end
102
102
 
103
- def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
103
+ def visit_ArelExtensions_Nodes_IMatches(o, collector) # insensitive on ASCII
104
104
  collector << 'LOWER('
105
105
  collector = visit o.left, collector
106
106
  collector << ') LIKE LOWER('
@@ -113,7 +113,7 @@ module ArelExtensions
113
113
  collector
114
114
  end
115
115
 
116
- def visit_ArelExtensions_Nodes_AiMatches o, collector
116
+ def visit_ArelExtensions_Nodes_AiMatches(o, collector)
117
117
  collector = visit o.left.ai_collate, collector
118
118
  collector << ' LIKE '
119
119
  collector = visit o.right.ai_collate, collector
@@ -124,7 +124,7 @@ module ArelExtensions
124
124
  collector
125
125
  end
126
126
 
127
- def visit_ArelExtensions_Nodes_AiIMatches o, collector
127
+ def visit_ArelExtensions_Nodes_AiIMatches(o, collector)
128
128
  collector = visit o.left.ai_collate, collector
129
129
  collector << ' LIKE '
130
130
  collector = visit o.right.ai_collate, collector
@@ -135,7 +135,7 @@ module ArelExtensions
135
135
  collector
136
136
  end
137
137
 
138
- def visit_ArelExtensions_Nodes_SMatches o, collector
138
+ def visit_ArelExtensions_Nodes_SMatches(o, collector)
139
139
  collector = visit o.left.collate, collector
140
140
  collector << ' LIKE '
141
141
  collector = visit o.right.collate, collector
@@ -146,7 +146,7 @@ module ArelExtensions
146
146
  collector
147
147
  end
148
148
 
149
- def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
149
+ def visit_ArelExtensions_Nodes_IDoesNotMatch(o, collector)
150
150
  collector << 'LOWER('
151
151
  collector = visit o.left, collector
152
152
  collector << ') NOT LIKE LOWER('
@@ -159,7 +159,7 @@ module ArelExtensions
159
159
  collector
160
160
  end
161
161
 
162
- def visit_ArelExtensions_Nodes_Collate o, collector
162
+ def visit_ArelExtensions_Nodes_Collate(o, collector)
163
163
  charset =
164
164
  case o.expressions.first
165
165
  when Arel::Attributes::Attribute
@@ -170,7 +170,7 @@ module ArelExtensions
170
170
  Arel::Table.engine.connection.charset || 'utf8'
171
171
  end
172
172
  else
173
- (o.option == 'latin1') ? 'latin1' : 'utf8'
173
+ o.option == 'latin1' ? 'latin1' : 'utf8'
174
174
  end
175
175
  collector = visit o.expressions.first, collector
176
176
  collector <<
@@ -185,7 +185,7 @@ module ArelExtensions
185
185
  collector
186
186
  end
187
187
 
188
- def visit_ArelExtensions_Nodes_Concat o, collector
188
+ def visit_ArelExtensions_Nodes_Concat(o, collector)
189
189
  collector << 'CONCAT('
190
190
  o.expressions.each_with_index { |arg, i|
191
191
  collector << COMMA if i != 0
@@ -203,16 +203,16 @@ module ArelExtensions
203
203
 
204
204
  def visit_Arel_Nodes_RollUp(o, collector)
205
205
  visit o.expr, collector
206
- collector << " WITH ROLLUP"
206
+ collector << ' WITH ROLLUP'
207
207
  end
208
208
 
209
- def visit_ArelExtensions_Nodes_GroupConcat o, collector
209
+ def visit_ArelExtensions_Nodes_GroupConcat(o, collector)
210
210
  collector << 'GROUP_CONCAT('
211
211
  collector = visit o.left, collector
212
212
  if !o.order.blank?
213
213
  collector << ' ORDER BY '
214
214
  o.order.each_with_index do |order, i|
215
- collector << Arel::Visitors::ToSql::COMMA if i != 0
215
+ collector << COMMA if i != 0
216
216
  collector = visit order, collector
217
217
  end
218
218
  end
@@ -225,7 +225,7 @@ module ArelExtensions
225
225
  collector
226
226
  end
227
227
 
228
- def visit_ArelExtensions_Nodes_Trim o, collector
228
+ def visit_ArelExtensions_Nodes_Trim(o, collector)
229
229
  collector << 'TRIM(' # BOTH
230
230
  collector = visit o.right, collector
231
231
  collector << ' FROM '
@@ -234,7 +234,7 @@ module ArelExtensions
234
234
  collector
235
235
  end
236
236
 
237
- def visit_ArelExtensions_Nodes_Ltrim o, collector
237
+ def visit_ArelExtensions_Nodes_Ltrim(o, collector)
238
238
  collector << 'TRIM(LEADING '
239
239
  collector = visit o.right, collector
240
240
  collector << ' FROM '
@@ -243,7 +243,7 @@ module ArelExtensions
243
243
  collector
244
244
  end
245
245
 
246
- def visit_ArelExtensions_Nodes_Rtrim o, collector
246
+ def visit_ArelExtensions_Nodes_Rtrim(o, collector)
247
247
  collector << 'TRIM(TRAILING '
248
248
  collector = visit o.right, collector
249
249
  collector << ' FROM '
@@ -252,24 +252,24 @@ module ArelExtensions
252
252
  collector
253
253
  end
254
254
 
255
- def visit_ArelExtensions_Nodes_Repeat o, collector
255
+ def visit_ArelExtensions_Nodes_Repeat(o, collector)
256
256
  collector << 'REPEAT('
257
257
  o.expressions.each_with_index { |arg, i|
258
- collector << Arel::Visitors::ToSql::COMMA if i != 0
258
+ collector << COMMA if i != 0
259
259
  collector = visit arg, collector
260
260
  }
261
261
  collector << ')'
262
262
  collector
263
263
  end
264
264
 
265
- def visit_ArelExtensions_Nodes_RegexpReplace o, collector
265
+ def visit_ArelExtensions_Nodes_RegexpReplace(o, collector)
266
266
  if !regexp_replace_supported?
267
267
  warn('Warning: ArelExtensions: REGEXP_REPLACE does not seem to be available in the current version of the DBMS, it might crash')
268
268
  end
269
- super(o, collector)
269
+ super
270
270
  end
271
271
 
272
- def visit_ArelExtensions_Nodes_Format o, collector
272
+ def visit_ArelExtensions_Nodes_Format(o, collector)
273
273
  # One use case we met is
274
274
  # `case…when…then(valid_date).else(Arel.null).format(…)`.
275
275
  #
@@ -278,10 +278,12 @@ module ArelExtensions
278
278
  # infer the proper type.
279
279
  first = o.expressions[0]
280
280
  type =
281
- o.col_type.nil? \
282
- && (first.respond_to?(:return_type) && !first&.return_type.nil?) \
283
- ? first&.return_type \
284
- : o.col_type
281
+ if o.col_type.nil? \
282
+ && first.respond_to?(:return_type) && !first&.return_type.nil?
283
+ first&.return_type
284
+ else
285
+ o.col_type
286
+ end
285
287
 
286
288
  case type
287
289
  when :date, :datetime, :time
@@ -289,9 +291,9 @@ module ArelExtensions
289
291
  when :integer, :float, :decimal
290
292
  collector << 'FORMAT('
291
293
  collector = visit o.left, collector
292
- collector << Arel::Visitors::ToSql::COMMA
294
+ collector << COMMA
293
295
  collector << '2'
294
- collector << Arel::Visitors::ToSql::COMMA
296
+ collector << COMMA
295
297
  collector = visit o.right, collector
296
298
  collector << ')'
297
299
  else
@@ -300,8 +302,8 @@ module ArelExtensions
300
302
  collector
301
303
  end
302
304
 
303
- def visit_ArelExtensions_Nodes_FormattedDate o, collector
304
- fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
305
+ def visit_ArelExtensions_Nodes_FormattedDate(o, collector)
306
+ fmt = ArelExtensions::Visitors.strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
305
307
  collector << 'DATE_FORMAT('
306
308
  collector << 'CONVERT_TZ(' if o.time_zone
307
309
  collector = visit o.left, collector
@@ -323,7 +325,7 @@ module ArelExtensions
323
325
  collector << ')'
324
326
  end
325
327
 
326
- def visit_ArelExtensions_Nodes_DateDiff o, collector
328
+ def visit_ArelExtensions_Nodes_DateDiff(o, collector)
327
329
  case o.right_node_type
328
330
  when :ruby_date, :ruby_time, :date, :datetime, :time
329
331
  collector <<
@@ -353,7 +355,7 @@ module ArelExtensions
353
355
  collector
354
356
  end
355
357
 
356
- def visit_ArelExtensions_Nodes_DateAdd o, collector
358
+ def visit_ArelExtensions_Nodes_DateAdd(o, collector)
357
359
  collector << 'DATE_ADD('
358
360
  collector = visit o.left, collector
359
361
  collector << COMMA
@@ -362,7 +364,7 @@ module ArelExtensions
362
364
  collector
363
365
  end
364
366
 
365
- def visit_ArelExtensions_Nodes_Duration o, collector
367
+ def visit_ArelExtensions_Nodes_Duration(o, collector)
366
368
  if o.left == 'wd'
367
369
  collector << '(WEEKDAY('
368
370
  collector = visit o.right, collector
@@ -388,28 +390,28 @@ module ArelExtensions
388
390
  collector
389
391
  end
390
392
 
391
- def visit_ArelExtensions_Nodes_IsNull o, collector
393
+ def visit_ArelExtensions_Nodes_IsNull(o, collector)
392
394
  collector << 'ISNULL('
393
395
  collector = visit o.expr, collector
394
396
  collector << ')'
395
397
  collector
396
398
  end
397
399
 
398
- def visit_ArelExtensions_Nodes_IsNotNull o, collector
400
+ def visit_ArelExtensions_Nodes_IsNotNull(o, collector)
399
401
  collector << 'NOT ISNULL('
400
- collector = visit o.expr, collector
401
- collector << ')'
402
- collector
402
+ collector = visit o.expr, collector
403
+ collector << ')'
404
+ collector
403
405
  end
404
406
 
405
- def visit_ArelExtensions_Nodes_Wday o, collector
407
+ def visit_ArelExtensions_Nodes_Wday(o, collector)
406
408
  collector << '(WEEKDAY('
407
409
  collector = visit o.date, collector
408
410
  collector << ') + 1) % 7'
409
411
  collector
410
412
  end
411
413
 
412
- def visit_ArelExtensions_Nodes_Cast o, collector
414
+ def visit_ArelExtensions_Nodes_Cast(o, collector)
413
415
  as_attr =
414
416
  case o.as_attr
415
417
  when :binary then 'binary'
@@ -430,8 +432,8 @@ module ArelExtensions
430
432
  collector
431
433
  end
432
434
 
433
- alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
434
- def visit_Arel_Nodes_SelectStatement o, collector
435
+ alias old_visit_Arel_Nodes_SelectStatement visit_Arel_Nodes_SelectStatement rescue nil
436
+ def visit_Arel_Nodes_SelectStatement(o, collector)
435
437
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
436
438
  o = o.dup
437
439
  o.orders = []
@@ -439,8 +441,8 @@ module ArelExtensions
439
441
  old_visit_Arel_Nodes_SelectStatement(o, collector)
440
442
  end
441
443
 
442
- alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
443
- def visit_Arel_Nodes_As o, collector
444
+ alias old_visit_Arel_Nodes_As visit_Arel_Nodes_As rescue nil
445
+ def visit_Arel_Nodes_As(o, collector)
444
446
  if o.left.is_a?(Arel::Nodes::Binary)
445
447
  collector << '('
446
448
  collector = visit o.left, collector
@@ -460,7 +462,7 @@ module ArelExtensions
460
462
  collector
461
463
  end
462
464
 
463
- def visit_ArelExtensions_Nodes_FormattedNumber o, collector
465
+ def visit_ArelExtensions_Nodes_FormattedNumber(o, collector)
464
466
  col = o.left.coalesce(0)
465
467
  params = o.locale ? [o.precision, Arel.quoted(o.locale)] : [o.precision]
466
468
  sign = Arel.when(col < 0).
@@ -510,7 +512,7 @@ module ArelExtensions
510
512
  collector
511
513
  end
512
514
 
513
- def visit_Aggregate_For_AggregateFunction o, collector
515
+ def visit_Aggregate_For_AggregateFunction(o, collector)
514
516
  if !window_supported?
515
517
  warn('Warning: ArelExtensions: Window Functions are not available in the current version of the DBMS.')
516
518
  return collector
@@ -533,7 +535,7 @@ module ArelExtensions
533
535
  collector
534
536
  end
535
537
 
536
- def visit_ArelExtensions_Nodes_Std o, collector
538
+ def visit_ArelExtensions_Nodes_Std(o, collector)
537
539
  collector << (o.unbiased_estimator ? 'STDDEV_SAMP(' : 'STDDEV_POP(')
538
540
  visit o.left, collector
539
541
  collector << ')'
@@ -541,7 +543,7 @@ module ArelExtensions
541
543
  collector
542
544
  end
543
545
 
544
- def visit_ArelExtensions_Nodes_Variance o, collector
546
+ def visit_ArelExtensions_Nodes_Variance(o, collector)
545
547
  collector << (o.unbiased_estimator ? 'VAR_SAMP(' : 'VAR_POP(')
546
548
  visit o.left, collector
547
549
  collector << ')'
@@ -564,19 +566,19 @@ module ArelExtensions
564
566
 
565
567
  def version_supported?(mariadb_v = '10.2.3', mysql_v = '5.7.0')
566
568
  conn = Arel::Table.engine.connection
567
- conn.send(:mariadb?) && \
568
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v || \
569
- conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
570
- conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
571
- !conn.send(:mariadb?) && \
572
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
573
- conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
574
- conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
569
+ conn.send(:mariadb?) &&
570
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v ||
571
+ conn.respond_to?(:version) && conn.send(:version) >= mariadb_v ||
572
+ conn.instance_variable_get(:@version) && conn.instance_variable_get(:@version) >= mariadb_v) ||
573
+ !conn.send(:mariadb?) &&
574
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v ||
575
+ conn.respond_to?(:version) && conn.send(:version) >= mysql_v ||
576
+ conn.instance_variable_get(:@version) && conn.instance_variable_get(:@version) >= mysql_v)
575
577
  # ideally we should parse the instance_variable @full_version because @version contains only the supposedly
576
578
  # corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
577
579
  end
578
580
 
579
- def visit_ArelExtensions_Nodes_Json o, collector
581
+ def visit_ArelExtensions_Nodes_Json(o, collector)
580
582
  return super if !json_supported?
581
583
 
582
584
  case o.dict
@@ -586,7 +588,7 @@ module ArelExtensions
586
588
  if i != 0
587
589
  collector << COMMA
588
590
  end
589
- collector = visit v, collector
591
+ collector = visit_json_value(o, v, collector)
590
592
  end
591
593
  collector << ')'
592
594
  when Hash
@@ -597,16 +599,34 @@ module ArelExtensions
597
599
  end
598
600
  collector = visit k, collector
599
601
  collector << COMMA
600
- collector = visit v, collector
602
+ collector = visit_json_value(o, v, collector)
601
603
  end
602
604
  collector << ')'
603
605
  else
604
- collector = visit o.dict, collector
606
+ collector = visit_json_value(o, o.dict, collector)
607
+ end
608
+ collector
609
+ end
610
+
611
+ # A JSON Boolean must render as `true`/`false`, not the integer `1`/`0` that MySQL
612
+ # collapses `TRUE`/`FALSE` into inside JSON functions (MariaDB keeps them boolean).
613
+ def visit_json_value(o, v, collector)
614
+ if o.boolean_literal?(v)
615
+ value = v.is_a?(Arel::Nodes::Quoted) ? v.expr : v
616
+ collector << "JSON_EXTRACT('#{value}', '$')"
617
+ elsif o.type_of_node(v) == :boolean
618
+ collector << 'JSON_EXTRACT(CASE WHEN '
619
+ collector = visit v, collector
620
+ collector << " IS NULL THEN NULL WHEN "
621
+ collector = visit v, collector
622
+ collector << " THEN 'true' ELSE 'false' END, '$')"
623
+ else
624
+ collector = visit v, collector
605
625
  end
606
626
  collector
607
627
  end
608
628
 
609
- def visit_ArelExtensions_Nodes_JsonMerge o, collector
629
+ def visit_ArelExtensions_Nodes_JsonMerge(o, collector)
610
630
  collector << 'JSON_MERGE_PATCH('
611
631
  o.expressions.each.with_index do |v, i|
612
632
  if i != 0
@@ -618,7 +638,7 @@ module ArelExtensions
618
638
  collector
619
639
  end
620
640
 
621
- def visit_ArelExtensions_Nodes_JsonGet o, collector
641
+ def visit_ArelExtensions_Nodes_JsonGet(o, collector)
622
642
  collector << 'JSON_EXTRACT('
623
643
  collector = visit o.dict, collector
624
644
  collector << COMMA
@@ -631,7 +651,7 @@ module ArelExtensions
631
651
  collector
632
652
  end
633
653
 
634
- def visit_ArelExtensions_Nodes_JsonSet o, collector
654
+ def visit_ArelExtensions_Nodes_JsonSet(o, collector)
635
655
  collector << 'JSON_SET('
636
656
  collector = visit o.dict, collector
637
657
  collector << COMMA
@@ -646,7 +666,7 @@ module ArelExtensions
646
666
  collector
647
667
  end
648
668
 
649
- def visit_ArelExtensions_Nodes_JsonGroup o, collector
669
+ def visit_ArelExtensions_Nodes_JsonGroup(o, collector)
650
670
  return super if !json_supported?
651
671
 
652
672
  if o.as_array