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,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- class Arel::Visitors::IBM_DB
3
+ Arel::Visitors::IBM_DB.class_eval do
4
+
4
5
  def visit_ArelExtensions_Nodes_Ceil o, collector
5
6
  collector << "CEILING("
6
7
  collector = visit o.expr, collector
@@ -11,13 +12,14 @@ module ArelExtensions
11
12
  def visit_ArelExtensions_Nodes_Trim o, collector
12
13
  collector << "LTRIM(RTRIM("
13
14
  o.expressions.each_with_index { |arg, i|
14
- collector << COMMA if i != 0
15
+ collector << Arel::Visitors::IBM_DB::COMMA unless i == 0
15
16
  collector = visit arg, collector
16
17
  }
17
18
  collector << "))"
18
19
  collector
19
20
  end
20
21
 
22
+
21
23
  def visit_ArelExtensions_Nodes_DateDiff o, collector
22
24
  collector << "DAY("
23
25
  collector = visit o.left, collector
@@ -31,8 +33,9 @@ module ArelExtensions
31
33
  collector
32
34
  end
33
35
 
36
+
34
37
  def visit_ArelExtensions_Nodes_Duration o, collector
35
- # visit left for period
38
+ #visit left for period
36
39
  if o.left == "d"
37
40
  collector << "DAY("
38
41
  elsif o.left == "m"
@@ -42,7 +45,7 @@ module ArelExtensions
42
45
  elsif o.left == "y"
43
46
  collector << "YEAR("
44
47
  end
45
- # visit right
48
+ #visit right
46
49
  if o.right.is_a?(Arel::Attributes::Attribute)
47
50
  collector = visit o.right, collector
48
51
  else
@@ -52,11 +55,12 @@ module ArelExtensions
52
55
  collector
53
56
  end
54
57
 
58
+
55
59
  def visit_ArelExtensions_Nodes_IsNull o, collector
56
60
  collector << "COALESCE("
57
61
  collector = visit o.left, collector
58
62
  collector << ","
59
- if (o.right.is_a?(Arel::Attributes::Attribute))
63
+ if(o.right.is_a?(Arel::Attributes::Attribute))
60
64
  collector = visit o.right, collector
61
65
  else
62
66
  collector << "'#{o.right}'"
@@ -64,6 +68,9 @@ module ArelExtensions
64
68
  collector << ")"
65
69
  collector
66
70
  end
71
+
72
+
73
+
67
74
  end
68
75
  end
69
76
  end
@@ -1,26 +1,13 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  module MSSQL
4
-
5
- Arel::Visitors::MSSQL::DATE_MAPPING = {
6
- 'd' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'
7
- }.freeze
8
-
4
+ Arel::Visitors::MSSQL::DATE_MAPPING = {'d' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'}
9
5
  Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES = {
10
6
  '%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => '', '%b' => '', '%^b' => '', # year, month
11
7
  '%d' => 'DD', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
12
8
  '%H' => 'hh', '%k' => '', '%I' => '', '%l' => '', '%P' => '', '%p' => '', # hours
13
9
  '%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
14
- }.freeze
15
-
16
- Arel::Visitors::MSSQL::DATE_FORMAT_REGEX =
17
- Regexp.new(
18
- Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES
19
- .keys
20
- .map{|k| Regexp.escape(k)}
21
- .join('|')
22
- ).freeze
23
-
10
+ }
24
11
  # TODO; all others... http://www.sql-server-helper.com/tips/date-formats.aspx
25
12
  Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS = {
26
13
  'YYYY-MM-DD' => 120,
@@ -32,7 +19,7 @@ module ArelExtensions
32
19
  'DD-MM-YY' => 5,
33
20
  'DD.MM.YYYY' => 104,
34
21
  'YYYY-MM-DDTHH:MM:SS:MMM' => 126
35
- }.freeze
22
+ }
36
23
 
37
24
  # Math Functions
