arel_extensions 2.3.3 → 2.5.0
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/.github/workflows/ruby.yml +92 -43
- data/.gitignore +2 -1
- data/.rubocop.yml +131 -5
- data/Makefile +48 -0
- data/NEWS.md +22 -0
- data/README.md +32 -5
- data/Rakefile +5 -3
- data/arel_extensions.gemspec +3 -5
- data/dev/arelx.dockerfile +13 -16
- data/dev/compose.yaml +26 -28
- data/gemfiles/rails5.gemfile +15 -8
- data/gemfiles/rails5_1_4.gemfile +11 -9
- data/gemfiles/rails5_2.gemfile +16 -9
- data/gemfiles/rails6.gemfile +13 -7
- data/gemfiles/rails6_1.gemfile +13 -7
- data/gemfiles/rails7.gemfile +15 -9
- data/gemfiles/rails7_1.gemfile +15 -8
- data/gemfiles/rails7_2.gemfile +12 -6
- data/gemfiles/rails8.gemfile +40 -0
- data/gemfiles/rails8_1.gemfile +41 -0
- data/gemspecs/arel_extensions-v1.gemspec +3 -5
- data/gemspecs/arel_extensions-v2.gemspec +3 -5
- data/lib/arel_extensions/aliases.rb +3 -3
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/boolean_functions.rb +9 -7
- data/lib/arel_extensions/common_sql_functions.rb +5 -3
- data/lib/arel_extensions/comparators.rb +6 -4
- data/lib/arel_extensions/constants.rb +13 -0
- data/lib/arel_extensions/date_duration.rb +2 -0
- data/lib/arel_extensions/helpers.rb +18 -19
- data/lib/arel_extensions/insert_manager.rb +5 -1
- data/lib/arel_extensions/math.rb +40 -44
- data/lib/arel_extensions/math_functions.rb +29 -31
- data/lib/arel_extensions/nodes/aggregate_function.rb +4 -4
- data/lib/arel_extensions/nodes/blank.rb +6 -4
- data/lib/arel_extensions/nodes/byte_size.rb +11 -0
- data/lib/arel_extensions/nodes/case.rb +16 -13
- data/lib/arel_extensions/nodes/cast.rb +3 -5
- data/lib/arel_extensions/nodes/char_length.rb +11 -0
- data/lib/arel_extensions/nodes/coalesce.rb +1 -1
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/concat.rb +6 -6
- data/lib/arel_extensions/nodes/date_diff.rb +40 -49
- data/lib/arel_extensions/nodes/duration.rb +2 -2
- data/lib/arel_extensions/nodes/format.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_date.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_number.rb +2 -2
- data/lib/arel_extensions/nodes/function.rb +7 -7
- data/lib/arel_extensions/nodes/is_null.rb +2 -0
- data/lib/arel_extensions/nodes/json.rb +27 -15
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
- data/lib/arel_extensions/nodes/locate.rb +1 -1
- data/lib/arel_extensions/nodes/matches.rb +2 -2
- data/lib/arel_extensions/nodes/power.rb +2 -2
- data/lib/arel_extensions/nodes/rand.rb +2 -2
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/replace.rb +3 -3
- data/lib/arel_extensions/nodes/rollup.rb +4 -4
- data/lib/arel_extensions/nodes/round.rb +3 -3
- data/lib/arel_extensions/nodes/select.rb +1 -1
- data/lib/arel_extensions/nodes/std.rb +4 -4
- data/lib/arel_extensions/nodes/substring.rb +52 -2
- data/lib/arel_extensions/nodes/then.rb +1 -1
- data/lib/arel_extensions/nodes/trim.rb +2 -2
- data/lib/arel_extensions/nodes/union.rb +3 -3
- data/lib/arel_extensions/nodes/union_all.rb +3 -3
- data/lib/arel_extensions/nodes/wday.rb +2 -2
- data/lib/arel_extensions/null_functions.rb +5 -7
- data/lib/arel_extensions/predications.rb +23 -19
- data/lib/arel_extensions/string_functions.rb +37 -28
- data/lib/arel_extensions/version.rb +3 -1
- data/lib/arel_extensions/visitors/convert_format.rb +2 -2
- data/lib/arel_extensions/visitors/ibm_db.rb +5 -5
- data/lib/arel_extensions/visitors/mssql.rb +111 -97
- data/lib/arel_extensions/visitors/mysql.rb +101 -67
- data/lib/arel_extensions/visitors/oracle.rb +113 -103
- data/lib/arel_extensions/visitors/oracle12.rb +5 -6
- data/lib/arel_extensions/visitors/postgresql.rb +119 -92
- data/lib/arel_extensions/visitors/sqlite.rb +72 -64
- data/lib/arel_extensions/visitors/to_sql.rb +85 -75
- data/lib/arel_extensions/visitors.rb +7 -7
- data/lib/arel_extensions/warning.rb +5 -5
- data/lib/arel_extensions.rb +47 -31
- data/test/arelx_test_helper.rb +8 -6
- data/test/config_loader.rb +9 -0
- data/test/database.yml +8 -6
- data/test/real_db_test.rb +33 -33
- data/test/support/fake_record.rb +3 -1
- data/test/visitors/test_bulk_insert_oracle.rb +2 -2
- data/test/visitors/test_bulk_insert_sqlite.rb +2 -2
- data/test/visitors/test_to_sql.rb +2 -2
- data/test/with_ar/all_agnostic_test.rb +214 -32
- data/test/with_ar/insert_agnostic_test.rb +2 -2
- data/test/with_ar/test_bulk_sqlite.rb +2 -2
- data/test/with_ar/test_math_sqlite.rb +2 -2
- data/test/with_ar/test_string_mysql.rb +2 -2
- data/test/with_ar/test_string_sqlite.rb +2 -2
- data/version_v1.rb +3 -1
- data/version_v2.rb +3 -1
- metadata +9 -33
- data/bin/compose +0 -6
- data/gemfiles/rails3.gemfile +0 -20
- data/gemfiles/rails4_2.gemfile +0 -38
|
@@ -2,7 +2,7 @@ module ArelExtensions::Nodes
|
|
|
2
2
|
class Concat < Function
|
|
3
3
|
RETURN_TYPE = :string
|
|
4
4
|
|
|
5
|
-
def initialize
|
|
5
|
+
def initialize(expr)
|
|
6
6
|
tab = expr.map { |arg|
|
|
7
7
|
# flatten nested concats.
|
|
8
8
|
node = convert_to_node(arg)
|
|
@@ -25,8 +25,8 @@ module ArelExtensions::Nodes
|
|
|
25
25
|
super(tab)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def self.new
|
|
29
|
-
o = super
|
|
28
|
+
def self.new(expr)
|
|
29
|
+
o = super
|
|
30
30
|
if o.expressions.length == 1
|
|
31
31
|
o.expressions[0]
|
|
32
32
|
else
|
|
@@ -35,7 +35,7 @@ module ArelExtensions::Nodes
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def concat(other)
|
|
38
|
-
Concat.new(
|
|
38
|
+
Concat.new(expressions + [other])
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
@@ -44,9 +44,9 @@ module ArelExtensions::Nodes
|
|
|
44
44
|
|
|
45
45
|
attr_accessor :separator
|
|
46
46
|
|
|
47
|
-
def initialize
|
|
47
|
+
def initialize(node, separator = ', ', **opts)
|
|
48
48
|
@separator = convert_to_node(separator)
|
|
49
|
-
super
|
|
49
|
+
super(node, **opts)
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
end
|
|
@@ -3,8 +3,7 @@ require 'date'
|
|
|
3
3
|
module ArelExtensions
|
|
4
4
|
module Nodes
|
|
5
5
|
class DateDiff < Function # difference entre colonne date et date string/date
|
|
6
|
-
attr_accessor :left_node_type
|
|
7
|
-
attr_accessor :right_node_type
|
|
6
|
+
attr_accessor :left_node_type, :right_node_type
|
|
8
7
|
|
|
9
8
|
RETURN_TYPE = :integer # by default...
|
|
10
9
|
|
|
@@ -29,7 +28,7 @@ module ArelExtensions
|
|
|
29
28
|
@right_node_type = :ruby_time
|
|
30
29
|
end
|
|
31
30
|
res << (%i[date ruby_date].include?(@left_node_type) ? convert_to_date_node(expr[1]) : convert_to_datetime_node(expr[1]))
|
|
32
|
-
super
|
|
31
|
+
super(res)
|
|
33
32
|
end
|
|
34
33
|
end
|
|
35
34
|
|
|
@@ -37,7 +36,7 @@ module ArelExtensions
|
|
|
37
36
|
RETURN_TYPE = :date
|
|
38
37
|
attr_accessor :date_type
|
|
39
38
|
|
|
40
|
-
def initialize
|
|
39
|
+
def initialize(expr)
|
|
41
40
|
col = expr.first
|
|
42
41
|
@date_type = type_of_attribute(col)
|
|
43
42
|
tab = expr.map do |arg|
|
|
@@ -47,8 +46,8 @@ module ArelExtensions
|
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
def sqlite_value
|
|
50
|
-
v =
|
|
51
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
49
|
+
v = expressions.last
|
|
50
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
52
51
|
if @date_type == :date
|
|
53
52
|
Arel.quoted((v.value >= 0 ? '+' : '-') + v.inspect)
|
|
54
53
|
elsif @date_type == :datetime
|
|
@@ -60,60 +59,54 @@ module ArelExtensions
|
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
def mysql_value(v = nil)
|
|
63
|
-
v ||=
|
|
64
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
62
|
+
v ||= expressions.last
|
|
63
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
65
64
|
if @date_type == :date || @date_type == :datetime
|
|
66
65
|
Arel.sql('INTERVAL %s' % v.inspect.sub(/s\Z/, ''))
|
|
67
66
|
end
|
|
67
|
+
elsif v.is_a?(ArelExtensions::Nodes::Duration)
|
|
68
|
+
v.with_interval = true
|
|
69
|
+
v
|
|
68
70
|
else
|
|
69
|
-
|
|
70
|
-
v.with_interval = true
|
|
71
|
-
v
|
|
72
|
-
else
|
|
73
|
-
v
|
|
74
|
-
end
|
|
71
|
+
v
|
|
75
72
|
end
|
|
76
73
|
end
|
|
77
74
|
|
|
78
75
|
def postgresql_value(v = nil)
|
|
79
|
-
v ||=
|
|
80
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
76
|
+
v ||= expressions.last
|
|
77
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
81
78
|
if @date_type == :date
|
|
82
79
|
Arel.sql("INTERVAL '%s'" % v.inspect.sub(/s\Z/, '').upcase)
|
|
83
80
|
elsif @date_type == :datetime
|
|
84
81
|
Arel.sql("INTERVAL '%s'" % v.inspect.sub(/s\Z/, '').upcase)
|
|
85
82
|
end
|
|
83
|
+
elsif v.is_a?(ArelExtensions::Nodes::Duration)
|
|
84
|
+
v.with_interval = true
|
|
85
|
+
v
|
|
86
86
|
else
|
|
87
|
-
|
|
88
|
-
v.with_interval = true
|
|
89
|
-
v
|
|
90
|
-
else
|
|
91
|
-
v
|
|
92
|
-
end
|
|
87
|
+
v
|
|
93
88
|
end
|
|
94
89
|
end
|
|
95
90
|
|
|
96
91
|
def oracle_value(v = nil)
|
|
97
|
-
v ||=
|
|
98
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
92
|
+
v ||= expressions.last
|
|
93
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
99
94
|
if @date_type == :ruby_date
|
|
100
95
|
Arel.sql("(INTERVAL '1' DAY) * %s" % v.inspect.to_i)
|
|
101
96
|
else
|
|
102
97
|
Arel.sql("(INTERVAL '1' SECOND) * %s" % v.to_i)
|
|
103
98
|
end
|
|
99
|
+
elsif v.is_a?(ArelExtensions::Nodes::Duration)
|
|
100
|
+
v.with_interval = true
|
|
101
|
+
v
|
|
104
102
|
else
|
|
105
|
-
|
|
106
|
-
v.with_interval = true
|
|
107
|
-
v
|
|
108
|
-
else
|
|
109
|
-
v
|
|
110
|
-
end
|
|
103
|
+
v
|
|
111
104
|
end
|
|
112
105
|
end
|
|
113
106
|
|
|
114
107
|
def mssql_value(v = nil)
|
|
115
|
-
v ||=
|
|
116
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
108
|
+
v ||= expressions.last
|
|
109
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
117
110
|
if @date_type == :date
|
|
118
111
|
v.to_i / (24 * 3600)
|
|
119
112
|
elsif @date_type == :datetime
|
|
@@ -134,8 +127,8 @@ module ArelExtensions
|
|
|
134
127
|
end
|
|
135
128
|
|
|
136
129
|
def mssql_datepart(v = nil)
|
|
137
|
-
v ||=
|
|
138
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
130
|
+
v ||= expressions.last
|
|
131
|
+
if defined?(ActiveSupport::Duration) && v.is_a?(ActiveSupport::Duration)
|
|
139
132
|
if @date_type == :date
|
|
140
133
|
Arel.sql('day')
|
|
141
134
|
elsif @date_type == :datetime
|
|
@@ -151,19 +144,17 @@ module ArelExtensions
|
|
|
151
144
|
end
|
|
152
145
|
Arel.sql(res)
|
|
153
146
|
end
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Arel.sql(ArelExtensions::Visitors::MSSQL::LOADED_VISITOR::DATE_MAPPING[v.left])
|
|
166
|
-
end
|
|
147
|
+
elsif v.is_a?(ArelExtensions::Nodes::Duration)
|
|
148
|
+
v.with_interval = true
|
|
149
|
+
case v.left
|
|
150
|
+
when 'd', 'm', 'y'
|
|
151
|
+
Arel.sql('day')
|
|
152
|
+
when 'h', 'mn', 's'
|
|
153
|
+
Arel.sql('second')
|
|
154
|
+
when /i\z/
|
|
155
|
+
Arel.sql(ArelExtensions::Visitors::MSSQL::LOADED_VISITOR::DATE_MAPPING[v.left[0..-2]])
|
|
156
|
+
else
|
|
157
|
+
Arel.sql(ArelExtensions::Visitors::MSSQL::LOADED_VISITOR::DATE_MAPPING[v.left])
|
|
167
158
|
end
|
|
168
159
|
end
|
|
169
160
|
end
|
|
@@ -190,7 +181,7 @@ module ArelExtensions
|
|
|
190
181
|
RETURN_TYPE = :integer
|
|
191
182
|
|
|
192
183
|
def initialize(expr)
|
|
193
|
-
super
|
|
184
|
+
super([expr.first, convert_number(expr[1])])
|
|
194
185
|
end
|
|
195
186
|
|
|
196
187
|
def convert_number(object)
|
|
@@ -200,7 +191,7 @@ module ArelExtensions
|
|
|
200
191
|
when String
|
|
201
192
|
object.to_i
|
|
202
193
|
else
|
|
203
|
-
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration
|
|
194
|
+
if defined?(ActiveSupport::Duration) && object.is_a?(ActiveSupport::Duration)
|
|
204
195
|
object.to_i
|
|
205
196
|
else
|
|
206
197
|
raise(ArgumentError, "#{object.class} cannot be converted to Number")
|
|
@@ -7,12 +7,12 @@ module ArelExtensions
|
|
|
7
7
|
|
|
8
8
|
attr_accessor :col_type, :iso_format, :time_zone
|
|
9
9
|
|
|
10
|
-
def initialize
|
|
10
|
+
def initialize(expr)
|
|
11
11
|
col = expr[0]
|
|
12
12
|
@iso_format = convert_format(expr[1])
|
|
13
13
|
@time_zone = expr[2]
|
|
14
14
|
@col_type = type_of_attribute(col)
|
|
15
|
-
super
|
|
15
|
+
super([col, convert_to_string_node(@iso_format)])
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
private
|
|
@@ -7,12 +7,12 @@ module ArelExtensions
|
|
|
7
7
|
|
|
8
8
|
attr_accessor :col_type, :iso_format, :time_zone
|
|
9
9
|
|
|
10
|
-
def initialize
|
|
10
|
+
def initialize(expr)
|
|
11
11
|
col = expr[0]
|
|
12
12
|
@iso_format = convert_format(expr[1])
|
|
13
13
|
@time_zone = expr[2]
|
|
14
14
|
@col_type = type_of_attribute(col)
|
|
15
|
-
super
|
|
15
|
+
super([col, convert_to_string_node(@iso_format)])
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
private
|
|
@@ -5,7 +5,7 @@ module ArelExtensions
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width, :precision, :type, :original_string
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
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]
|
|
@@ -17,7 +17,7 @@ module ArelExtensions
|
|
|
17
17
|
@flags = expr[1][:flags]
|
|
18
18
|
@scientific_notation = /[eE]/.match(expr[1][:type]) || false
|
|
19
19
|
@original_string = expr[1][:original_string]
|
|
20
|
-
super
|
|
20
|
+
super([col])
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -26,11 +26,9 @@ module ArelExtensions
|
|
|
26
26
|
self.class.const_get(:RETURN_TYPE)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def as
|
|
30
|
-
res = Arel::Nodes::As.new(
|
|
31
|
-
|
|
32
|
-
self.alias = Arel.sql(other)
|
|
33
|
-
end
|
|
29
|
+
def as(other)
|
|
30
|
+
res = Arel::Nodes::As.new(clone, Arel.sql(other))
|
|
31
|
+
self.alias = Arel.sql(other)
|
|
34
32
|
res
|
|
35
33
|
end
|
|
36
34
|
|
|
@@ -75,6 +73,8 @@ module ArelExtensions
|
|
|
75
73
|
Arel.quoted(object.strftime('%H:%M:%S'), self)
|
|
76
74
|
when MBSTRING, String, Symbol
|
|
77
75
|
Arel.quoted(object.to_s)
|
|
76
|
+
when TrueClass, FalseClass
|
|
77
|
+
Arel.quoted(object)
|
|
78
78
|
when Date
|
|
79
79
|
Arel.quoted(object.to_s, self)
|
|
80
80
|
when NilClass
|
|
@@ -82,7 +82,7 @@ module ArelExtensions
|
|
|
82
82
|
when ActiveSupport::Duration
|
|
83
83
|
Arel.sql(object.to_i)
|
|
84
84
|
when Array
|
|
85
|
-
Arel.grouping(object.map{|e| convert_to_node(e)})
|
|
85
|
+
Arel.grouping(object.map { |e| convert_to_node(e) })
|
|
86
86
|
else
|
|
87
87
|
raise(ArgumentError, "#{object.class} cannot be converted to CONCAT arg")
|
|
88
88
|
end
|
|
@@ -95,7 +95,7 @@ module ArelExtensions
|
|
|
95
95
|
when Integer
|
|
96
96
|
Arel.quoted(object.to_s)
|
|
97
97
|
when Arel::Attributes::Attribute
|
|
98
|
-
case
|
|
98
|
+
case type_of_attribute(object)
|
|
99
99
|
when :date
|
|
100
100
|
ArelExtensions::Nodes::Format.new [object, 'yyyy-mm-dd']
|
|
101
101
|
when :time
|
|
@@ -4,11 +4,13 @@ module ArelExtensions
|
|
|
4
4
|
module Nodes
|
|
5
5
|
class IsNull < Arel::Nodes::Unary
|
|
6
6
|
include ArelExtensions::BooleanFunctions
|
|
7
|
+
|
|
7
8
|
RETURN_TYPE = :boolean
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
class IsNotNull < Arel::Nodes::Unary
|
|
11
12
|
include ArelExtensions::BooleanFunctions
|
|
13
|
+
|
|
12
14
|
RETURN_TYPE = :boolean
|
|
13
15
|
end
|
|
14
16
|
end
|
|
@@ -5,20 +5,20 @@ module ArelExtensions
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :dict
|
|
7
7
|
|
|
8
|
-
def merge
|
|
9
|
-
args = [self] + expr.map{|e| Json.new(e)}
|
|
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
|
|
13
|
+
def get(key)
|
|
14
14
|
JsonGet.new(self, key)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def set
|
|
17
|
+
def set(key, value)
|
|
18
18
|
JsonSet.new(self, key, value)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def group
|
|
21
|
+
def group(as_array = true, orders = nil, distinct: false)
|
|
22
22
|
if distinct
|
|
23
23
|
JsonGroup.new(Arel::Nodes::NamedFunction.new('DISTINCT', [self]), as_array, orders)
|
|
24
24
|
else
|
|
@@ -35,12 +35,12 @@ module ArelExtensions
|
|
|
35
35
|
when JsonNode
|
|
36
36
|
n.dict
|
|
37
37
|
when Array
|
|
38
|
-
n.map{|e|
|
|
39
|
-
|
|
38
|
+
n.map { |e|
|
|
39
|
+
e.is_a?(Array) || e.is_a?(Hash) ? Json.new(e) : convert_to_json_node(e)
|
|
40
40
|
}
|
|
41
41
|
when Hash
|
|
42
|
-
n.reduce({}){|acc, v|
|
|
43
|
-
acc[convert_to_json_node(v[0])] =
|
|
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
44
|
acc
|
|
45
45
|
}
|
|
46
46
|
when String, Numeric, TrueClass, FalseClass
|
|
@@ -58,9 +58,21 @@ module ArelExtensions
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
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
|
+
|
|
61
69
|
def type_of_node(v)
|
|
62
70
|
if v.is_a?(Arel::Attributes::Attribute)
|
|
63
|
-
|
|
71
|
+
type_of_attribute(v)
|
|
72
|
+
elsif v.is_a?(Numeric)
|
|
73
|
+
:numeric
|
|
74
|
+
elsif boolean_literal?(v)
|
|
75
|
+
:boolean
|
|
64
76
|
elsif v.respond_to?(:return_type)
|
|
65
77
|
v.return_type
|
|
66
78
|
elsif v.nil?
|
|
@@ -72,12 +84,12 @@ module ArelExtensions
|
|
|
72
84
|
end
|
|
73
85
|
|
|
74
86
|
class Json < JsonNode
|
|
75
|
-
def initialize
|
|
87
|
+
def initialize(*expr)
|
|
76
88
|
@dict =
|
|
77
89
|
if expr.length == 1
|
|
78
90
|
convert_to_json_node(expr.first)
|
|
79
91
|
else
|
|
80
|
-
expr.map{|e| convert_to_json_node(e) }
|
|
92
|
+
expr.map { |e| convert_to_json_node(e) }
|
|
81
93
|
end
|
|
82
94
|
super
|
|
83
95
|
end
|
|
@@ -89,7 +101,7 @@ module ArelExtensions
|
|
|
89
101
|
class JsonGroup < JsonNode
|
|
90
102
|
attr_accessor :as_array, :orders
|
|
91
103
|
|
|
92
|
-
def initialize
|
|
104
|
+
def initialize(json, as_array = true, orders = nil)
|
|
93
105
|
@dict = as_array ? json : json.dict
|
|
94
106
|
@as_array = as_array
|
|
95
107
|
if orders
|
|
@@ -101,7 +113,7 @@ module ArelExtensions
|
|
|
101
113
|
class JsonGet < JsonNode
|
|
102
114
|
attr_accessor :key
|
|
103
115
|
|
|
104
|
-
def initialize
|
|
116
|
+
def initialize(json, key)
|
|
105
117
|
@dict = json
|
|
106
118
|
@key = convert_to_node(key)
|
|
107
119
|
end
|
|
@@ -110,7 +122,7 @@ module ArelExtensions
|
|
|
110
122
|
class JsonSet < JsonNode
|
|
111
123
|
attr_accessor :key, :value
|
|
112
124
|
|
|
113
|
-
def initialize
|
|
125
|
+
def initialize(json, key, value)
|
|
114
126
|
@dict = json
|
|
115
127
|
@key = convert_to_node(key)
|
|
116
128
|
@value = Json.new(value)
|
|
@@ -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.quoted(expr[1])])
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class IMatches < Arel::Nodes::Matches
|
|
4
|
-
attr_accessor :case_sensitive if
|
|
4
|
+
attr_accessor :case_sensitive if AREL_VERSION < V7
|
|
5
5
|
|
|
6
6
|
def initialize(left, right, escape = nil)
|
|
7
7
|
r = Arel.quoted(right)
|
|
8
|
-
if
|
|
8
|
+
if AREL_VERSION < V7 # managed by default in version 7+ (rails 5), so useful for rails 3 & 4
|
|
9
9
|
super(left, r, escape)
|
|
10
10
|
@case_sensitive = false
|
|
11
11
|
else
|
|
@@ -3,8 +3,8 @@ module ArelExtensions
|
|
|
3
3
|
class Power < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
super
|
|
6
|
+
def initialize(expr)
|
|
7
|
+
super([convert_to_node(expr.first), convert_to_number(expr[1])])
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -3,7 +3,7 @@ module ArelExtensions
|
|
|
3
3
|
class Repeat < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
6
|
+
def initialize(expr)
|
|
7
7
|
tab = expr.map { |arg|
|
|
8
8
|
convert_to_node(arg)
|
|
9
9
|
}
|
|
@@ -11,7 +11,7 @@ module ArelExtensions
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def +(other)
|
|
14
|
-
ArelExtensions::Nodes::Concat.new(
|
|
14
|
+
ArelExtensions::Nodes::Concat.new(expressions + [other])
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -4,7 +4,7 @@ module ArelExtensions
|
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
5
|
attr_accessor :left, :pattern, :substitute
|
|
6
6
|
|
|
7
|
-
def initialize
|
|
7
|
+
def initialize(left, pattern, substitute)
|
|
8
8
|
@left = convert_to_node(left)
|
|
9
9
|
@pattern = convert_to_node(pattern)
|
|
10
10
|
@substitute = convert_to_node(substitute)
|
|
@@ -16,9 +16,9 @@ module ArelExtensions
|
|
|
16
16
|
RETURN_TYPE = :string
|
|
17
17
|
attr_accessor :left, :pattern, :substitute
|
|
18
18
|
|
|
19
|
-
def initialize
|
|
19
|
+
def initialize(left, pattern, substitute)
|
|
20
20
|
@left = convert_to_node(left)
|
|
21
|
-
@pattern = (pattern.is_a?(Regexp) ? pattern :
|
|
21
|
+
@pattern = (pattern.is_a?(Regexp) ? pattern : /#{pattern}/)
|
|
22
22
|
@substitute = convert_to_node(substitute)
|
|
23
23
|
super([@left, @pattern, @substitute])
|
|
24
24
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
begin
|
|
5
5
|
Arel::Nodes.const_get('RollUp')
|
|
6
|
-
rescue NameError =>
|
|
6
|
+
rescue NameError => _e
|
|
7
7
|
module Arel
|
|
8
8
|
module Nodes
|
|
9
9
|
class RollUp < Arel::Nodes::Unary
|
|
@@ -18,16 +18,16 @@ rescue NameError => _
|
|
|
18
18
|
# handle grouping aggregation semantics
|
|
19
19
|
def grouping_array_or_grouping_element(o, collector)
|
|
20
20
|
if o.expr.is_a? Array
|
|
21
|
-
collector <<
|
|
21
|
+
collector << '( '
|
|
22
22
|
visit o.expr, collector
|
|
23
|
-
collector <<
|
|
23
|
+
collector << ' )'
|
|
24
24
|
else
|
|
25
25
|
visit o.expr, collector
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def visit_Arel_Nodes_RollUp(o, collector)
|
|
30
|
-
collector <<
|
|
30
|
+
collector << 'ROLLUP'
|
|
31
31
|
grouping_array_or_grouping_element o, collector
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -3,11 +3,11 @@ module ArelExtensions
|
|
|
3
3
|
class Round < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
6
|
+
def initialize(expr)
|
|
7
7
|
if expr && expr.length == 1
|
|
8
|
-
super
|
|
8
|
+
super([convert_to_node(expr.first)])
|
|
9
9
|
else
|
|
10
|
-
super
|
|
10
|
+
super([convert_to_node(expr.first), convert_to_number(expr[1])])
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -4,9 +4,9 @@ module ArelExtensions
|
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
attr_accessor :unbiased_estimator
|
|
6
6
|
|
|
7
|
-
def initialize
|
|
7
|
+
def initialize(node, **opts)
|
|
8
8
|
@unbiased_estimator = opts[:unbiased] ? true : false
|
|
9
|
-
super
|
|
9
|
+
super
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -14,9 +14,9 @@ module ArelExtensions
|
|
|
14
14
|
RETURN_TYPE = :number
|
|
15
15
|
attr_accessor :unbiased_estimator
|
|
16
16
|
|
|
17
|
-
def initialize
|
|
17
|
+
def initialize(node, **opts)
|
|
18
18
|
@unbiased_estimator = opts[:unbiased] ? true : false
|
|
19
|
-
super
|
|
19
|
+
super
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|