arel_extensions 1.2.3 → 1.2.5

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 (53) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +10 -10
  3. data/Gemfile +2 -2
  4. data/README.md +10 -10
  5. data/appveyor.yml +1 -1
  6. data/functions.html +1 -1
  7. data/init/mssql.sql +4 -4
  8. data/init/mysql.sql +38 -38
  9. data/init/postgresql.sql +21 -21
  10. data/lib/arel_extensions.rb +17 -1
  11. data/lib/arel_extensions/common_sql_functions.rb +1 -1
  12. data/lib/arel_extensions/comparators.rb +4 -2
  13. data/lib/arel_extensions/math_functions.rb +9 -4
  14. data/lib/arel_extensions/nodes.rb +1 -1
  15. data/lib/arel_extensions/nodes/aggregate_function.rb +14 -0
  16. data/lib/arel_extensions/nodes/coalesce.rb +2 -2
  17. data/lib/arel_extensions/nodes/concat.rb +6 -13
  18. data/lib/arel_extensions/nodes/date_diff.rb +2 -2
  19. data/lib/arel_extensions/nodes/format.rb +8 -8
  20. data/lib/arel_extensions/nodes/formatted_number.rb +6 -6
  21. data/lib/arel_extensions/nodes/function.rb +2 -0
  22. data/lib/arel_extensions/nodes/matches.rb +4 -4
  23. data/lib/arel_extensions/nodes/power.rb +2 -2
  24. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  25. data/lib/arel_extensions/nodes/replace.rb +1 -1
  26. data/lib/arel_extensions/nodes/soundex.rb +4 -4
  27. data/lib/arel_extensions/nodes/std.rb +19 -21
  28. data/lib/arel_extensions/nodes/substring.rb +1 -1
  29. data/lib/arel_extensions/nodes/sum.rb +7 -0
  30. data/lib/arel_extensions/nodes/trim.rb +2 -2
  31. data/lib/arel_extensions/nodes/union.rb +2 -2
  32. data/lib/arel_extensions/null_functions.rb +2 -2
  33. data/lib/arel_extensions/string_functions.rb +10 -7
  34. data/lib/arel_extensions/version.rb +1 -1
  35. data/lib/arel_extensions/visitors/mssql.rb +4 -4
  36. data/lib/arel_extensions/visitors/mysql.rb +28 -4
  37. data/lib/arel_extensions/visitors/oracle.rb +4 -4
  38. data/lib/arel_extensions/visitors/postgresql.rb +34 -6
  39. data/lib/arel_extensions/visitors/to_sql.rb +29 -22
  40. data/test/helper.rb +1 -1
  41. data/test/real_db_test.rb +1 -1
  42. data/test/test_comparators.rb +1 -1
  43. data/test/visitors/test_bulk_insert_sqlite.rb +1 -1
  44. data/test/visitors/test_bulk_insert_to_sql.rb +7 -9
  45. data/test/visitors/test_oracle.rb +1 -0
  46. data/test/visitors/test_to_sql.rb +6 -0
  47. data/test/with_ar/all_agnostic_test.rb +14 -3
  48. data/test/with_ar/insert_agnostic_test.rb +2 -1
  49. data/test/with_ar/test_bulk_sqlite.rb +1 -1
  50. data/test/with_ar/test_math_sqlite.rb +2 -2
  51. data/test/with_ar/test_string_mysql.rb +3 -3
  52. data/test/with_ar/test_string_sqlite.rb +2 -2
  53. metadata +5 -4
@@ -7,6 +7,7 @@ require 'arel_extensions/nodes/formatted_number'
7
7
  require 'arel_extensions/nodes/log10'
8
8
  require 'arel_extensions/nodes/power'
9
9
  require 'arel_extensions/nodes/std'
10
+ require 'arel_extensions/nodes/sum'
10
11
 
11
12
  module ArelExtensions
12
13
  module MathFunctions
@@ -62,12 +63,16 @@ module ArelExtensions
62
63
  end
63
64
 
64
65
  # Aggregate Functions