38
25
  def visit_ArelExtensions_Nodes_Ceil o, collector
@@ -45,7 +32,7 @@ module ArelExtensions
45
32
  def visit_ArelExtensions_Nodes_Log10 o, collector
46
33
  collector << "LOG10("
47
34
  o.expressions.each_with_index { |arg, i|
48
- collector << Arel::Visitors::ToSql::COMMA if i != 0
35
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
49
36
  collector = visit arg, collector
50
37
  }
51
38
  collector << ")"
@@ -55,7 +42,7 @@ module ArelExtensions
55
42
  def visit_ArelExtensions_Nodes_Power o, collector
56
43
  collector << "POWER("
57
44
  o.expressions.each_with_index { |arg, i|
58
- collector << Arel::Visitors::ToSql::COMMA if i != 0
45
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
59
46
  collector = visit arg, collector
60
47
  }
61
48
  collector << ")"
@@ -79,7 +66,7 @@ module ArelExtensions
79
66
  def visit_ArelExtensions_Nodes_Concat o, collector
80
67
  collector << "CONCAT("
81
68
  o.expressions.each_with_index { |arg, i|
82
- collector << Arel::Visitors::MSSQL::COMMA if i != 0
69
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
83
70
  collector = visit arg, collector
84
71
  }
85
72
  collector << ")"
@@ -89,7 +76,7 @@ module ArelExtensions
89
76
  def visit_ArelExtensions_Nodes_Repeat o, collector
90
77
  collector << "REPLICATE("
91
78
  o.expressions.each_with_index { |arg, i|
92
- collector << Arel::Visitors::ToSql::COMMA if i != 0
79
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
93
80
  collector = visit arg, collector
94
81
  }
95
82
  collector << ")"
@@ -99,12 +86,12 @@ module ArelExtensions
99
86
 
100
87
 
101
88
  def visit_ArelExtensions_Nodes_DateDiff o, collector
102
- case o.right_node_type
103
- when :ruby_date, :ruby_time, :date, :datetime, :time
104
- collector << case o.left_node_type
105
- when :ruby_time, :datetime, :time then 'DATEDIFF(second'
106
- else 'DATEDIFF(day'
107
- end
89
+ if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
90
+ collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
91
+ 'DATEDIFF(second'
92
+ else
93
+ 'DATEDIFF(day'
94
+ end
108
95
  collector << Arel::Visitors::MSSQL::COMMA
109
96
  collector = visit o.right, collector
110
97
  collector << Arel::Visitors::MSSQL::COMMA
@@ -164,7 +151,7 @@ module ArelExtensions
164
151
  def visit_ArelExtensions_Nodes_Round o, collector
165
152
  collector << "ROUND("
166
153
  o.expressions.each_with_index { |arg, i|
167
- collector << Arel::Visitors::MSSQL::COMMA if i != 0
154
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
168
155
  collector = visit arg, collector
169
156
  }
170
157
  if o.expressions.length == 1
@@ -255,34 +242,42 @@ module ArelExtensions
255
242
  end
256
243
 
257
244
  def visit_ArelExtensions_Nodes_Format o, collector
258
- f = ArelExtensions::Visitors::strftime_to_format(o.iso_format, Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES)
259
- if fmt = Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f]
245
+ f = o.iso_format.dup
246
+ Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
247
+ if Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f]
260
248
  collector << "CONVERT(VARCHAR(#{f.length})"
261
249
  collector << Arel::Visitors::MSSQL::COMMA
262
250
  collector = visit o.left, collector
263
251
  collector << Arel::Visitors::MSSQL::COMMA
264
- collector << fmt.to_s
252
+ collector << Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f].to_s
265
253
  collector << ')'
266
254
  collector
267
255
  else
268
- s = StringScanner.new o.iso_format
269
256
  collector << "("
