arel_extensions 2.0.1 → 2.0.4

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 (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