65
- def std unbiased = true
66
- ArelExtensions::Nodes::Std.new [self,unbiased]
66
+ def std opts={unbiased: true}
67
+ ArelExtensions::Nodes::Std.new self, opts
67
68
  end
68
69
 
69
- def variance unbiased = true
70
- ArelExtensions::Nodes::Variance.new [self,unbiased]
70
+ def variance opts={unbiased: true}
71
+ ArelExtensions::Nodes::Variance.new self, opts
72
+ end
73
+
74
+ def sum opts={unbiased: true}
75
+ ArelExtensions::Nodes::Sum.new self, opts
71
76
  end
72
77
 
73
78
  #function that can be invoked to produce random numbers between 0 and 1
@@ -1,2 +1,2 @@
1
1
  require 'arel_extensions/nodes/function'
2
-
2
+ require 'arel_extensions/nodes/aggregate_function'
@@ -0,0 +1,14 @@
1
+ module ArelExtensions
2
+ module Nodes
3
+ class AggregateFunction < Function
4
+ attr_accessor :order, :group
5
+
6
+ def initialize node, **opts
7
+ @order = Array(opts[:order]).map{|e| convert_to_node(e)}
8
+ @group = Array(opts[:group]).map{|e| convert_to_node(e)}
9
+ super [node]
10
+ end
11
+ end
12
+
13
+ end
14
+ end
@@ -2,7 +2,7 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Coalesce < Function
4
4
  RETURN_TYPE = :string
5
-
5
+
6
6
  attr_accessor :left_node_type
7
7
 
8
8
  def return_type
@@ -20,7 +20,7 @@ module ArelExtensions
20
20
  @left_node_type = :number
21
21
  when ArelExtensions::Nodes::Coalesce, ArelExtensions::Nodes::Function
22
22
  @left_node_type = expr.first.respond_to?(:left_node_type) ? expr.first.left_node_type : nil
23
- when Arel::Nodes::Node, Arel::Attributes::Attribute
23
+ when Arel::Nodes::Node, Arel::Attributes::Attribute
24
24
  @left_node_type = type_of_attribute(expr.first)
25
25
  when Date
26
26
  @left_node_type = :ruby_date
@@ -40,21 +40,14 @@ module ArelExtensions::Nodes
40
40
 
41
41
  end
42
42
 
43
- class GroupConcat < Function
43
+ class GroupConcat < AggregateFunction
44
44
  RETURN_TYPE = :string
45
45
 
46
- attr_accessor :orders
47
-
48
- def initialize expr
49
- tab = expr.map { |arg|
50
- if arg.is_a?(Array)
51
- @orders = arg
52
- nil
53
- else
54
- convert_to_node(arg)
55
- end
56
- }.compact
57
- super(tab)
46
+ attr_accessor :separator
47
+
48
+ def initialize node, separator = ', ', **opts
49
+ @separator = convert_to_node(separator)
50
+ super node, opts
58
51
  end
59
52
 
60
53
  end
@@ -12,7 +12,7 @@ module ArelExtensions
12
12
  res = []
13
13
  col = expr.first
14
14
  case col
15
- when Arel::Nodes::Node, Arel::Attributes::Attribute
15
+ when Arel::Nodes::Node, Arel::Attributes::Attribute
16
16
  @left_node_type = type_of_attribute(col)
17
17
  when Date
18
18
  @left_node_type = :ruby_date
@@ -21,7 +21,7 @@ module ArelExtensions
21
21
  end
22
22
  res << ([:date, :ruby_date].include?(@left_node_type) ? convert_to_date_node(col) : convert_to_datetime_node(col))
23
23
  case expr[1]
24
- when Arel::Nodes::Node, Arel::Attributes::Attribute
24
+ when Arel::Nodes::Node, Arel::Attributes::Attribute
25
25
  @right_node_type = type_of_attribute(expr[1])
26
26
  when Date
27
27
  @right_node_type = :ruby_date
@@ -1,15 +1,15 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
- class Format < Function
3
+ class Format < Function
4
4
  RETURN_TYPE = :string
