arel_extensions 2.0.1 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +10 -10
  4. data/Gemfile +14 -19
  5. data/README.md +17 -12
  6. data/Rakefile +23 -23
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +2 -2
  9. data/functions.html +3 -3
  10. data/gemfiles/rails6.gemfile +30 -0
  11. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  12. data/generate_gems.sh +13 -0
  13. data/init/mssql.sql +4 -4
  14. data/init/mysql.sql +38 -38
  15. data/init/postgresql.sql +21 -21
  16. data/lib/arel_extensions/boolean_functions.rb +0 -2
  17. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  18. data/lib/arel_extensions/comparators.rb +4 -2
  19. data/lib/arel_extensions/insert_manager.rb +12 -12
  20. data/lib/arel_extensions/math.rb +3 -3
  21. data/lib/arel_extensions/math_functions.rb +10 -5
  22. data/lib/arel_extensions/nodes/aggregate_function.rb +14 -0
  23. data/lib/arel_extensions/nodes/case.rb +0 -2
  24. data/lib/arel_extensions/nodes/coalesce.rb +2 -2
  25. data/lib/arel_extensions/nodes/collate.rb +1 -1
  26. data/lib/arel_extensions/nodes/concat.rb +6 -13
  27. data/lib/arel_extensions/nodes/date_diff.rb +3 -5
  28. data/lib/arel_extensions/nodes/duration.rb +0 -2
  29. data/lib/arel_extensions/nodes/format.rb +8 -8
  30. data/lib/arel_extensions/nodes/formatted_number.rb +23 -23
  31. data/lib/arel_extensions/nodes/function.rb +2 -0
  32. data/lib/arel_extensions/nodes/json.rb +28 -30
  33. data/lib/arel_extensions/nodes/matches.rb +4 -4
  34. data/lib/arel_extensions/nodes/power.rb +6 -5
  35. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  36. data/lib/arel_extensions/nodes/replace.rb +24 -6
  37. data/lib/arel_extensions/nodes/round.rb +5 -5
  38. data/lib/arel_extensions/nodes/soundex.rb +16 -15
  39. data/lib/arel_extensions/nodes/std.rb +19 -21
  40. data/lib/arel_extensions/nodes/substring.rb +8 -15
  41. data/lib/arel_extensions/nodes/sum.rb +7 -0
  42. data/lib/arel_extensions/nodes/trim.rb +3 -3
  43. data/lib/arel_extensions/nodes/union.rb +2 -3
  44. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  45. data/lib/arel_extensions/nodes.rb +1 -1
  46. data/lib/arel_extensions/null_functions.rb +2 -2
  47. data/lib/arel_extensions/predications.rb +16 -17
  48. data/lib/arel_extensions/string_functions.rb +21 -12
  49. data/lib/arel_extensions/tasks.rb +5 -5
  50. data/lib/arel_extensions/version.rb +1 -1
  51. data/lib/arel_extensions/visitors/mssql.rb +14 -13
  52. data/lib/arel_extensions/visitors/mysql.rb +72 -37
  53. data/lib/arel_extensions/visitors/oracle.rb +12 -11
  54. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  55. data/lib/arel_extensions/visitors/postgresql.rb +77 -31
  56. data/lib/arel_extensions/visitors/sqlite.rb +54 -40
  57. data/lib/arel_extensions/visitors/to_sql.rb +50 -31
  58. data/lib/arel_extensions.rb +20 -1
  59. data/test/helper.rb +1 -1
  60. data/test/real_db_test.rb +1 -1
  61. data/test/support/fake_record.rb +0 -4
  62. data/test/test_comparators.rb +1 -1
  63. data/test/visitors/test_bulk_insert_oracle.rb +6 -6
  64. data/test/visitors/test_bulk_insert_sqlite.rb +6 -6
  65. data/test/visitors/test_bulk_insert_to_sql.rb +7 -9
  66. data/test/visitors/test_oracle.rb +1 -0
  67. data/test/visitors/test_to_sql.rb +15 -1
  68. data/test/with_ar/all_agnostic_test.rb +54 -32
  69. data/test/with_ar/insert_agnostic_test.rb +2 -1
  70. data/test/with_ar/test_bulk_sqlite.rb +2 -2
  71. data/test/with_ar/test_math_sqlite.rb +3 -3
  72. data/test/with_ar/test_string_mysql.rb +3 -5
  73. data/test/with_ar/test_string_sqlite.rb +2 -6
  74. data/version_v1.rb +3 -0
  75. data/version_v2.rb +3 -0
  76. metadata +13 -6