270
- sep = ''
271
- while !s.eos?
272
- collector << sep
273
- sep = ' + '
274
- case
275
- when s.scan(Arel::Visitors::MSSQL::DATE_FORMAT_REGEX)
276
- dir = Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES[s.matched]
277
- collector << 'LTRIM(STR(DATEPART('
278
- collector << dir
279
- collector << Arel::Visitors::MSSQL::COMMA
280
- collector = visit o.left, collector
281
- collector << ')))'
282
- when s.scan(/[^%]+|./)
283
- collector = visit Arel::Nodes.build_quoted(s.matched), collector
257
+ t = o.iso_format.split('%')
258
+ t.each_with_index {|str, i|
259
+ if i == 0 && t[0] != '%'
260
+ collector = visit Arel::Nodes.build_quoted(str), collector
261
+ if str.length > 1
262
+ collector << Arel::Visitors::MSSQL::COMMA
263
+ collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
264
+ end
265
+ elsif str.length > 0
266
+ if !Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]].blank?
267
+ collector << 'LTRIM(STR(DATEPART('
268
+ collector << Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]]
269
+ collector << Arel::Visitors::MSSQL::COMMA
270
+ collector = visit o.left, collector
271
+ collector << ')))'
272
+ if str.length > 1
273
+ collector << ' + '
274
+ collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
275
+ end
276
+ end
284
277
  end
285
- end
278
+ collector << ' + ' if t[i + 1]
279
+ }
280
+
286
281
  collector << ')'
287
282
  collector
288
283
  end
@@ -291,7 +286,7 @@ module ArelExtensions
291
286
  def visit_ArelExtensions_Nodes_Replace o, collector
292
287
  collector << "REPLACE("
293
288
  o.expressions.each_with_index { |arg, i|
294
- collector << Arel::Visitors::MSSQL::COMMA if i != 0
289
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
295
290
  collector = visit arg, collector
296
291
  }
297
292
  collector << ")"
@@ -301,7 +296,7 @@ module ArelExtensions
301
296
  def visit_ArelExtensions_Nodes_FindInSet o, collector
302
297
  collector << "dbo.FIND_IN_SET("
303
298
  o.expressions.each_with_index { |arg, i|
304
- collector << Arel::Visitors::MSSQL::COMMA if i != 0
299
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
305
300
  collector = visit arg, collector
306
301
  }
307
302
  collector << ")"
@@ -405,16 +400,15 @@ module ArelExtensions
405
400
  collector << "(STRING_AGG("
406
401
  collector = visit o.left, collector
407
402
  collector << Arel::Visitors::Oracle::COMMA
408
- collector =
409
- if o.separator && o.separator != 'NULL'
410
- visit o.separator, collector
411
- else
412
- visit Arel::Nodes.build_quoted(','), collector
413
- end
403
+ if o.right && o.right != 'NULL'
404
+ collector = visit o.right, collector
405
+ else
406
+ collector = visit Arel::Nodes.build_quoted(','), collector
407
+ end
414
408
  collector << ") WITHIN GROUP (ORDER BY "
415
- if o.order.present?
416
- o.order.each_with_index do |order,i|
417
- collector << Arel::Visitors::Oracle::COMMA if i != 0
409
+ if !o.orders.blank?
410
+ o.orders.each_with_index do |order,i|
411
+ collector << Arel::Visitors::Oracle::COMMA unless i == 0
418
412
  collector = visit order, collector
419
413
  end
420
414
  else
@@ -472,9 +466,8 @@ module ArelExtensions
472
466
  Arel::Nodes.build_quoted(1) :
473
467
  ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
474
468
 