5
5
 
6
- attr_accessor :col_type, :iso_format
7
- def initialize expr
8
- col = expr.first
9
- @iso_format = expr[1]
10
- @col_type = type_of_attribute(col)
11
- super [col, convert_to_string_node(@iso_format)]
12
- end
6
+ attr_accessor :col_type, :iso_format
7
+ def initialize expr
8
+ col = expr.first
9
+ @iso_format = expr[1]
10
+ @col_type = type_of_attribute(col)
11
+ super [col, convert_to_string_node(@iso_format)]
12
+ end
13
13
  end
14
14
  end
15
15
  end
@@ -1,16 +1,16 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
- class FormattedNumber < Function
3
+ class FormattedNumber < Function
4
4
  RETURN_TYPE = :string
5
-
5
+
6
6
  attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width,:precision, :type, :original_string
7
-
7
+
8
8
  def initialize expr
9
9
  # expr[1] = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
10
10
  col = expr.first
11
11
  @locale = expr[1][:locale]
12
12
  @prefix = expr[1][:prefix]
13
- @suffix = expr[1][:suffix]
13
+ @suffix = expr[1][:suffix]
14
14
  @width = expr[1][:width]
15
15
  @precision = expr[1][:precision]
16
16
  @type = expr[1][:type]
@@ -19,7 +19,7 @@ module ArelExtensions
19
19
  @original_string = expr[1][:original_string]
20
20
  super [col]
21
21
  end
22
-
23
- end
22
+
23
+ end
24
24
  end
25
25
  end
@@ -71,6 +71,8 @@ module ArelExtensions
71
71
  Arel.sql('NULL')
72
72
  when ActiveSupport::Duration
73
73
  Arel.sql(object.to_i)
74
+ when Array
75
+ Arel::Nodes::Grouping.new(object.map{|r| convert_to_node(e)})
74
76
  else
75
77
  raise(ArgumentError, "#{object.class} can not be converted to CONCAT arg")
76
78
  end
@@ -3,7 +3,7 @@ module ArelExtensions
3
3
  class IMatches < Arel::Nodes::Matches
4
4
 
5
5
  attr_accessor :case_sensitive if Arel::VERSION.to_i < 7
6
-
6
+
7
7
  def initialize(left, right, escape = nil)
8
8
  r = Arel::Nodes.build_quoted(right)
9
9
  if Arel::VERSION.to_i < 7 # managed by default in version 7+ (rails 5), so useful for rails 3 & 4
@@ -17,13 +17,13 @@ module ArelExtensions
17
17
 
18
18
  class IDoesNotMatch < IMatches
19
19
  end
20
-
20
+
21
21
  class AiMatches < IMatches
22
22
  end
23
-
23
+
24
24
  class AiIMatches < IMatches
25
25
  end
26
-
26
+
27
27
  class SMatches < IMatches
28
28
  end
29
29
 
@@ -2,9 +2,9 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Power < Function
4
4
  RETURN_TYPE = :number
5
-
5
+
6
6
  def initialize expr
7
- super [convert_to_node(expr.first), convert_to_number(expr[1])]
7
+ super [convert_to_node(expr.first), convert_to_number(expr[1])]
8
8
  end
9
9
  end
10
10
  end
@@ -2,7 +2,7 @@ module ArelExtensions
2
2
  module Nodes
3
3
  class Repeat < 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,7 +11,7 @@ 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
@@ -11,7 +11,7 @@ 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
@@ -1,11 +1,11 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
- class Soundex < Function
3
+ class Soundex < Function
4
4
  include Arel::Expressions
5
- include ArelExtensions::Comparators
6
-
5
+ include ArelExtensions::Comparators
6
+
7
7
  RETURN_TYPE = :string
8
-
8
+
9
9
  def ==(other)
10
10
  Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
11
11
  end
@@ -1,26 +1,24 @@
1
1
  module ArelExtensions
2
2
  module Nodes