@@ -1,22 +1,15 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
3
  class Substring < Function
4
- RETURN_TYPE = :string
4
+ RETURN_TYPE = :string
5
5
 
6
- def initialize expr
7
- tab = [convert_to_node(expr[0]), convert_to_node(expr[1])]
8
- if expr[2]
9
- tab << convert_to_node(expr[2])
10
- # else
11
- # tab << expr[0].length
12
- end
13
- return super(tab)
14
- end
15
-
16
- # def +(other)
17
- # puts "[Substring] : #{other.inspect} (#{self.expressions.inspect})"
18
- # return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
19
- # end
6
+ def initialize expr
7
+ tab = [convert_to_node(expr[0]), convert_to_node(expr[1])]
8
+ if expr[2]
9
+ tab << convert_to_node(expr[2])
10
+ end
11
+ return super(tab)
12
+ end
20
13
 
21
14
  end
22
15
  end
@@ -0,0 +1,7 @@
1
+ module ArelExtensions
2
+ module Nodes
3
+ class Sum < AggregateFunction
4
+ RETURN_TYPE = :number
5
+ end
6
+ end
7
+ end
@@ -2,7 +2,7 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Trim < Function
4
4
  RETURN_TYPE = :string
5
-
5
+
6
6
  def initialize expr
7
7
  tab = expr.map { |arg|
8
8
  convert_to_node(arg)
@@ -11,13 +11,13 @@ module ArelExtensions
11
11
  end
12
12
 
13
13
  def +(other)
14
- return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
14
+ return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
15
15
  end
16
16
 
17
17
  end
18
18
 
19
19
  class Ltrim < Trim
20
- RETURN_TYPE = :string
20
+ RETURN_TYPE = :string
21
21
  end
22
22
 
23
23
  class Rtrim < Trim
@@ -7,11 +7,11 @@ module ArelExtensions
7
7
  end
8
8
 
9
9
  def +(other)
10
- return ArelExtensions::Nodes::Union.new(self,other)
10
+ return ArelExtensions::Nodes::Union.new(self,other)
11
11
  end
12
12
 
13
13
  def union(other)
14
- return ArelExtensions::Nodes::UnionAll.new(self,other)
14
+ return ArelExtensions::Nodes::UnionAll.new(self,other)
15
15
  end
16
16
 
17
17
  def as other
@@ -21,4 +21,3 @@ module ArelExtensions
21
21
 
22
22
  end
23
23
  end
24
-
@@ -17,4 +17,3 @@ module ArelExtensions
17
17
 
18
18
  end
19
19
  end
20
-
@@ -1,2 +1,2 @@
1
1
  require 'arel_extensions/nodes/function'
2
-
2
+ require 'arel_extensions/nodes/aggregate_function'
@@ -8,12 +8,12 @@ module ArelExtensions
8
8
  def is_null
9
9
  ArelExtensions::Nodes::IsNull.new [self]
10
10
  end
11
-
11
+
12
12
  #ISNOTNULL function lets you return an alternative value when an expression is NOT NULL.
13
13
  def is_not_null
14
14
  ArelExtensions::Nodes::IsNotNull.new [self]
15
15
  end
16
-
16
+
17
17
  # returns the first non-null expr in the expression list. You must specify at least two expressions.
18
18
  #If all occurrences of expr evaluate to null, then the function returns null.
19
19
  def coalesce *args
@@ -1,10 +1,10 @@
1
1
  module ArelExtensions
2
2
  module Predications
3
- def when right, expression=nil
3
+ def when right, expression = nil
4
4
  ArelExtensions::Nodes::Case.new(self).when(right,expression)
5
5
  end
6
6
 
7
- def matches(other, escape=nil,case_sensitive= nil)
7
+ def matches(other, escape = nil,case_sensitive = nil)
8
8
  if Arel::VERSION.to_i < 7
9
9
  Arel::Nodes::Matches.new(self, Arel::Nodes.build_quoted(other), escape)
10
10
  else
@@ -12,7 +12,7 @@ module ArelExtensions
12
12
  end
13
13
  end
14
14
 
15
- def imatches(other, escape=nil)
15
+ def imatches(other, escape = nil)
16
16
  ArelExtensions::Nodes::IMatches.new(self, other, escape)
17
17
  end
18
18
 
@@ -25,25 +25,24 @@ module ArelExtensions
25
25
  when Range
26
26
  self.between(other)
27
27
  when Enumerable
28
- if other.include?(nil)
29
- other.delete(nil)
30
- case other.length
31
- when 0
32
- self.is_null
33
- when 1
34
- self.is_null.or(self==other[0])
35
- else
36
- self.is_null.or(Arel::Nodes::In.new(self,quoted_array(other)))
37
- end
38
- else
39
- Arel::Nodes::In.new(self,quoted_array(other))
40
- end
28
+ nils, values = other.partition{ |v| v.nil? }
29
+ ranges, values = values.partition{ |v| v.is_a?(Range) || v.is_a?(Arel::SelectManager)}
30
+
31
+ # In order of (imagined) decreasing efficiency: nil, values, and then more complex.
32
+ clauses =
33
+ nils.uniq.map { |r| self.in(r) } \
34
+ + (case values.uniq.size
35
+ when 0 then []
36
+ when 1 then [self == values[0]]
37
+ else [Arel::Nodes::In.new(self, quoted_array(values))] end) \
38
+ + ranges.uniq.map { |r| self.in(r) }
39
+ clauses.empty? ? self.is_null : clauses.reduce(&:or)
41
40
  when nil
42
41
  self.is_null
43
42
  when Arel::SelectManager
44
43
  Arel::Nodes::In.new(self, other.ast)
45
44
  else
46
- Arel::Nodes::In.new(self,quoted_node(other))
45
+ Arel::Nodes::In.new(self, quoted_node(other))
47
46
  end
48
47
  end
49
48
 
@@ -92,7 +92,7 @@ module ArelExtensions
92
92
  ArelExtensions::Nodes::SMatches.new(self,other)
93
93
  end
94
94
 
95
- def ai_collate
95
+ def ai_collate
96
96
  ArelExtensions::Nodes::Collate.new(self,nil,true,false)
97
97
  end
98
98
 
@@ -100,31 +100,40 @@ module ArelExtensions
100
100
  ArelExtensions::Nodes::Collate.new(self,nil,false,true)
101
101
  end
102
102
 
103
- def collate ai=false,ci=false, option=nil
103
+ def collate ai = false,ci = false, option = nil
104
104
  ArelExtensions::Nodes::Collate.new(self,option,ai,ci)
105
105
  end
106
106
 
107
107
  #REPLACE function replaces a sequence of characters in a string with another set of characters, not case-sensitive.
108
- def replace left, right
109
- ArelExtensions::Nodes::Replace.new [self, left, right]
108
+ def replace pattern, substitute
109
+ if pattern.is_a? Regexp
110
+ ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
111
+ else
112
+ ArelExtensions::Nodes::Replace.new self, pattern, substitute
113
+ end
114
+ end
115
+
116
+ def regexp_replace pattern, substitute
117
+ ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
110
118
  end
111
-
119
+
112
120
  def concat other
113
121
  ArelExtensions::Nodes::Concat.new [self, other]
114
122
  end
115
123
 
116
124
  #concat elements of a group, separated by sep and ordered by a list of Ascending or Descending
117
- def group_concat sep = nil, *orders
125
+ def group_concat(sep = nil, *orders, group: nil, order: nil)
126
+ if orders.present?
127
+ warn("Warning : ArelExtensions: group_concat: you should now use the kwarg 'order' to specify an order in the group_concat.")
128
+ end
118
129
  order_tabs = [orders].flatten.map{ |o|
119
130
  if o.is_a?(Arel::Nodes::Ascending) || o.is_a?(Arel::Nodes::Descending)
120
131
  o
121
132
  elsif o.respond_to?(:asc)
122
133
  o.asc
123
- else
124
- nil
125
134
  end
126
135
  }.compact
127
- ArelExtensions::Nodes::GroupConcat.new [self, sep, order_tabs]
136
+ ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order: (order || order_tabs))
128
137
  end