475
- number =
476
- if o.scientific_notation
477
- ArelExtensions::Nodes::Concat.new([
469
+ if o.scientific_notation
470
+ number = ArelExtensions::Nodes::Concat.new([
478
471
  Arel::Nodes::NamedFunction.new('FORMAT',[
479
472
  col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
480
473
  param,
@@ -487,13 +480,13 @@ module ArelExtensions
487
480
  locale
488
481
  ])
489
482
  ])
490
- else
491
- Arel::Nodes::NamedFunction.new('FORMAT',[
483
+ else
484
+ number = Arel::Nodes::NamedFunction.new('FORMAT',[
492
485
  Arel::Nodes.build_quoted(col.abs),
493
486
  param,
494
487
  locale
495
488
  ])
496
- end
489
+ end
497
490
 
498
491
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
499
492
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -555,6 +548,7 @@ module ArelExtensions
555
548
  collector
556
549
  end
557
550
 
551
+
558
552
  end
559
553
  end
560
554
  end
@@ -1,24 +1,21 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- class Arel::Visitors::MySQL
4
- DATE_MAPPING = {
5
- 'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY',
6
- 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
7
- }.freeze
8
-
9
- DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
3
+ Arel::Visitors::MySQL.class_eval do
4
+ Arel::Visitors::MySQL::COMMA = ", "
5
+ Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
6
+ Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
10
7
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
11
8
  '%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
12
9
  '%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
13
10
  '%M' => '%i', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => ''
14
- }.freeze
11
+ }
15
12
 
16
13
 
17
- # Math functions
14
+ #Math functions
18
15
  def visit_ArelExtensions_Nodes_Log10 o, collector
19
16
  collector << "LOG10("
20
17
  o.expressions.each_with_index { |arg, i|
21
- collector << Arel::Visitors::ToSql::COMMA if i != 0
18
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
22
19
  collector = visit arg, collector
23
20
  }
24
21
  collector << ")"
@@ -28,14 +25,14 @@ module ArelExtensions
28
25
  def visit_ArelExtensions_Nodes_Power o, collector
29
26
  collector << "POW("
30
27
  o.expressions.each_with_index { |arg, i|
31
- collector << Arel::Visitors::ToSql::COMMA if i != 0
28
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
32
29
  collector = visit arg, collector
33
30
  }
34
31
  collector << ")"
35
32
  collector
36
33
  end
37
34
 
38
- # String functions
35
+ #String functions
39
36
  def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
40
37
  collector << 'LOWER('
41
38
  collector = visit o.left, collector
@@ -101,35 +98,33 @@ module ArelExtensions
101
98
  end
102
99
 
103
100
  def visit_ArelExtensions_Nodes_Collate o, collector
104
- charset =
105
- case o.expressions.first
106
- when Arel::Attributes::Attribute
107
- case o.option
101
+ case o.expressions.first
102
+ when Arel::Attributes::Attribute
103
+ charset = case o.option
108
104
  when 'latin1','utf8'
109
105
  o.option
110
106
  else
111
107
  Arel::Table.engine.connection.charset || 'utf8'
112
108
  end
113
- else
114
- (o.option == 'latin1') ? 'latin1' : 'utf8'
115
- end
109
+ else
110
+ charset = (o.option == 'latin1') ? 'latin1' : 'utf8'
111
+ end
116
112
  collector = visit o.expressions.first, collector
117
- collector <<
118
- if o.ai
119
- " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
120
- # doesn't work in latin1
121
- elsif o.ci
122
- " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
123
- else
124
- " COLLATE #{charset}_bin"
125
- end
113
+ if o.ai
114
+ collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
115
+ #doesn't work in latin1
116
+ elsif o.ci
117
+ collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
118
+ else
119
+ collector << " COLLATE #{charset}_bin"
120
+ end
126
121
  collector
127
122
  end
128
123
 
129
124
  def visit_ArelExtensions_Nodes_Concat o, collector
130
125
  collector << "CONCAT("
131
126
  o.expressions.each_with_index { |arg, i|
132
- collector << COMMA if i != 0
127
+ collector << Arel::Visitors::MySQL::COMMA unless i == 0
133
128
  if (arg.is_a?(Numeric)) || (arg.is_a?(Arel::Attributes::Attribute))
134
129
  collector << "CAST("
135
130
  collector = visit arg, collector
@@ -145,16 +140,16 @@ module ArelExtensions
145
140
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
146
141
  collector << "GROUP_CONCAT("
147
142
  collector = visit o.left, collector
148
- if !o.order.blank?
143
+ if !o.orders.blank?
149
144
  collector << ' ORDER BY '
150
- o.order.each_with_index do |order,i|
151
- collector << Arel::Visitors::ToSql::COMMA if i != 0
145
+ o.orders.each_with_index do |order,i|
146
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
152
147
  collector = visit order, collector
153
148
  end
154
149
  end
155
- if o.separator && o.separator != 'NULL'
150
+ if o.right && o.right != 'NULL'
156
151
  collector << ' SEPARATOR '
157
- collector = visit o.separator, collector
152
+ collector = visit o.right, collector
158
153
  end
159
154
  collector << ")"
160
155
  collector
@@ -169,7 +164,7 @@ module ArelExtensions
169
164
  collector
170
165
  end
171
166
 
172
- def visit_ArelExtensions_Nodes_Ltrim o, collector
167
+ def visit_ArelExtensions_Nodes_Ltrim o , collector
173
168
  collector << 'TRIM(LEADING '
174
169
  collector = visit o.right, collector
175
170
  collector << " FROM "
@@ -178,7 +173,7 @@ module ArelExtensions
178
173
  collector
179
174
  end
180
175
 
181
- def visit_ArelExtensions_Nodes_Rtrim o, collector
176
+ def visit_ArelExtensions_Nodes_Rtrim o , collector
182
177
  collector << 'TRIM(TRAILING '
183
178
  collector = visit o.right, collector
184
179
  collector << " FROM "
@@ -190,28 +185,22 @@ module ArelExtensions
190
185
  def visit_ArelExtensions_Nodes_Repeat o, collector
191
186
  collector << "REPEAT("
192
187
  o.expressions.each_with_index { |arg, i|
193
- collector << Arel::Visitors::ToSql::COMMA if i != 0
188
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
194
189
  collector = visit arg, collector
195
190
  }
196
191
  collector << ")"
197
192
  collector
198
193
  end
199
194
 
200
- def visit_ArelExtensions_Nodes_RegexpReplace o, collector
201
- if !regexp_replace_supported?
202
- warn("Warning : ArelExtensions: REGEXP_REPLACE does not seem to be available in the current version of the DBMS, it might crash")
203
- end
204
- super(o,collector)
205
- end
206
-
207
195
  def visit_ArelExtensions_Nodes_Format o, collector
208
196
  case o.col_type
209
- when :date, :datetime, :time
210
- fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
197
+ when :date, :datetime
211
198
  collector << "DATE_FORMAT("
212
199
  collector = visit o.left, collector
213
- collector << COMMA
214
- collector = visit Arel::Nodes.build_quoted(fmt), collector
200
+ collector << Arel::Visitors::MySQL::COMMA
201
+ f = o.iso_format.dup
202
+ Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
203
+ collector = visit Arel::Nodes.build_quoted(f), collector
215
204
  collector << ")"
216
205
  when :integer, :float, :decimal
217
206
  collector << "FORMAT("
@@ -228,15 +217,14 @@ module ArelExtensions
228
217
  end
229
218
 
230
219
  def visit_ArelExtensions_Nodes_DateDiff o, collector
231
- case o.right_node_type
232
- when :ruby_date, :ruby_time, :date, :datetime, :time
233
- collector <<
234
- case o.left_node_type
235
- when :ruby_time, :datetime, :time then 'TIMESTAMPDIFF(SECOND, '
236
- else 'DATEDIFF('
237
- end
220
+ if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
221
+ collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
222
+ 'TIMESTAMPDIFF(SECOND, '
223
+ else
224
+ 'DATEDIFF('
225
+ end
238
226
  collector = visit o.right, collector
239
- collector << COMMA
227
+ collector << Arel::Visitors::MySQL::COMMA
240
228
  collector = visit o.left, collector
241
229
  collector << ")"
242
230
  else
@@ -260,12 +248,13 @@ module ArelExtensions
260
248
  def visit_ArelExtensions_Nodes_DateAdd o, collector
261
249
  collector << "DATE_ADD("
262
250
  collector = visit o.left, collector
263
- collector << COMMA
251
+ collector << Arel::Visitors::MySQL::COMMA
264
252
  collector = visit o.mysql_value(o.right), collector
265
253
  collector << ")"
266
254
  collector
267
255
  end
268
256
 
257
+
269
258
  def visit_ArelExtensions_Nodes_Duration o, collector
270
259
  if o.left == 'wd'
271
260
  collector << "(WEEKDAY("
@@ -274,18 +263,18 @@ module ArelExtensions
274
263
  else
275
264
  if o.with_interval
276
265
  case o.left
277
- when 'd','m','y'
266
+ when 'd','m','y'
278
267
  interval = 'DAY'
279
268
  when 'h','mn','s'
280
269
  interval = 'SECOND'
281
270
  when /i\z/
282
- interval = DATE_MAPPING[o.left[0..-2]]
271
+ interval = Arel::Visitors::MySQL::DATE_MAPPING[o.left[0..-2]]
283
272
  else
284
273
  interval = nil
285
274
  end
286
275
  end
287
276
  collector << " INTERVAL " if o.with_interval && interval
288
- collector << "#{DATE_MAPPING[o.left]}("
277
+ collector << "#{Arel::Visitors::MySQL::DATE_MAPPING[o.left]}("
289
278
  collector = visit o.right, collector
290
279
  collector << ")"
291
280
  collector << " #{interval} " if o.with_interval && interval
@@ -293,6 +282,7 @@ module ArelExtensions
293
282
  collector
294
283
  end
295
284
 
285
+
296
286
  def visit_ArelExtensions_Nodes_IsNull o, collector
297
287
  collector << "ISNULL("
298
288
  collector = visit o.expr, collector
@@ -318,25 +308,30 @@ module ArelExtensions
318
308
  collector << "CAST("
319
309
  collector = visit o.left, collector
320
310
  collector << " AS "
321
- as_attr =
322
- Arel::Nodes::SqlLiteral.new(
323
- case o.as_attr
324
- when :string then 'char'
325
- when :time then 'time'
326
- when :int then 'signed'
327
- when :number, :decimal then 'decimal(20,6)'
328
- when :datetime then 'datetime'
329
- when :date then 'date'
330
- when :binary then 'binary'
331
- else o.as_attr.to_s
332
- end
333
- )
311
+ case o.as_attr
312
+ when :string
313
+ as_attr = Arel::Nodes::SqlLiteral.new('char')
314
+ when :time
315
+ as_attr = Arel::Nodes::SqlLiteral.new('time')
316
+ when :int
317
+ as_attr = Arel::Nodes::SqlLiteral.new('signed')
318
+ when :number, :decimal
319
+ as_attr = Arel::Nodes::SqlLiteral.new('decimal(20,6)')
320
+ when :datetime
321
+ as_attr = Arel::Nodes::SqlLiteral.new('datetime')
322
+ when :date
323
+ as_attr = Arel::Nodes::SqlLiteral.new('date')
324
+ when :binary
325
+ as_attr = Arel::Nodes::SqlLiteral.new('binary')
326
+ else
327
+ as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
328
+ end
334
329
  collector = visit as_attr, collector
335
330
  collector << ")"
336
331
  collector
337
332
  end
338
333
 
339
- alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
334
+ alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
340
335
  def visit_Arel_Nodes_SelectStatement o, collector
341
336
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
342
337
  o = o.dup
@@ -345,7 +340,7 @@ module ArelExtensions
345
340
  old_visit_Arel_Nodes_SelectStatement(o,collector)
346
341
  end
347
342
 
348
- alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
343
+ alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
349
344
  def visit_Arel_Nodes_As o, collector
350
345
  if o.left.is_a?(Arel::Nodes::Binary)
351
346
  collector << '('
@@ -368,21 +363,20 @@ module ArelExtensions
368
363
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
369
364
  sign_length = ArelExtensions::Nodes::Length.new([sign])
370
365
 
371
- number =
372
- if o.scientific_notation
373
- ArelExtensions::Nodes::Concat.new([
374
- Arel::Nodes::NamedFunction.new('FORMAT',[
375
- col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
376
- ]+params),
377
- o.type,
378
- Arel::Nodes::NamedFunction.new('FORMAT',[
379
- col.abs.log10.floor,
380
- 0
381
- ])
366
+ if o.scientific_notation
367
+ number = ArelExtensions::Nodes::Concat.new([
368
+ Arel::Nodes::NamedFunction.new('FORMAT',[
369
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
370
+ ]+params),
371
+ o.type,
372
+ Arel::Nodes::NamedFunction.new('FORMAT',[
373
+ col.abs.log10.floor,
374
+ 0
382
375
  ])
383
- else
384
- Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
385
- end
376
+ ])
377
+ else
378
+ number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
379
+ end
386
380
 
387
381
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
388
382
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -405,34 +399,10 @@ module ArelExtensions
405
399
  collector
406
400
  end
407
401
 
408
- def visit_Aggregate_For_AggregateFunction o, collector
409
- if !window_supported?
410
- warn("Warning : ArelExtensions: Window Functions are not available in the current version of the DBMS.")
411
- return collector
412
- end
413
-
414
- if !o.order.empty? || !o.group.empty?
415
- collector << " OVER ("
416
- if !o.group.empty?
417
- collector << " PARTITION BY ("
418
- visit o.group, collector
419
- collector << ")"
420
- end
421
- if !o.order.empty?
422
- collector << " ORDER BY ("
423
- visit o.order, collector
424
- collector << ")"
425
- end
426
- collector << ")"
427
- end
428
- collector
429
- end
430
-
431
402
  def visit_ArelExtensions_Nodes_Std o, collector
432
403
  collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
433
404
  visit o.left, collector
434
405
  collector << ")"
435
- visit_Aggregate_For_AggregateFunction o, collector
436
406
  collector
437
407
  end
438
408
 
@@ -440,46 +410,25 @@ module ArelExtensions
440
410
  collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
441
411
  visit o.left, collector
442
412
  collector << ")"
443
- visit_Aggregate_For_AggregateFunction o, collector
444
413
  collector
445
414
  end
446
415
 
447
- # JSON if implemented only after 10.2.3 (aggregations after 10.5.0) in MariaDb and 5.7 (aggregations after 5.7.22) in MySql
416
+ # JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
448
417
  def json_supported?
449
- version_supported?('10.5.0', '5.7.22')
450
- end
451
-
452
- def window_supported?
453
- version_supported?('10.2.3', '8.0')
454
- end
455
-
456
- def regexp_replace_supported?
457
- version_supported?('10.0.5', '8.0')
458
- end
459
-
460
- def version_supported?(mariadb_v = '10.2.3', mysql_v = '5.7.0')
461
- conn = Arel::Table.engine.connection
462
- conn.send(:mariadb?) && \
463
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v || \
464
- conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
465
- conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
466
- !conn.send(:mariadb?) && \
467
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
468
- conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
469
- conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
470
- # ideally we should parse the instance_variable @full_version because @version contains only the supposedly
471
- # corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
418
+ Arel::Table.engine.connection.send(:mariadb?) &&
419
+ Arel::Table.engine.connection.send(:version) >= '10.2.3' ||
420
+ !Arel::Table.engine.connection.send(:mariadb?) &&
421
+ Arel::Table.engine.connection.send(:version) >= '5.7.0'
472
422
  end
473
423
 
474
424
  def visit_ArelExtensions_Nodes_Json o,collector
475
425
  return super if !json_supported?
476
-
477
426
  case o.dict
478
427
  when Array
479
428
  collector << 'JSON_ARRAY('
480
429
  o.dict.each.with_index do |v,i|
481
430
  if i != 0
482
- collector << COMMA
431
+ collector << Arel::Visitors::MySQL::COMMA
483
432
  end
484
433
  collector = visit v, collector
485
434
  end
@@ -488,10 +437,10 @@ module ArelExtensions
488
437
  collector << 'JSON_OBJECT('
489
438
  o.dict.each.with_index do |(k,v),i|
490
439
  if i != 0
491
- collector << COMMA
440
+ collector << Arel::Visitors::MySQL::COMMA
492
441
  end
493
442
  collector = visit k, collector
494
- collector << COMMA
443
+ collector << Arel::Visitors::MySQL::COMMA
495
444
  collector = visit v, collector
496
445
  end
497
446
  collector << ')'
@@ -505,7 +454,7 @@ module ArelExtensions
505
454
  collector << 'JSON_MERGE_PATCH('
506
455
  o.expressions.each.with_index do |v,i|
507
456
  if i != 0
508
- collector << COMMA
457
+ collector << Arel::Visitors::MySQL::COMMA
509
458
  end
510
459
  collector = visit v, collector
511
460
  end
@@ -516,7 +465,7 @@ module ArelExtensions
516
465
  def visit_ArelExtensions_Nodes_JsonGet o,collector
517
466
  collector << 'JSON_EXTRACT('
518
467
  collector = visit o.dict, collector
519
- collector << COMMA
468
+ collector << Arel::Visitors::MySQL::COMMA
520
469
  if o.key.is_a?(Integer)
521
470
  collector << "\"$[#{o.key}]\""
522
471
  else
@@ -529,13 +478,13 @@ module ArelExtensions
529
478
  def visit_ArelExtensions_Nodes_JsonSet o,collector
530
479
  collector << 'JSON_SET('
531
480
  collector = visit o.dict, collector
532
- collector << COMMA
481
+ collector << Arel::Visitors::MySQL::COMMA
533
482
  if o.key.is_a?(Integer)
534
483
  collector << "\"$[#{o.key}]\""
535
484
  else
536
485
  collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
537
486
  end
538
- collector << COMMA
487
+ collector << Arel::Visitors::MySQL::COMMA
539
488
  collector = visit o.value, collector
540
489
  collector << ')'
541
490
  collector
@@ -543,7 +492,6 @@ module ArelExtensions
543
492
 
544
493
  def visit_ArelExtensions_Nodes_JsonGroup o, collector
545
494
  return super if !json_supported?
546
-
547
495
  if o.as_array
548
496
  collector << 'JSON_ARRAYAGG('
549
497
  collector = visit o.dict, collector
@@ -554,11 +502,11 @@ module ArelExtensions
554
502
  collector << 'JSON_MERGE_PATCH(' if o.dict.length > 1
555
503
  o.dict.each.with_index do |(k,v),i|
556
504
  if i != 0
557
- collector << COMMA
505
+ collector << Arel::Visitors::MySQL::COMMA
558
506
  end
559
507
  collector << 'JSON_OBJECTAGG('
560
508
  collector = visit k, collector
561
- collector << COMMA
509
+ collector << Arel::Visitors::MySQL::COMMA
562
510
  collector = visit v, collector
563
511
  collector << ')'
564
512
  end
@@ -571,6 +519,7 @@ module ArelExtensions
571
519
  end
572
520
  collector
573
521
  end
522
+
574
523
  end
575
524
  end
576
525
  end