arel_extensions 1.2.5 → 1.2.8

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/README.md +7 -2
  4. data/Rakefile +23 -23
  5. data/arel_extensions.gemspec +1 -1
  6. data/functions.html +2 -2
  7. data/gemfiles/rails6.gemfile +30 -0
  8. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  9. data/generate_gems.sh +13 -0
  10. data/lib/arel_extensions.rb +4 -1
  11. data/lib/arel_extensions/boolean_functions.rb +0 -2
  12. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  13. data/lib/arel_extensions/insert_manager.rb +24 -24
  14. data/lib/arel_extensions/math.rb +3 -3
  15. data/lib/arel_extensions/math_functions.rb +4 -4
  16. data/lib/arel_extensions/nodes/case.rb +0 -2
  17. data/lib/arel_extensions/nodes/collate.rb +1 -1
  18. data/lib/arel_extensions/nodes/date_diff.rb +1 -3
  19. data/lib/arel_extensions/nodes/duration.rb +0 -2
  20. data/lib/arel_extensions/nodes/formatted_number.rb +20 -20
  21. data/lib/arel_extensions/nodes/json.rb +28 -30
  22. data/lib/arel_extensions/nodes/power.rb +5 -4
  23. data/lib/arel_extensions/nodes/replace.rb +23 -5
  24. data/lib/arel_extensions/nodes/round.rb +5 -5
  25. data/lib/arel_extensions/nodes/soundex.rb +14 -13
  26. data/lib/arel_extensions/nodes/substring.rb +8 -15
  27. data/lib/arel_extensions/nodes/trim.rb +1 -1
  28. data/lib/arel_extensions/nodes/union.rb +0 -1
  29. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  30. data/lib/arel_extensions/predications.rb +16 -17
  31. data/lib/arel_extensions/string_functions.rb +12 -6
  32. data/lib/arel_extensions/tasks.rb +5 -5
  33. data/lib/arel_extensions/version.rb +1 -1
  34. data/lib/arel_extensions/visitors/mssql.rb +13 -12
  35. data/lib/arel_extensions/visitors/mysql.rb +50 -35
  36. data/lib/arel_extensions/visitors/oracle.rb +7 -6
  37. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  38. data/lib/arel_extensions/visitors/postgresql.rb +45 -27
  39. data/lib/arel_extensions/visitors/sqlite.rb +41 -27
  40. data/lib/arel_extensions/visitors/to_sql.rb +18 -5
  41. data/test/visitors/test_bulk_insert_oracle.rb +6 -6
  42. data/test/visitors/test_bulk_insert_sqlite.rb +5 -5
  43. data/test/visitors/test_to_sql.rb +10 -2
  44. data/test/with_ar/all_agnostic_test.rb +44 -33
  45. data/test/with_ar/test_bulk_sqlite.rb +1 -1
  46. data/test/with_ar/test_math_sqlite.rb +1 -1
  47. data/test/with_ar/test_string_mysql.rb +1 -3
  48. data/test/with_ar/test_string_sqlite.rb +1 -5
  49. data/version_v1.rb +3 -0
  50. data/version_v2.rb +3 -0
  51. metadata +9 -4
@@ -1,25 +1,25 @@
1
1
  module ArelExtensions
2
- module Nodes
3
- class FormattedNumber < Function
4
- RETURN_TYPE = :string
2
+ module Nodes
3
+ class FormattedNumber < Function
4
+ RETURN_TYPE = :string
5
5
 
6
- attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width,:precision, :type, :original_string
6
+ attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width,:precision, :type, :original_string
7
7
 
8
- def initialize expr
9
- # expr[1] = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
10
- col = expr.first
11
- @locale = expr[1][:locale]
12
- @prefix = expr[1][:prefix]
13
- @suffix = expr[1][:suffix]
14
- @width = expr[1][:width]
15
- @precision = expr[1][:precision]
16
- @type = expr[1][:type]
17
- @flags = expr[1][:flags]
18
- @scientific_notation = /[eE]/.match(expr[1][:type]) || false
19
- @original_string = expr[1][:original_string]
20
- super [col]
21
- end
8
+ def initialize expr
9
+ # expr[1] = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
10
+ col = expr.first
11
+ @locale = expr[1][:locale]
12
+ @prefix = expr[1][:prefix]
13
+ @suffix = expr[1][:suffix]
14
+ @width = expr[1][:width]
15
+ @precision = expr[1][:precision]
16
+ @type = expr[1][:type]
17
+ @flags = expr[1][:flags]
18
+ @scientific_notation = /[eE]/.match(expr[1][:type]) || false
19
+ @original_string = expr[1][:original_string]
20
+ super [col]
21
+ end
22
22
 