129
138
 
130
139
  #Function returns a string after removing left, right or the both prefixes or suffixes int argument
@@ -155,11 +164,11 @@ module ArelExtensions
155
164
  def not_blank
156
165
  ArelExtensions::Nodes::NotBlank.new [self]
157
166
  end
158
-
159
- def repeat other = 1
167
+
168
+ def repeat other = 1
160
169
  ArelExtensions::Nodes::Repeat.new [self, other]
161
170
  end
162
-
171
+
163
172
  def levenshtein_distance other
164
173
  ArelExtensions::Nodes::LevenshteinDistance.new [self, other]
165
174
  end
@@ -1,12 +1,12 @@
1
1
  namespace :arel_extensions do
2
- desc 'Install DB functions into current DB'
3
- task :install_functions => :environment do
4
- @env_db = if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
2
+ desc 'Install DB functions into current DB'
3
+ task :install_functions => :environment do
4
+ @env_db = if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
5
5
  (RUBY_PLATFORM == 'java' ? "jdbc-sqlite" : 'sqlite')
6
6
  else
7
7
  ENV['DB'] || ActiveRecord::Base.connection.adapter_name
8
8
  end
9
- ActiveRecord::Base.establish_connection(Rails.env)
9
+ ActiveRecord::Base.establish_connection(Rails.env.to_sym)
10
10
  CommonSqlFunctions.new(ActiveRecord::Base.connection).add_sql_functions(@env_db)
