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.
- checksums.yaml +5 -5
- data/.travis.yml +10 -10
- data/Gemfile +2 -2
- data/README.md +10 -10
- data/appveyor.yml +1 -1
- data/functions.html +1 -1
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/postgresql.sql +21 -21
- data/lib/arel_extensions.rb +17 -1
- data/lib/arel_extensions/common_sql_functions.rb +1 -1
- data/lib/arel_extensions/comparators.rb +4 -2
- data/lib/arel_extensions/math_functions.rb +9 -4
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/nodes/aggregate_function.rb +14 -0
- data/lib/arel_extensions/nodes/coalesce.rb +2 -2
- data/lib/arel_extensions/nodes/concat.rb +6 -13
- data/lib/arel_extensions/nodes/date_diff.rb +2 -2
- data/lib/arel_extensions/nodes/format.rb +8 -8
- data/lib/arel_extensions/nodes/formatted_number.rb +6 -6
- data/lib/arel_extensions/nodes/function.rb +2 -0
- data/lib/arel_extensions/nodes/matches.rb +4 -4
- data/lib/arel_extensions/nodes/power.rb +2 -2
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/replace.rb +1 -1
- data/lib/arel_extensions/nodes/soundex.rb +4 -4
- data/lib/arel_extensions/nodes/std.rb +19 -21
- data/lib/arel_extensions/nodes/substring.rb +1 -1
- data/lib/arel_extensions/nodes/sum.rb +7 -0
- data/lib/arel_extensions/nodes/trim.rb +2 -2
- data/lib/arel_extensions/nodes/union.rb +2 -2
- data/lib/arel_extensions/null_functions.rb +2 -2
- data/lib/arel_extensions/string_functions.rb +10 -7
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +4 -4
- data/lib/arel_extensions/visitors/mysql.rb +28 -4
- data/lib/arel_extensions/visitors/oracle.rb +4 -4
- data/lib/arel_extensions/visitors/postgresql.rb +34 -6
- data/lib/arel_extensions/visitors/to_sql.rb +29 -22
- data/test/helper.rb +1 -1
- data/test/real_db_test.rb +1 -1
- data/test/test_comparators.rb +1 -1
- data/test/visitors/test_bulk_insert_sqlite.rb +1 -1
- data/test/visitors/test_bulk_insert_to_sql.rb +7 -9
- data/test/visitors/test_oracle.rb +1 -0
- data/test/visitors/test_to_sql.rb +6 -0
- data/test/with_ar/all_agnostic_test.rb +14 -3
- data/test/with_ar/insert_agnostic_test.rb +2 -1
- data/test/with_ar/test_bulk_sqlite.rb +1 -1
- data/test/with_ar/test_math_sqlite.rb +2 -2
- data/test/with_ar/test_string_mysql.rb +3 -3
- data/test/with_ar/test_string_sqlite.rb +2 -2
- 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
|
66
|
-
ArelExtensions::Nodes::Std.new
|
66
|
+
def std opts={unbiased: true}
|
67
|
+
ArelExtensions::Nodes::Std.new self, opts
|
67
68
|
end
|
68
69
|
|
69
|
-
def variance unbiased
|
70
|
-
ArelExtensions::Nodes::Variance.new
|
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 <
|
43
|
+
class GroupConcat < AggregateFunction
|
44
44
|
RETURN_TYPE = :string
|
45
45
|
|
46
|
-
attr_accessor :
|
47
|
-
|
48
|
-
def initialize
|
49
|
-
|
50
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
@@ -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 <
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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 <
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
@@ -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
|
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
|
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
|
@@ -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.
|
404
|
-
collector = visit o.
|
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.
|
410
|
-
o.
|
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
|