23
- end
24
- end
23
+ end
24
+ end
25
25
  end
@@ -18,7 +18,7 @@ module ArelExtensions
18
18
  JsonSet.new(self,key,value)
19
19
  end
20
20
 
21
- def group as_array = true, orders= nil
21
+ def group as_array = true, orders = nil
22
22
  JsonGroup.new(self,as_array, orders)
23
23
  end
24
24
 
@@ -31,33 +31,35 @@ module ArelExtensions
31
31
  class Json < JsonNode
32
32
 
33
33
  def initialize *expr
34
- if expr.length == 1
35
- case expr.first
36
- when JsonNode
37
- @dict = expr.first.dict
38
- when Array
39
- @dict = expr.first.map{|e|
40
- (e.is_a?(Array) || e.is_a?(Hash)) ? Json.new(e) : convert_to_node(e)
41
- }
42
- when Hash
43
- @dict = expr.first.inject({}){|acc,v|
44
- acc[convert_to_node(v[0])] = (v[1].is_a?(Array) || v[1].is_a?(Hash)) ? Json.new(v[1]) : convert_to_node(v[1])
45
- acc
46
- }
47
- when String, Numeric, TrueClass, FalseClass
48
- @dict = convert_to_node(expr.first)
49
- when NilClass
50
- @dict = Arel.sql('null')
51
- else
52
- if expr.first.is_a?(String) || (expr.first.is_a?(Arel::Attributes::Attribute) && type_of_attribute(expr.first) == :string) || (expr.first.return_type == :string)
53
- @dict = convert_to_node(expr.first)
34
+ @dict =
35
+ if expr.length == 1
36
+ case exp = expr.first
37
+ when JsonNode
38
+ exp.dict
39
+ when Array
40
+ exp.map{|e|
41
+ (e.is_a?(Array) || e.is_a?(Hash)) ? Json.new(e) : convert_to_node(e)
42
+ }
43
+ when Hash
44
+ exp.reduce({}){|acc,v|
45
+ acc[convert_to_node(v[0])] = (v[1].is_a?(Array) || v[1].is_a?(Hash)) ? Json.new(v[1]) : convert_to_node(v[1])
46
+ acc
47
+ }
48
+ when String, Numeric, TrueClass, FalseClass
49
+ convert_to_node(exp)
50
+ when NilClass
51
+ Arel.sql('null')
54
52
  else
55
- @dict = [convert_to_node(expr.first)]
53
+ if (exp.is_a?(Arel::Attributes::Attribute) && type_of_attribute(exp) == :string) \
54
+ || (exp.return_type == :string)
55
+ convert_to_node(exp)
56
+ else
57
+ [convert_to_node(exp)]
58
+ end
56
59
  end
60
+ else
61
+ expr.map{|e| (e.is_a?(Array) || e.is_a?(Hash)) ? Json.new(e) : convert_to_node(e) }
57
62
  end
58
- else
59
- @dict = expr.map{|e| (e.is_a?(Array) || e.is_a?(Hash)) ? Json.new(e) : convert_to_node(e) }
60
- end
61
63
  super
62
64
  end
63
65
 
@@ -73,11 +75,7 @@ module ArelExtensions
73
75
  @dict = as_array ? json : json.dict
74
76
  @as_array = as_array
75
77
  if orders
76
- if orders.is_a?(Array)
77
- @orders = orders
78
- else
79
- @orders = [orders]
80
- end
78
+ @orders = Array(orders)
81
79
  end
82
80
  end
83
81
  end
@@ -1,11 +1,12 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
3
  class Power < Function
4
- RETURN_TYPE = :number
4
+ RETURN_TYPE = :number
5
+
6
+ def initialize expr
7
+ super [convert_to_node(expr.first), convert_to_number(expr[1])]
8
+ end
5
9
 