11
- end
11
+ end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "2.0.1".freeze
2
+ VERSION = "2.0.4".freeze
3
3
  end
@@ -400,14 +400,15 @@ module ArelExtensions
400
400
  collector << "(STRING_AGG("
401
401
  collector = visit o.left, collector
402
402
  collector << Arel::Visitors::Oracle::COMMA
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
403
+ collector =
404
+ if o.separator && o.separator != 'NULL'
405
+ visit o.separator, collector
406
+ else
407
+ visit Arel::Nodes.build_quoted(','), collector
408
+ end
408
409
  collector << ") WITHIN GROUP (ORDER BY "
409
- if !o.orders.blank?
410
- o.orders.each_with_index do |order,i|
410
+ if o.order.present?
411
+ o.order.each_with_index do |order,i|
411
412
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
412
413
  collector = visit order, collector
413
414
  end
@@ -466,8 +467,9 @@ module ArelExtensions
466
467
  Arel::Nodes.build_quoted(1) :
467
468
  ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
468
469
 
469
- if o.scientific_notation
470
- number = ArelExtensions::Nodes::Concat.new([
470
+ number =
471
+ if o.scientific_notation
472
+ ArelExtensions::Nodes::Concat.new([
471
473
  Arel::Nodes::NamedFunction.new('FORMAT',[
472
474
  col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
473
475
  param,
@@ -480,13 +482,13 @@ module ArelExtensions
480
482
  locale
481
483
  ])
482
484
  ])
483
- else
484
- number = Arel::Nodes::NamedFunction.new('FORMAT',[
485
+ else
486
+ Arel::Nodes::NamedFunction.new('FORMAT',[
485
487
  Arel::Nodes.build_quoted(col.abs),
486
488
  param,
487
489
  locale
488
490
  ])
489
- end
491
+ end
490
492
 
491
493
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
492
494
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -548,7 +550,6 @@ module ArelExtensions
548
550
  collector
549
551
  end
550
552
 
551
-
552
553
  end
553
554
  end
554
555
  end
@@ -1,7 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  Arel::Visitors::MySQL.class_eval do
4
- Arel::Visitors::MySQL::COMMA = ", "
5
4
  Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
6
5
  Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
7
6
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
@@ -98,26 +97,28 @@ module ArelExtensions
98
97
  end
99
98
 
100
99
  def visit_ArelExtensions_Nodes_Collate o, collector
101
- case o.expressions.first
102
- when Arel::Attributes::Attribute
103
- charset = case o.option
100
+ charset =
101
+ case o.expressions.first
102
+ when Arel::Attributes::Attribute
103
+ case o.option
104
104
  when 'latin1','utf8'
105
105
  o.option
106
106
  else
107
107
  Arel::Table.engine.connection.charset || 'utf8'
108
108
  end
109
- else
110
- charset = (o.option == 'latin1') ? 'latin1' : 'utf8'
111
- end
109
+ else
110
+ (o.option == 'latin1') ? 'latin1' : 'utf8'
111
+ end
112
112
  collector = visit o.expressions.first, collector
113
- if o.ai
114
- collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
113
+ collector <<
114
+ if o.ai
115
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
115
116
  #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
117
+ elsif o.ci
118
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
119
+ else
120
+ " COLLATE #{charset}_bin"
121
+ end
121
122
  collector
122
123
  end
123
124
 
@@ -140,16 +141,16 @@ module ArelExtensions
140
141
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
141
142
  collector << "GROUP_CONCAT("
142
143
  collector = visit o.left, collector
143
- if !o.orders.blank?
144
+ if !o.order.blank?
144
145
  collector << ' ORDER BY '
145
- o.orders.each_with_index do |order,i|
146
+ o.order.each_with_index do |order,i|
146
147
  collector << Arel::Visitors::ToSql::COMMA unless i == 0
147
148
  collector = visit order, collector
148
149
  end
149
150
  end
150
- if o.right && o.right != 'NULL'
151
+ if o.separator && o.separator != 'NULL'
151
152
  collector << ' SEPARATOR '
152
- collector = visit o.right, collector
153
+ collector = visit o.separator, collector
153
154
  end
154
155
  collector << ")"
155
156
  collector
@@ -263,7 +264,7 @@ module ArelExtensions
263
264
  else
264
265
  if o.with_interval
265
266
  case o.left
266
- when 'd','m','y'
267
+ when 'd','m','y'
267
268
  interval = 'DAY'
268
269
  when 'h','mn','s'
269
270
  interval = 'SECOND'
@@ -363,20 +364,21 @@ module ArelExtensions
363
364
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
364
365
  sign_length = ArelExtensions::Nodes::Length.new([sign])
365
366
 
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
367
+ number =
368
+ if o.scientific_notation
369
+ ArelExtensions::Nodes::Concat.new([
370
+ Arel::Nodes::NamedFunction.new('FORMAT',[
371
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
372
+ ]+params),
373
+ o.type,
374
+ Arel::Nodes::NamedFunction.new('FORMAT',[
375
+ col.abs.log10.floor,
376
+ 0
377
+ ])
375
378
  ])
376
- ])
377
- else
378
- number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
379
- end
379
+ else
380
+ Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
381
+ end
380
382
 
381
383
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
382
384
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -399,10 +401,34 @@ module ArelExtensions
399
401
  collector
400
402
  end
401
403
 
404
+ def visit_Aggregate_For_AggregateFunction o, collector
405
+ if !window_supported?
406
+ warn("Warning : ArelExtensions: Window Functions are not available in the current version on the DBMS.")
407
+ return collector
408
+ end
409
+
410
+ if !o.order.empty? || !o.group.empty?
411
+ collector << " OVER ("
412
+ if !o.group.empty?
413
+ collector << " PARTITION BY ("
414
+ visit o.group, collector
415
+ collector << ")"
416
+ end
417
+ if !o.order.empty?
418
+ collector << " ORDER BY ("
419
+ visit o.order, collector
420
+ collector << ")"
421
+ end
422
+ collector << ")"
423
+ end
424
+ collector
425
+ end
426
+
402
427
  def visit_ArelExtensions_Nodes_Std o, collector
403
428
  collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
404
429
  visit o.left, collector
405
430
  collector << ")"
431
+ visit_Aggregate_For_AggregateFunction o, collector
406
432
  collector
407
433
  end
408
434
 
@@ -410,18 +436,27 @@ module ArelExtensions
410
436
  collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
411
437
  visit o.left, collector
412
438
  collector << ")"
439
+ visit_Aggregate_For_AggregateFunction o, collector
413
440
  collector
414
441
  end
415
442
 
416
443
  # JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
417
444
  def json_supported?
445
+ version_supported?('10.2.3', '5.7.0')
446
+ end
447
+
448
+ def window_supported?
449
+ version_supported?('10.2.3', '8.0')
450
+ end
451
+
452
+ def version_supported?(mysql_v = '10.2.3',mariadb_v = '5.7.0')
418
453
  conn = Arel::Table.engine.connection
419
454
  conn.send(:mariadb?) &&
420
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= '10.2.3' ||
421
- conn.respond_to?(:version) && conn.send(:version) >= '10.2.3') ||
422
- !Arel::Table.engine.connection.send(:mariadb?) &&
423
- (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= '5.7.0' ||
424
- conn.respond_to?(:version) && conn.send(:version) >= '5.7.0')
455
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v ||
456
+ conn.respond_to?(:version) && conn.send(:version) >= mysql_v) ||
457
+ !Arel::Table.engine.connection.send(:mariadb?) &&
458
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v ||
459
+ conn.respond_to?(:version) && conn.send(:version) >= mariadb_v)
425
460
  end
