arel_extensions 1.7.0 → 2.0.0.rc3
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 +4 -4
- data/.codeclimate.yml +2 -1
- data/.gitignore +6 -8
- data/.rubocop.yml +4 -194
- data/.travis/oracle/download.js +152 -0
- data/.travis/oracle/download.sh +30 -0
- data/.travis/oracle/download_ojdbc.js +116 -0
- data/.travis/oracle/install.sh +34 -0
- data/.travis/setup_accounts.sh +9 -0
- data/.travis/sqlite3/extension-functions.sh +6 -0
- data/.travis.yml +223 -0
- data/Gemfile +28 -2
- data/README.md +89 -265
- data/Rakefile +30 -50
- data/TODO +1 -0
- data/appveyor.yml +22 -60
- data/arel_extensions.gemspec +17 -14
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +20 -0
- data/gemfiles/rails4.gemfile +29 -0
- data/gemfiles/rails5_0.gemfile +29 -0
- data/gemfiles/rails5_1_4.gemfile +17 -19
- data/gemfiles/rails5_2.gemfile +17 -26
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/oracle.sql +0 -0
- data/init/postgresql.sql +25 -24
- data/init/sqlite.sql +0 -0
- data/lib/arel_extensions/attributes.rb +3 -9
- data/lib/arel_extensions/boolean_functions.rb +16 -57
- data/lib/arel_extensions/common_sql_functions.rb +20 -21
- data/lib/arel_extensions/comparators.rb +28 -31
- data/lib/arel_extensions/date_duration.rb +13 -19
- data/lib/arel_extensions/insert_manager.rb +15 -22
- data/lib/arel_extensions/math.rb +70 -68
- data/lib/arel_extensions/math_functions.rb +52 -57
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +5 -6
- data/lib/arel_extensions/nodes/case.rb +27 -31
- data/lib/arel_extensions/nodes/cast.rb +12 -12
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/coalesce.rb +5 -4
- data/lib/arel_extensions/nodes/collate.rb +10 -9
- data/lib/arel_extensions/nodes/concat.rb +22 -13
- data/lib/arel_extensions/nodes/date_diff.rb +70 -77
- data/lib/arel_extensions/nodes/duration.rb +5 -2
- data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
- data/lib/arel_extensions/nodes/floor.rb +1 -1
- data/lib/arel_extensions/nodes/format.rb +8 -35
- data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
- data/lib/arel_extensions/nodes/function.rb +39 -50
- data/lib/arel_extensions/nodes/is_null.rb +0 -2
- data/lib/arel_extensions/nodes/json.rb +47 -72
- data/lib/arel_extensions/nodes/length.rb +0 -5
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
- data/lib/arel_extensions/nodes/locate.rb +3 -2
- data/lib/arel_extensions/nodes/log10.rb +2 -1
- data/lib/arel_extensions/nodes/matches.rb +8 -6
- data/lib/arel_extensions/nodes/md5.rb +1 -0
- data/lib/arel_extensions/nodes/power.rb +5 -5
- data/lib/arel_extensions/nodes/rand.rb +3 -2
- data/lib/arel_extensions/nodes/repeat.rb +6 -4
- data/lib/arel_extensions/nodes/replace.rb +8 -16
- data/lib/arel_extensions/nodes/round.rb +7 -6
- data/lib/arel_extensions/nodes/soundex.rb +15 -15
- data/lib/arel_extensions/nodes/std.rb +21 -18
- data/lib/arel_extensions/nodes/substring.rb +16 -58
- data/lib/arel_extensions/nodes/then.rb +2 -2
- data/lib/arel_extensions/nodes/trim.rb +7 -5
- data/lib/arel_extensions/nodes/union.rb +9 -6
- data/lib/arel_extensions/nodes/union_all.rb +8 -5
- data/lib/arel_extensions/nodes/wday.rb +6 -2
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +6 -18
- data/lib/arel_extensions/predications.rb +49 -54
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +7 -5
- data/lib/arel_extensions/string_functions.rb +55 -110
- data/lib/arel_extensions/tasks.rb +6 -6
- data/lib/arel_extensions/version.rb +1 -3
- data/lib/arel_extensions/visitors/ibm_db.rb +36 -29
- data/lib/arel_extensions/visitors/mssql.rb +248 -493
- data/lib/arel_extensions/visitors/mysql.rb +244 -420
- data/lib/arel_extensions/visitors/oracle.rb +258 -311
- data/lib/arel_extensions/visitors/oracle12.rb +34 -20
- data/lib/arel_extensions/visitors/postgresql.rb +239 -350
- data/lib/arel_extensions/visitors/sqlite.rb +169 -191
- data/lib/arel_extensions/visitors/to_sql.rb +299 -371
- data/lib/arel_extensions/visitors.rb +62 -83
- data/lib/arel_extensions.rb +32 -243
- data/test/database.yml +10 -20
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +120 -123
- data/test/support/fake_record.rb +3 -11
- data/test/test_comparators.rb +17 -14
- data/test/visitors/test_bulk_insert_oracle.rb +12 -12
- data/test/visitors/test_bulk_insert_sqlite.rb +14 -13
- data/test/visitors/test_bulk_insert_to_sql.rb +13 -11
- data/test/visitors/test_oracle.rb +55 -55
- data/test/visitors/test_to_sql.rb +226 -419
- data/test/with_ar/all_agnostic_test.rb +375 -912
- data/test/with_ar/insert_agnostic_test.rb +22 -28
- data/test/with_ar/test_bulk_sqlite.rb +17 -18
- data/test/with_ar/test_math_sqlite.rb +27 -27
- data/test/with_ar/test_string_mysql.rb +34 -32
- data/test/with_ar/test_string_sqlite.rb +35 -31
- metadata +64 -50
- data/.github/workflows/publish.yml +0 -30
- data/.github/workflows/release.yml +0 -30
- data/.github/workflows/ruby.yml +0 -452
- data/CONTRIBUTING.md +0 -102
- data/Makefile +0 -48
- data/NEWS.md +0 -131
- data/bin/build +0 -15
- data/bin/publish +0 -8
- data/dev/arelx.dockerfile +0 -41
- data/dev/compose.yaml +0 -69
- data/dev/postgres.dockerfile +0 -5
- data/dev/rbenv +0 -189
- data/gemfiles/rails5.gemfile +0 -36
- data/gemfiles/rails6.gemfile +0 -40
- data/gemfiles/rails6_1.gemfile +0 -48
- data/gemfiles/rails7.gemfile +0 -48
- data/gemfiles/rails7_1.gemfile +0 -48
- data/gemfiles/rails7_2.gemfile +0 -47
- data/gemfiles/rails8.gemfile +0 -40
- data/gemfiles/rails8_1.gemfile +0 -41
- data/gemspecs/arel_extensions-v1.gemspec +0 -25
- data/gemspecs/arel_extensions-v2.gemspec +0 -25
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/aliases.rb +0 -14
- data/lib/arel_extensions/constants.rb +0 -13
- data/lib/arel_extensions/helpers.rb +0 -61
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/byte_size.rb +0 -11
- data/lib/arel_extensions/nodes/char_length.rb +0 -11
- data/lib/arel_extensions/nodes/formatted_date.rb +0 -42
- data/lib/arel_extensions/nodes/rollup.rb +0 -36
- data/lib/arel_extensions/nodes/select.rb +0 -10
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/lib/arel_extensions/warning.rb +0 -42
- data/test/arelx_test_helper.rb +0 -94
- data/test/config_loader.rb +0 -9
- data/version_v1.rb +0 -5
- data/version_v2.rb +0 -5
|
@@ -5,94 +5,62 @@ module ArelExtensions
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :dict
|
|
7
7
|
|
|
8
|
-
def merge
|
|
9
|
-
args = [self] + expr.map
|
|
8
|
+
def merge *expr
|
|
9
|
+
args = [self] + expr.map{|e| Json.new(e)}
|
|
10
10
|
JsonMerge.new(args)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def get
|
|
14
|
-
JsonGet.new(self,
|
|
13
|
+
def get key
|
|
14
|
+
JsonGet.new(self,key)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def set
|
|
18
|
-
JsonSet.new(self,
|
|
17
|
+
def set key, value
|
|
18
|
+
JsonSet.new(self,key,value)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def group
|
|
22
|
-
|
|
23
|
-
JsonGroup.new(Arel::Nodes::NamedFunction.new('DISTINCT', [self]), as_array, orders)
|
|
24
|
-
else
|
|
25
|
-
JsonGroup.new(self, as_array, orders)
|
|
26
|
-
end
|
|
21
|
+
def group as_array = true, orders= nil
|
|
22
|
+
JsonGroup.new(self,as_array, orders)
|
|
27
23
|
end
|
|
28
24
|
|
|
29
25
|
def hash
|
|
30
26
|
[@dict].hash
|
|
31
27
|
end
|
|
32
28
|
|
|
33
|
-
def convert_to_json_node(n)
|
|
34
|
-
case n
|
|
35
|
-
when JsonNode
|
|
36
|
-
n.dict
|
|
37
|
-
when Array
|
|
38
|
-
n.map { |e|
|
|
39
|
-
e.is_a?(Array) || e.is_a?(Hash) ? Json.new(e) : convert_to_json_node(e)
|
|
40
|
-
}
|
|
41
|
-
when Hash
|
|
42
|
-
n.reduce({}) { |acc, v|
|
|
43
|
-
acc[convert_to_json_node(v[0])] = v[1].is_a?(Array) || v[1].is_a?(Hash) ? Json.new(v[1]) : convert_to_json_node(v[1])
|
|
44
|
-
acc
|
|
45
|
-
}
|
|
46
|
-
when String, Numeric, TrueClass, FalseClass
|
|
47
|
-
convert_to_node(n)
|
|
48
|
-
when Date
|
|
49
|
-
convert_to_node(n.strftime('%Y-%m-%d'))
|
|
50
|
-
when DateTime, Time
|
|
51
|
-
convert_to_node(n.strftime('%Y-%m-%dT%H:%M:%S.%L%:z'))
|
|
52
|
-
when NilClass
|
|
53
|
-
Arel.null
|
|
54
|
-
when Arel::SelectManager
|
|
55
|
-
Arel.grouping(n)
|
|
56
|
-
else
|
|
57
|
-
convert_to_node(n)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# A boolean literal, either bare (TrueClass/FalseClass) or wrapped in a Quoted node
|
|
62
|
-
# (which is how `convert_to_node` represents one after construction).
|
|
63
|
-
def boolean_literal?(v)
|
|
64
|
-
v.is_a?(TrueClass) \
|
|
65
|
-
|| v.is_a?(FalseClass) \
|
|
66
|
-
|| (v.is_a?(Arel::Nodes::Quoted) && [true, false].include?(v.expr))
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def type_of_node(v)
|
|
70
|
-
if v.is_a?(Arel::Attributes::Attribute)
|
|
71
|
-
type_of_attribute(v)
|
|
72
|
-
elsif v.is_a?(Numeric)
|
|
73
|
-
:numeric
|
|
74
|
-
elsif boolean_literal?(v)
|
|
75
|
-
:boolean
|
|
76
|
-
elsif v.respond_to?(:return_type)
|
|
77
|
-
v.return_type
|
|
78
|
-
elsif v.nil?
|
|
79
|
-
:nil
|
|
80
|
-
else
|
|
81
|
-
:string
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
29
|
end
|
|
85
30
|
|
|
86
31
|
class Json < JsonNode
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
32
|
+
|
|
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')
|
|
91
51
|
else
|
|
92
|
-
expr.
|
|
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)
|
|
54
|
+
else
|
|
55
|
+
@dict = [convert_to_node(expr.first)]
|
|
56
|
+
end
|
|
93
57
|
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
|
|
94
61
|
super
|
|
95
62
|
end
|
|
63
|
+
|
|
96
64
|
end
|
|
97
65
|
|
|
98
66
|
class JsonMerge < JsonNode
|
|
@@ -101,11 +69,15 @@ module ArelExtensions
|
|
|
101
69
|
class JsonGroup < JsonNode
|
|
102
70
|
attr_accessor :as_array, :orders
|
|
103
71
|
|
|
104
|
-
def initialize
|
|
72
|
+
def initialize json, as_array = true, orders = nil
|
|
105
73
|
@dict = as_array ? json : json.dict
|
|
106
74
|
@as_array = as_array
|
|
107
75
|
if orders
|
|
108
|
-
|
|
76
|
+
if orders.is_a?(Array)
|
|
77
|
+
@orders = orders
|
|
78
|
+
else
|
|
79
|
+
@orders = [orders]
|
|
80
|
+
end
|
|
109
81
|
end
|
|
110
82
|
end
|
|
111
83
|
end
|
|
@@ -113,20 +85,23 @@ module ArelExtensions
|
|
|
113
85
|
class JsonGet < JsonNode
|
|
114
86
|
attr_accessor :key
|
|
115
87
|
|
|
116
|
-
def initialize
|
|
88
|
+
def initialize json, key
|
|
117
89
|
@dict = json
|
|
118
90
|
@key = convert_to_node(key)
|
|
119
91
|
end
|
|
92
|
+
|
|
120
93
|
end
|
|
121
94
|
|
|
122
95
|
class JsonSet < JsonNode
|
|
123
96
|
attr_accessor :key, :value
|
|
124
97
|
|
|
125
|
-
def initialize
|
|
98
|
+
def initialize json, key, value
|
|
126
99
|
@dict = json
|
|
127
100
|
@key = convert_to_node(key)
|
|
128
101
|
@value = Json.new(value)
|
|
129
102
|
end
|
|
103
|
+
|
|
130
104
|
end
|
|
105
|
+
|
|
131
106
|
end
|
|
132
107
|
end
|
|
@@ -3,8 +3,8 @@ module ArelExtensions
|
|
|
3
3
|
class LevenshteinDistance < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
super
|
|
6
|
+
def initialize expr
|
|
7
|
+
super [convert_to_node(expr.first), Arel::Nodes.build_quoted(expr[1])]
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class IMatches < Arel::Nodes::Matches
|
|
4
|
-
attr_accessor :case_sensitive if AREL_VERSION < V7
|
|
5
4
|
|
|
5
|
+
attr_accessor :case_sensitive if Arel::VERSION.to_i < 7
|
|
6
|
+
|
|
6
7
|
def initialize(left, right, escape = nil)
|
|
7
|
-
r = Arel.
|
|
8
|
-
if
|
|
8
|
+
r = Arel::Nodes.build_quoted(right)
|
|
9
|
+
if Arel::VERSION.to_i < 7 # managed by default in version 7+ (rails 5), so useful for rails 3 & 4
|
|
9
10
|
super(left, r, escape)
|
|
10
11
|
@case_sensitive = false
|
|
11
12
|
else
|
|
@@ -16,14 +17,15 @@ module ArelExtensions
|
|
|
16
17
|
|
|
17
18
|
class IDoesNotMatch < IMatches
|
|
18
19
|
end
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
class AiMatches < IMatches
|
|
21
22
|
end
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
class AiIMatches < IMatches
|
|
24
25
|
end
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
class SMatches < IMatches
|
|
27
28
|
end
|
|
29
|
+
|
|
28
30
|
end
|
|
29
31
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class Power < Function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
RETURN_TYPE = :number
|
|
5
|
+
|
|
6
|
+
def initialize expr
|
|
7
|
+
super [convert_to_node(expr.first), convert_to_number(expr[1])]
|
|
8
|
+
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -2,17 +2,19 @@ module ArelExtensions
|
|
|
2
2
|
module Nodes
|
|
3
3
|
class Repeat < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
|
-
|
|
6
|
-
def initialize
|
|
5
|
+
|
|
6
|
+
def initialize expr
|
|
7
7
|
tab = expr.map { |arg|
|
|
8
8
|
convert_to_node(arg)
|
|
9
9
|
}
|
|
10
|
-
super(tab)
|
|
10
|
+
return super(tab)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def +(other)
|
|
14
|
-
ArelExtensions::Nodes::Concat.new(expressions + [other])
|
|
14
|
+
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
|
15
15
|
end
|
|
16
|
+
|
|
16
17
|
end
|
|
18
|
+
|
|
17
19
|
end
|
|
18
20
|
end
|
|
@@ -2,26 +2,18 @@ module ArelExtensions
|
|
|
2
2
|
module Nodes
|
|
3
3
|
class Replace < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
|
-
attr_accessor :left, :pattern, :substitute
|
|
6
5
|
|
|
7
|
-
def initialize
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
super(
|
|
6
|
+
def initialize expr
|
|
7
|
+
tab = expr.map { |arg|
|
|
8
|
+
convert_to_node(arg)
|
|
9
|
+
}
|
|
10
|
+
return super(tab)
|
|
12
11
|
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class RegexpReplace < Function
|
|
16
|
-
RETURN_TYPE = :string
|
|
17
|
-
attr_accessor :left, :pattern, :substitute
|
|
18
12
|
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
@pattern = (pattern.is_a?(Regexp) ? pattern : /#{pattern}/)
|
|
22
|
-
@substitute = convert_to_node(substitute)
|
|
23
|
-
super([@left, @pattern, @substitute])
|
|
13
|
+
def +(other)
|
|
14
|
+
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
|
24
15
|
end
|
|
16
|
+
|
|
25
17
|
end
|
|
26
18
|
end
|
|
27
19
|
end
|
|
@@ -3,13 +3,14 @@ module ArelExtensions
|
|
|
3
3
|
class Round < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
12
12
|
end
|
|
13
|
+
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
module Nodes
|
|
3
|
+
class Soundex < Function
|
|
4
|
+
include Arel::Expressions
|
|
5
|
+
include ArelExtensions::Comparators
|
|
6
|
+
|
|
7
|
+
RETURN_TYPE = :string
|
|
8
|
+
|
|
9
|
+
def ==(other)
|
|
10
|
+
Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
|
|
11
|
+
end
|
|
6
12
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def !=(other)
|
|
14
|
-
Arel::Nodes::NotEqual.new self, Arel.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
|
+
end
|
|
17
|
+
end
|
|
18
18
|
end
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
|
-
class Std <
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
20
|
-
end
|
|
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
|
|
21
12
|
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
|
+
|
|
22
25
|
end
|
|
23
26
|
end
|
|
@@ -1,65 +1,23 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class Substring < Function
|
|
4
|
-
|
|
4
|
+
RETURN_TYPE = :string
|
|
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
|
|
5
20
|
|
|
6
|
-
def initialize(expr)
|
|
7
|
-
start = expr[1]
|
|
8
|
-
if start.is_a?(Range) && expr[2]
|
|
9
|
-
raise ArgumentError, 'cannot pass a length together with a Range start; the Range already determines the extracted length'
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
tab = [convert_to_node(expr[0]), start.is_a?(Range) ? start : convert_to_node(start)]
|
|
13
|
-
if expr[2]
|
|
14
|
-
tab << convert_to_node(expr[2])
|
|
15
|
-
end
|
|
16
|
-
super(tab)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def range?
|
|
20
|
-
expressions[1].is_a?(Range)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Builds the vendor-agnostic Arel node tree reproducing Ruby's
|
|
24
|
-
# `String#[Range]` semantics: endless/beginless ranges, negative
|
|
25
|
-
# "from the end" indices, `exclude_end?`, and Ruby's `nil`-vs-`""`
|
|
26
|
-
# distinction (out of range vs valid-but-empty).
|
|
27
|
-
#
|
|
28
|
-
# Only meaningful when `#range?` is true; visitors need to check
|
|
29
|
-
# that first, then `visit` the node this returns.
|
|
30
|
-
def range_substring_node
|
|
31
|
-
col = expressions[0]
|
|
32
|
-
range = expressions[1]
|
|
33
|
-
b = range.begin
|
|
34
|
-
e = range.end
|
|
35
|
-
n = col.char_length
|
|
36
|
-
|
|
37
|
-
b_idx =
|
|
38
|
-
if b.nil?
|
|
39
|
-
0
|
|
40
|
-
elsif b.negative?
|
|
41
|
-
n + b
|
|
42
|
-
else
|
|
43
|
-
b
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
e_idx =
|
|
47
|
-
if e.nil?
|
|
48
|
-
n
|
|
49
|
-
else
|
|
50
|
-
raw = e.negative? ? n + e : e
|
|
51
|
-
range.exclude_end? ? raw : raw + 1
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
e_idx_clamped = Arel.when(n < e_idx).then(n).else(e_idx)
|
|
55
|
-
|
|
56
|
-
cases = Arel.when(col.is_null).then(Arel.quoted(nil))
|
|
57
|
-
cases = cases.when(n < b_idx).then(Arel.quoted(nil))
|
|
58
|
-
cases = cases.when(b_idx < 0).then(Arel.quoted(nil)) if b.is_a?(Integer) && b.negative?
|
|
59
|
-
cases
|
|
60
|
-
.when(e_idx_clamped <= b_idx).then(Arel.quoted(''))
|
|
61
|
-
.else(Substring.new([col, b_idx + 1, e_idx_clamped - b_idx]))
|
|
62
|
-
end
|
|
63
21
|
end
|
|
64
22
|
end
|
|
65
23
|
end
|
|
@@ -2,25 +2,27 @@ module ArelExtensions
|
|
|
2
2
|
module Nodes
|
|
3
3
|
class Trim < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
|
-
|
|
6
|
-
def initialize
|
|
5
|
+
|
|
6
|
+
def initialize expr
|
|
7
7
|
tab = expr.map { |arg|
|
|
8
8
|
convert_to_node(arg)
|
|
9
9
|
}
|
|
10
|
-
super(tab)
|
|
10
|
+
return super(tab)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def +(other)
|
|
14
|
-
ArelExtensions::Nodes::Concat.new(expressions + [other])
|
|
14
|
+
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
|
15
15
|
end
|
|
16
|
+
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
class Ltrim < Trim
|
|
19
|
-
|
|
20
|
+
RETURN_TYPE = :string
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
class Rtrim < Trim
|
|
23
24
|
RETURN_TYPE = :string
|
|
24
25
|
end
|
|
26
|
+
|
|
25
27
|
end
|
|
26
28
|
end
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class Union < Arel::Nodes::Union
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
def initialize left,right
|
|
6
|
+
return super(left,right)
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def +(other)
|
|
9
|
-
ArelExtensions::Nodes::Union.new(self,
|
|
10
|
+
return ArelExtensions::Nodes::Union.new(self,other)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def union(other)
|
|
13
|
-
ArelExtensions::Nodes::UnionAll.new(self,
|
|
14
|
+
return ArelExtensions::Nodes::UnionAll.new(self,other)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
|
-
def as
|
|
17
|
-
Arel::Nodes::TableAlias.new Arel.
|
|
17
|
+
def as other
|
|
18
|
+
Arel::Nodes::TableAlias.new Arel::Nodes::Grouping.new(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
|
18
19
|
end
|
|
19
20
|
end
|
|
21
|
+
|
|
20
22
|
end
|
|
21
23
|
end
|
|
24
|
+
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class UnionAll < Arel::Nodes::UnionAll
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
def initialize left,right
|
|
6
|
+
return super(left,right)
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def union_all(other)
|
|
9
|
-
ArelExtensions::Nodes::UnionAll.new(self,
|
|
10
|
+
return ArelExtensions::Nodes::UnionAll.new(self,other)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
def as
|
|
13
|
-
Arel::Nodes::TableAlias.new Arel.
|
|
13
|
+
def as other
|
|
14
|
+
Arel::Nodes::TableAlias.new Arel::Nodes::Grouping.new(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
|
14
15
|
end
|
|
15
16
|
end
|
|
17
|
+
|
|
16
18
|
end
|
|
17
19
|
end
|
|
20
|
+
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class Wday < Function
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def initialize other, aliaz = nil
|
|
7
|
+
tab = Array.new
|
|
6
8
|
tab << other
|
|
7
9
|
super(tab, aliaz)
|
|
8
10
|
end
|
|
9
11
|
|
|
12
|
+
|
|
10
13
|
def date
|
|
11
14
|
@expressions.first
|
|
12
15
|
end
|
|
16
|
+
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
require 'arel_extensions/nodes/function'
|
|
2
|
-
|
|
2
|
+
|