6
- def initialize expr
7
- super [convert_to_node(expr.first), convert_to_number(expr[1])]
8
- end
9
10
  end
10
11
  end
11
12
  end
@@ -2,12 +2,13 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Replace < Function
4
4
  RETURN_TYPE = :string
5
+ attr_accessor :left, :pattern, :substitute
5
6
 
6
- def initialize expr
7
- tab = expr.map { |arg|
8
- convert_to_node(arg)
9
- }
10
- return super(tab)
7
+ def initialize left, pattern, substitute
8
+ @left = convert_to_node(left)
9
+ @pattern = convert_to_node(pattern)
10
+ @substitute = convert_to_node(substitute)
11
+ super([@left,@pattern,@substitute])
11
12
  end
12
13
 
13
14
  def +(other)
@@ -15,5 +16,22 @@ module ArelExtensions
15
16
  end
16
17
 
17
18
  end
19
+
20
+ class RegexpReplace < Function
21
+ RETURN_TYPE = :string
22
+ attr_accessor :left, :pattern, :substitute
23
+
24
+ def initialize left, pattern, substitute
25
+ @left = convert_to_node(left)
26
+ @pattern = (pattern.is_a?(Regexp) ? pattern : %r[#{pattern}])
27
+ @substitute = convert_to_node(substitute)
28
+ super([@left,@pattern,@substitute])
29
+ end
30
+
31
+ def +(other)
32
+ return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
33
+ end
34
+ end
35
+
18
36
  end
19
37
  end
@@ -4,11 +4,11 @@ module ArelExtensions
4
4
  RETURN_TYPE = :number
5
5
 
6
6
  def initialize expr
7
- if expr && expr.length == 1
8
- super [convert_to_node(expr.first)]
9
- else
10
- super [convert_to_node(expr.first), convert_to_number(expr[1])]
11
- end
7
+ if expr && expr.length == 1
8
+ super [convert_to_node(expr.first)]
9
+ else
10
+ super [convert_to_node(expr.first), convert_to_number(expr[1])]
11
+ end
12
12
  end
13
13
 
14
14
  end
@@ -1,18 +1,19 @@
1
1
  module ArelExtensions
2
- module Nodes
3
- class Soundex < Function
4
- include Arel::Expressions
5
- include ArelExtensions::Comparators
2
+ module Nodes
3
+ class Soundex < Function
4
+ include Arel::Expressions
5
+ include ArelExtensions::Comparators
6
6
 
7
- RETURN_TYPE = :string
7
+ RETURN_TYPE = :string
8
8
 
9
- def ==(other)
10
- Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
11
- end
9
+ def ==(other)
10
+ Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
11
+ end
12
12
 
13
- def !=(other)
14
- Arel::Nodes::NotEqual.new self, Arel::Nodes.build_quoted(other, self)
15
- end
16
- end
17
- end
13
+ def !=(other)
14
+ Arel::Nodes::NotEqual.new self, Arel::Nodes.build_quoted(other, self)
15
+ end
16
+
17
+ end
18
+ end
18
19
  end
@@ -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
@@ -17,7 +17,7 @@ module ArelExtensions
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
@@ -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,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
 
@@ -100,13 +100,21 @@ 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
@@ -114,7 +122,7 @@ module ArelExtensions
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, group: nil, order: nil)
125
+ def group_concat(sep = nil, *orders, group: nil, order: nil)
118
126
  if orders.present?
119
127
  warn("Warning : ArelExtensions: group_concat: you should now use the kwarg 'order' to specify an order in the group_concat.")
120
128
  end
@@ -123,8 +131,6 @@ module ArelExtensions
123
131
  o
124
132
  elsif o.respond_to?(:asc)
125
133
  o.asc
126
- else
127
- nil
128
134
  end
129
135
  }.compact
130
136
  ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order: (order || order_tabs))
@@ -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 = "1.2.5".freeze
2
+ VERSION = "1.2.8".freeze
3
3
  end
@@ -400,13 +400,14 @@ module ArelExtensions
400
400
  collector << "(STRING_AGG("
401
401
  collector = visit o.left, collector
402
402
  collector << Arel::Visitors::Oracle::COMMA
403
- if o.separator && o.selector != 'NULL'
404
- collector = visit o.separator, 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.order.blank?
410
+ if o.order.present?
410
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
@@ -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