3
- class Std < Function
4
- RETURN_TYPE = :number
5
-
6
- attr_accessor :unbiased_estimator
7
- def initialize expr
8
- col = expr.first
9
- @unbiased_estimator = expr[1]
10
- super [col]
11
- end
3
+ class Std < AggregateFunction
4
+ RETURN_TYPE = :number
5
+ attr_accessor :unbiased_estimator
6
+
7
+ def initialize node, opts = {}
8
+ @unbiased_estimator = opts[:unbiased] ? true : false
9
+ super node, opts
10
+ end
12
11
  end
13
-
14
- class Variance < Function
15
- RETURN_TYPE = :number
16
-
17
- attr_accessor :unbiased_estimator
18
- def initialize expr
19
- col = expr.first
20
- @unbiased_estimator = expr[1]
21
- super [col]
22
- end
23
- end
24
-
12
+
13
+ class Variance < AggregateFunction
14
+ RETURN_TYPE = :number
15
+ attr_accessor :unbiased_estimator
16
+
17
+ def initialize node, opts = {}
18
+ @unbiased_estimator = opts[:unbiased] ? true : false
19
+ super node, opts
20
+ end
21
+ end
22
+
25
23
  end
26
24
  end
@@ -15,7 +15,7 @@ module ArelExtensions
15
15
 
16
16
  # def +(other)
17
17
  # puts "[Substring] : #{other.inspect} (#{self.expressions.inspect})"
18
- # return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
18
+ # return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
19
19
  # end
20
20
 
21
21
  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,7 +11,7 @@ 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
@@ -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
@@ -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
@@ -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
 
@@ -108,13 +108,16 @@ module ArelExtensions
108
108
  def replace left, right
109
109
  ArelExtensions::Nodes::Replace.new [self, left, right]
110
110
  end
111
-
111
+
112
112
  def concat other
113
113
  ArelExtensions::Nodes::Concat.new [self, other]
114
114
  end
115
115
 
116
116
  #concat elements of a group, separated by sep and ordered by a list of Ascending or Descending
117
- def group_concat sep = nil, *orders
117
+ def group_concat(sep= nil, *orders, group: nil, order: nil)
118
+ if orders.present?
119
+ warn("Warning : ArelExtensions: group_concat: you should now use the kwarg 'order' to specify an order in the group_concat.")
120
+ end
118
121
  order_tabs = [orders].flatten.map{ |o|
119
122
  if o.is_a?(Arel::Nodes::Ascending) || o.is_a?(Arel::Nodes::Descending)
120
123
  o
@@ -124,7 +127,7 @@ module ArelExtensions
124
127
  nil
125
128
  end
126
129
  }.compact
127
- ArelExtensions::Nodes::GroupConcat.new [self, sep, order_tabs]
130
+ ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order: (order || order_tabs))
128
131
  end
129
132
 
130
133
  #Function returns a string after removing left, right or the both prefixes or suffixes int argument
@@ -155,11 +158,11 @@ module ArelExtensions
155
158
  def not_blank
156
159
  ArelExtensions::Nodes::NotBlank.new [self]
157
160
  end
158
-
159
- def repeat other = 1
161
+
162
+ def repeat other = 1
160
163
  ArelExtensions::Nodes::Repeat.new [self, other]
161
164
  end
162
-
165
+
163
166
  def levenshtein_distance other
164
167
  ArelExtensions::Nodes::LevenshteinDistance.new [self, other]
165
168
  end
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "1.2.3".freeze
2
+ VERSION = "1.2.5".freeze
3
3
  end
@@ -400,14 +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.right && o.right != 'NULL'
404
- collector = visit o.right, collector
403
+ if o.separator && o.selector != 'NULL'
404
+ collector = visit o.separator, collector
405
405
  else
406
406
  collector = visit Arel::Nodes.build_quoted(','), collector
407
407
  end
408
408
  collector << ") WITHIN GROUP (ORDER BY "
409
- if !o.orders.blank?
410
- o.orders.each_with_index do |order,i|
409
+ if !o.order.blank?
410
+ o.order.each_with_index do |order,i|
411
411
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
412
412
  collector = visit order, collector
413
413
  end