426
461
 
427
462
  def visit_ArelExtensions_Nodes_Json o,collector
@@ -131,14 +131,15 @@ module ArelExtensions
131
131
  collector << "(LISTAGG("
132
132
  collector = visit o.left, collector
133
133
  collector << Arel::Visitors::Oracle::COMMA
134
- if o.right && o.right != 'NULL'
135
- collector = visit o.right, collector
136
- else
137
- collector = visit Arel::Nodes.build_quoted(','), collector
138
- end
134
+ collector =
135
+ if o.separator && o.separator != 'NULL'
136
+ visit o.separator, collector
137
+ else
138
+ visit Arel::Nodes.build_quoted(','), collector
139
+ end
139
140
  collector << ") WITHIN GROUP (ORDER BY "
140
- if !o.orders.blank?
141
- o.orders.each_with_index do |order,i|
141
+ if !o.order.blank?
142
+ o.order.each_with_index do |order,i|
142
143
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
143
144
  collector = visit order, collector
144
145
  end
@@ -154,7 +155,7 @@ module ArelExtensions
154
155
  o.expressions.each_with_index { |arg, i|
155
156
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
156
157
  if i > 0 && o.left_node_type == :text
157
- if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
+ if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
159
  collector << "NULL"
159
160
  else
160
161
  collector << 'TO_CLOB('
@@ -489,9 +490,9 @@ module ArelExtensions
489
490
  o.left.each_with_index do |row, idx|
490
491
  collector << " UNION ALL " if idx != 0
491
492
  collector << "(SELECT "
492
- len = row.length - 1
493
- row.each_with_index { |value, i|
494
- attr = o.cols[i]
493
+ v = Arel::Nodes::Values.new(row, o.cols)
494
+ len = v.expressions.length - 1
495
+ v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
495
496
  case value
496
497
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
497
498
  collector = visit value, collector
@@ -68,7 +68,7 @@ module ArelExtensions
68
68
  if i != 0
69
69
  collector << Arel::Visitors::MySQL::COMMA
70
70
  end
71
- collector = visit v, collector
71
+ collector = visit v, collector
72
72
  end
73
73
  collector << ')'
74
74
  when Hash