arel_extensions 1.2.23 → 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/.rubocop.yml +4 -7
- data/.travis.yml +91 -61
- data/Gemfile +20 -15
- data/README.md +12 -17
- data/Rakefile +29 -40
- data/appveyor.yml +1 -1
- data/arel_extensions.gemspec +3 -3
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +9 -9
- data/gemfiles/rails4.gemfile +13 -13
- data/gemfiles/rails5_0.gemfile +13 -13
- data/gemfiles/rails5_1_4.gemfile +13 -13
- data/gemfiles/rails5_2.gemfile +13 -13
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/postgresql.sql +21 -21
- data/lib/arel_extensions.rb +19 -69
- data/lib/arel_extensions/attributes.rb +1 -0
- data/lib/arel_extensions/boolean_functions.rb +14 -55
- data/lib/arel_extensions/common_sql_functions.rb +8 -7
- data/lib/arel_extensions/comparators.rb +15 -14
- data/lib/arel_extensions/date_duration.rb +5 -4
- data/lib/arel_extensions/insert_manager.rb +16 -17
- data/lib/arel_extensions/math.rb +12 -11
- data/lib/arel_extensions/math_functions.rb +22 -29
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +1 -0
- data/lib/arel_extensions/nodes/case.rb +8 -11
- data/lib/arel_extensions/nodes/cast.rb +2 -4
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/change_case.rb +0 -0
- data/lib/arel_extensions/nodes/coalesce.rb +3 -2
- data/lib/arel_extensions/nodes/collate.rb +2 -1
- data/lib/arel_extensions/nodes/concat.rb +16 -7
- data/lib/arel_extensions/nodes/date_diff.rb +13 -10
- data/lib/arel_extensions/nodes/duration.rb +3 -0
- 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 -34
- data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
- data/lib/arel_extensions/nodes/function.rb +16 -25
- data/lib/arel_extensions/nodes/json.rb +36 -43
- data/lib/arel_extensions/nodes/length.rb +1 -0
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
- data/lib/arel_extensions/nodes/locate.rb +1 -0
- data/lib/arel_extensions/nodes/log10.rb +2 -1
- data/lib/arel_extensions/nodes/matches.rb +6 -4
- 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 +1 -0
- data/lib/arel_extensions/nodes/repeat.rb +4 -2
- data/lib/arel_extensions/nodes/replace.rb +6 -22
- data/lib/arel_extensions/nodes/round.rb +6 -5
- 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 -8
- data/lib/arel_extensions/nodes/then.rb +0 -0
- data/lib/arel_extensions/nodes/trim.rb +5 -3
- data/lib/arel_extensions/nodes/union.rb +5 -2
- data/lib/arel_extensions/nodes/union_all.rb +3 -0
- data/lib/arel_extensions/nodes/wday.rb +4 -0
- data/lib/arel_extensions/null_functions.rb +7 -5
- data/lib/arel_extensions/predications.rb +34 -35
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +4 -2
- data/lib/arel_extensions/string_functions.rb +22 -43
- data/lib/arel_extensions/tasks.rb +5 -5
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors.rb +60 -68
- data/lib/arel_extensions/visitors/ibm_db.rb +12 -5
- data/lib/arel_extensions/visitors/mssql.rb +57 -63
- data/lib/arel_extensions/visitors/mysql.rb +98 -149
- data/lib/arel_extensions/visitors/oracle.rb +68 -71
- data/lib/arel_extensions/visitors/oracle12.rb +15 -2
- data/lib/arel_extensions/visitors/postgresql.rb +63 -116
- data/lib/arel_extensions/visitors/sqlite.rb +70 -83
- data/lib/arel_extensions/visitors/to_sql.rb +109 -141
- data/test/database.yml +0 -2
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +43 -28
- data/test/support/fake_record.rb +2 -2
- data/test/test_comparators.rb +12 -9
- data/test/visitors/test_bulk_insert_oracle.rb +8 -8
- data/test/visitors/test_bulk_insert_sqlite.rb +10 -9
- data/test/visitors/test_bulk_insert_to_sql.rb +10 -8
- data/test/visitors/test_oracle.rb +42 -42
- data/test/visitors/test_to_sql.rb +196 -361
- data/test/with_ar/all_agnostic_test.rb +160 -195
- data/test/with_ar/insert_agnostic_test.rb +4 -3
- data/test/with_ar/test_bulk_sqlite.rb +9 -6
- data/test/with_ar/test_math_sqlite.rb +12 -8
- data/test/with_ar/test_string_mysql.rb +11 -5
- data/test/with_ar/test_string_sqlite.rb +12 -4
- metadata +11 -22
- data/.github/workflows/ruby.yml +0 -102
- data/gemfiles/rails6.gemfile +0 -30
- data/gemfiles/rails6_1.gemfile +0 -30
- data/gemspecs/arel_extensions-v1.gemspec +0 -28
- data/gemspecs/arel_extensions-v2.gemspec +0 -28
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/test/arelx_test_helper.rb +0 -26
- data/version_v1.rb +0 -3
- data/version_v2.rb +0 -3
@@ -1,6 +1,7 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
|
-
|
3
|
+
Arel::Visitors::IBM_DB.class_eval do
|
4
|
+
|
4
5
|
def visit_ArelExtensions_Nodes_Ceil o, collector
|
5
6
|
collector << "CEILING("
|
6
7
|
collector = visit o.expr, collector
|
@@ -11,13 +12,14 @@ module ArelExtensions
|
|
11
12
|
def visit_ArelExtensions_Nodes_Trim o, collector
|
12
13
|
collector << "LTRIM(RTRIM("
|
13
14
|
o.expressions.each_with_index { |arg, i|
|
14
|
-
collector << COMMA
|
15
|
+
collector << Arel::Visitors::IBM_DB::COMMA unless i == 0
|
15
16
|
collector = visit arg, collector
|
16
17
|
}
|
17
18
|
collector << "))"
|
18
19
|
collector
|
19
20
|
end
|
20
21
|
|
22
|
+
|
21
23
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
22
24
|
collector << "DAY("
|
23
25
|
collector = visit o.left, collector
|
@@ -31,8 +33,9 @@ module ArelExtensions
|
|
31
33
|
collector
|
32
34
|
end
|
33
35
|
|
36
|
+
|
34
37
|
def visit_ArelExtensions_Nodes_Duration o, collector
|
35
|
-
#
|
38
|
+
#visit left for period
|
36
39
|
if o.left == "d"
|
37
40
|
collector << "DAY("
|
38
41
|
elsif o.left == "m"
|
@@ -42,7 +45,7 @@ module ArelExtensions
|
|
42
45
|
elsif o.left == "y"
|
43
46
|
collector << "YEAR("
|
44
47
|
end
|
45
|
-
#
|
48
|
+
#visit right
|
46
49
|
if o.right.is_a?(Arel::Attributes::Attribute)
|
47
50
|
collector = visit o.right, collector
|
48
51
|
else
|
@@ -52,11 +55,12 @@ module ArelExtensions
|
|
52
55
|
collector
|
53
56
|
end
|
54
57
|
|
58
|
+
|
55
59
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
56
60
|
collector << "COALESCE("
|
57
61
|
collector = visit o.left, collector
|
58
62
|
collector << ","
|
59
|
-
if
|
63
|
+
if(o.right.is_a?(Arel::Attributes::Attribute))
|
60
64
|
collector = visit o.right, collector
|
61
65
|
else
|
62
66
|
collector << "'#{o.right}'"
|
@@ -64,6 +68,9 @@ module ArelExtensions
|
|
64
68
|
collector << ")"
|
65
69
|
collector
|
66
70
|
end
|
71
|
+
|
72
|
+
|
73
|
+
|
67
74
|
end
|
68
75
|
end
|
69
76
|
end
|
@@ -1,26 +1,13 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
3
|
module MSSQL
|
4
|
-
|
5
|
-
Arel::Visitors::MSSQL::DATE_MAPPING = {
|
6
|
-
'd' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'
|
7
|
-
}.freeze
|
8
|
-
|
4
|
+
Arel::Visitors::MSSQL::DATE_MAPPING = {'d' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'}
|
9
5
|
Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES = {
|
10
6
|
'%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => '', '%b' => '', '%^b' => '', # year, month
|
11
7
|
'%d' => 'DD', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
|
12
8
|
'%H' => 'hh', '%k' => '', '%I' => '', '%l' => '', '%P' => '', '%p' => '', # hours
|
13
9
|
'%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
|
14
|
-
}
|
15
|
-
|
16
|
-
Arel::Visitors::MSSQL::DATE_FORMAT_REGEX =
|
17
|
-
Regexp.new(
|
18
|
-
Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES
|
19
|
-
.keys
|
20
|
-
.map{|k| Regexp.escape(k)}
|
21
|
-
.join('|')
|
22
|
-
).freeze
|
23
|
-
|
10
|
+
}
|
24
11
|
# TODO; all others... http://www.sql-server-helper.com/tips/date-formats.aspx
|
25
12
|
Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS = {
|
26
13
|
'YYYY-MM-DD' => 120,
|
@@ -32,7 +19,7 @@ module ArelExtensions
|
|
32
19
|
'DD-MM-YY' => 5,
|
33
20
|
'DD.MM.YYYY' => 104,
|
34
21
|
'YYYY-MM-DDTHH:MM:SS:MMM' => 126
|
35
|
-
}
|
22
|
+
}
|
36
23
|
|
37
24
|
# Math Functions
|
38
25
|
def visit_ArelExtensions_Nodes_Ceil o, collector
|
@@ -45,7 +32,7 @@ module ArelExtensions
|
|
45
32
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
46
33
|
collector << "LOG10("
|
47
34
|
o.expressions.each_with_index { |arg, i|
|
48
|
-
collector << Arel::Visitors::ToSql::COMMA
|
35
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
49
36
|
collector = visit arg, collector
|
50
37
|
}
|
51
38
|
collector << ")"
|
@@ -55,7 +42,7 @@ module ArelExtensions
|
|
55
42
|
def visit_ArelExtensions_Nodes_Power o, collector
|
56
43
|
collector << "POWER("
|
57
44
|
o.expressions.each_with_index { |arg, i|
|
58
|
-
collector << Arel::Visitors::ToSql::COMMA
|
45
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
59
46
|
collector = visit arg, collector
|
60
47
|
}
|
61
48
|
collector << ")"
|
@@ -79,7 +66,7 @@ module ArelExtensions
|
|
79
66
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
80
67
|
collector << "CONCAT("
|
81
68
|
o.expressions.each_with_index { |arg, i|
|
82
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
69
|
+
collector << Arel::Visitors::MSSQL::COMMA unless i == 0
|
83
70
|
collector = visit arg, collector
|
84
71
|
}
|
85
72
|
collector << ")"
|
@@ -89,7 +76,7 @@ module ArelExtensions
|
|
89
76
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
90
77
|
collector << "REPLICATE("
|
91
78
|
o.expressions.each_with_index { |arg, i|
|
92
|
-
collector << Arel::Visitors::ToSql::COMMA
|
79
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
93
80
|
collector = visit arg, collector
|
94
81
|
}
|
95
82
|
collector << ")"
|
@@ -99,12 +86,12 @@ module ArelExtensions
|
|
99
86
|
|
100
87
|
|
101
88
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
89
|
+
if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
|
90
|
+
collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
|
91
|
+
'DATEDIFF(second'
|
92
|
+
else
|
93
|
+
'DATEDIFF(day'
|
94
|
+
end
|
108
95
|
collector << Arel::Visitors::MSSQL::COMMA
|
109
96
|
collector = visit o.right, collector
|
110
97
|
collector << Arel::Visitors::MSSQL::COMMA
|
@@ -164,7 +151,7 @@ module ArelExtensions
|
|
164
151
|
def visit_ArelExtensions_Nodes_Round o, collector
|
165
152
|
collector << "ROUND("
|
166
153
|
o.expressions.each_with_index { |arg, i|
|
167
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
154
|
+
collector << Arel::Visitors::MSSQL::COMMA unless i == 0
|
168
155
|
collector = visit arg, collector
|
169
156
|
}
|
170
157
|
if o.expressions.length == 1
|
@@ -255,34 +242,42 @@ module ArelExtensions
|
|
255
242
|
end
|
256
243
|
|
257
244
|
def visit_ArelExtensions_Nodes_Format o, collector
|
258
|
-
f =
|
259
|
-
|
245
|
+
f = o.iso_format.dup
|
246
|
+
Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
247
|
+
if Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f]
|
260
248
|
collector << "CONVERT(VARCHAR(#{f.length})"
|
261
249
|
collector << Arel::Visitors::MSSQL::COMMA
|
262
250
|
collector = visit o.left, collector
|
263
251
|
collector << Arel::Visitors::MSSQL::COMMA
|
264
|
-
collector <<
|
252
|
+
collector << Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f].to_s
|
265
253
|
collector << ')'
|
266
254
|
collector
|
267
255
|
else
|
268
|
-
s = StringScanner.new o.iso_format
|
269
256
|
collector << "("
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
257
|
+
t = o.iso_format.split('%')
|
258
|
+
t.each_with_index {|str, i|
|
259
|
+
if i == 0 && t[0] != '%'
|
260
|
+
collector = visit Arel::Nodes.build_quoted(str), collector
|
261
|
+
if str.length > 1
|
262
|
+
collector << Arel::Visitors::MSSQL::COMMA
|
263
|
+
collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
|
264
|
+
end
|
265
|
+
elsif str.length > 0
|
266
|
+
if !Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]].blank?
|
267
|
+
collector << 'LTRIM(STR(DATEPART('
|
268
|
+
collector << Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]]
|
269
|
+
collector << Arel::Visitors::MSSQL::COMMA
|
270
|
+
collector = visit o.left, collector
|
271
|
+
collector << ')))'
|
272
|
+
if str.length > 1
|
273
|
+
collector << ' + '
|
274
|
+
collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
|
275
|
+
end
|
276
|
+
end
|
284
277
|
end
|
285
|
-
|
278
|
+
collector << ' + ' if t[i + 1]
|
279
|
+
}
|
280
|
+
|
286
281
|
collector << ')'
|
287
282
|
collector
|
288
283
|
end
|
@@ -291,7 +286,7 @@ module ArelExtensions
|
|
291
286
|
def visit_ArelExtensions_Nodes_Replace o, collector
|
292
287
|
collector << "REPLACE("
|
293
288
|
o.expressions.each_with_index { |arg, i|
|
294
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
289
|
+
collector << Arel::Visitors::MSSQL::COMMA unless i == 0
|
295
290
|
collector = visit arg, collector
|
296
291
|
}
|
297
292
|
collector << ")"
|
@@ -301,7 +296,7 @@ module ArelExtensions
|
|
301
296
|
def visit_ArelExtensions_Nodes_FindInSet o, collector
|
302
297
|
collector << "dbo.FIND_IN_SET("
|
303
298
|
o.expressions.each_with_index { |arg, i|
|
304
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
299
|
+
collector << Arel::Visitors::MSSQL::COMMA unless i == 0
|
305
300
|
collector = visit arg, collector
|
306
301
|
}
|
307
302
|
collector << ")"
|
@@ -405,16 +400,15 @@ module ArelExtensions
|
|
405
400
|
collector << "(STRING_AGG("
|
406
401
|
collector = visit o.left, collector
|
407
402
|
collector << Arel::Visitors::Oracle::COMMA
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
end
|
403
|
+
if o.right && o.right != 'NULL'
|
404
|
+
collector = visit o.right, collector
|
405
|
+
else
|
406
|
+
collector = visit Arel::Nodes.build_quoted(','), collector
|
407
|
+
end
|
414
408
|
collector << ") WITHIN GROUP (ORDER BY "
|
415
|
-
if o.
|
416
|
-
o.
|
417
|
-
collector << Arel::Visitors::Oracle::COMMA
|
409
|
+
if !o.orders.blank?
|
410
|
+
o.orders.each_with_index do |order,i|
|
411
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
418
412
|
collector = visit order, collector
|
419
413
|
end
|
420
414
|
else
|
@@ -472,9 +466,8 @@ module ArelExtensions
|
|
472
466
|
Arel::Nodes.build_quoted(1) :
|
473
467
|
ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
|
474
468
|
|
475
|
-
|
476
|
-
|
477
|
-
ArelExtensions::Nodes::Concat.new([
|
469
|
+
if o.scientific_notation
|
470
|
+
number = ArelExtensions::Nodes::Concat.new([
|
478
471
|
Arel::Nodes::NamedFunction.new('FORMAT',[
|
479
472
|
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
480
473
|
param,
|
@@ -487,13 +480,13 @@ module ArelExtensions
|
|
487
480
|
locale
|
488
481
|
])
|
489
482
|
])
|
490
|
-
|
491
|
-
|
483
|
+
else
|
484
|
+
number = Arel::Nodes::NamedFunction.new('FORMAT',[
|
492
485
|
Arel::Nodes.build_quoted(col.abs),
|
493
486
|
param,
|
494
487
|
locale
|
495
488
|
])
|
496
|
-
|
489
|
+
end
|
497
490
|
|
498
491
|
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
499
492
|
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
@@ -555,6 +548,7 @@ module ArelExtensions
|
|
555
548
|
collector
|
556
549
|
end
|
557
550
|
|
551
|
+
|
558
552
|
end
|
559
553
|
end
|
560
554
|
end
|
@@ -1,24 +1,21 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
}.freeze
|
8
|
-
|
9
|
-
DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
|
3
|
+
Arel::Visitors::MySQL.class_eval do
|
4
|
+
Arel::Visitors::MySQL::COMMA = ", "
|
5
|
+
Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
6
|
+
Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
|
10
7
|
'%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
|
11
8
|
'%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
|
12
9
|
'%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
|
13
10
|
'%M' => '%i', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => ''
|
14
|
-
}
|
11
|
+
}
|
15
12
|
|
16
13
|
|
17
|
-
#
|
14
|
+
#Math functions
|
18
15
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
19
16
|
collector << "LOG10("
|
20
17
|
o.expressions.each_with_index { |arg, i|
|
21
|
-
collector << Arel::Visitors::ToSql::COMMA
|
18
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
22
19
|
collector = visit arg, collector
|
23
20
|
}
|
24
21
|
collector << ")"
|
@@ -28,14 +25,14 @@ module ArelExtensions
|
|
28
25
|
def visit_ArelExtensions_Nodes_Power o, collector
|
29
26
|
collector << "POW("
|
30
27
|
o.expressions.each_with_index { |arg, i|
|
31
|
-
collector << Arel::Visitors::ToSql::COMMA
|
28
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
32
29
|
collector = visit arg, collector
|
33
30
|
}
|
34
31
|
collector << ")"
|
35
32
|
collector
|
36
33
|
end
|
37
34
|
|
38
|
-
#
|
35
|
+
#String functions
|
39
36
|
def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
|
40
37
|
collector << 'LOWER('
|
41
38
|
collector = visit o.left, collector
|
@@ -101,35 +98,33 @@ module ArelExtensions
|
|
101
98
|
end
|
102
99
|
|
103
100
|
def visit_ArelExtensions_Nodes_Collate o, collector
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
case o.option
|
101
|
+
case o.expressions.first
|
102
|
+
when Arel::Attributes::Attribute
|
103
|
+
charset = case o.option
|
108
104
|
when 'latin1','utf8'
|
109
105
|
o.option
|
110
106
|
else
|
111
107
|
Arel::Table.engine.connection.charset || 'utf8'
|
112
108
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
109
|
+
else
|
110
|
+
charset = (o.option == 'latin1') ? 'latin1' : 'utf8'
|
111
|
+
end
|
116
112
|
collector = visit o.expressions.first, collector
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
113
|
+
if o.ai
|
114
|
+
collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
115
|
+
#doesn't work in latin1
|
116
|
+
elsif o.ci
|
117
|
+
collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
118
|
+
else
|
119
|
+
collector << " COLLATE #{charset}_bin"
|
120
|
+
end
|
126
121
|
collector
|
127
122
|
end
|
128
123
|
|
129
124
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
130
125
|
collector << "CONCAT("
|
131
126
|
o.expressions.each_with_index { |arg, i|
|
132
|
-
collector << COMMA
|
127
|
+
collector << Arel::Visitors::MySQL::COMMA unless i == 0
|
133
128
|
if (arg.is_a?(Numeric)) || (arg.is_a?(Arel::Attributes::Attribute))
|
134
129
|
collector << "CAST("
|
135
130
|
collector = visit arg, collector
|
@@ -145,16 +140,16 @@ module ArelExtensions
|
|
145
140
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
146
141
|
collector << "GROUP_CONCAT("
|
147
142
|
collector = visit o.left, collector
|
148
|
-
if !o.
|
143
|
+
if !o.orders.blank?
|
149
144
|
collector << ' ORDER BY '
|
150
|
-
o.
|
151
|
-
collector << Arel::Visitors::ToSql::COMMA
|
145
|
+
o.orders.each_with_index do |order,i|
|
146
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
152
147
|
collector = visit order, collector
|
153
148
|
end
|
154
149
|
end
|
155
|
-
if o.
|
150
|
+
if o.right && o.right != 'NULL'
|
156
151
|
collector << ' SEPARATOR '
|
157
|
-
collector = visit o.
|
152
|
+
collector = visit o.right, collector
|
158
153
|
end
|
159
154
|
collector << ")"
|
160
155
|
collector
|
@@ -169,7 +164,7 @@ module ArelExtensions
|
|
169
164
|
collector
|
170
165
|
end
|
171
166
|
|
172
|
-
def visit_ArelExtensions_Nodes_Ltrim o, collector
|
167
|
+
def visit_ArelExtensions_Nodes_Ltrim o , collector
|
173
168
|
collector << 'TRIM(LEADING '
|
174
169
|
collector = visit o.right, collector
|
175
170
|
collector << " FROM "
|
@@ -178,7 +173,7 @@ module ArelExtensions
|
|
178
173
|
collector
|
179
174
|
end
|
180
175
|
|
181
|
-
def visit_ArelExtensions_Nodes_Rtrim o, collector
|
176
|
+
def visit_ArelExtensions_Nodes_Rtrim o , collector
|
182
177
|
collector << 'TRIM(TRAILING '
|
183
178
|
collector = visit o.right, collector
|
184
179
|
collector << " FROM "
|
@@ -190,28 +185,22 @@ module ArelExtensions
|
|
190
185
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
191
186
|
collector << "REPEAT("
|
192
187
|
o.expressions.each_with_index { |arg, i|
|
193
|
-
collector << Arel::Visitors::ToSql::COMMA
|
188
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
194
189
|
collector = visit arg, collector
|
195
190
|
}
|
196
191
|
collector << ")"
|
197
192
|
collector
|
198
193
|
end
|
199
194
|
|
200
|
-
def visit_ArelExtensions_Nodes_RegexpReplace o, collector
|
201
|
-
if !regexp_replace_supported?
|
202
|
-
warn("Warning : ArelExtensions: REGEXP_REPLACE does not seem to be available in the current version of the DBMS, it might crash")
|
203
|
-
end
|
204
|
-
super(o,collector)
|
205
|
-
end
|
206
|
-
|
207
195
|
def visit_ArelExtensions_Nodes_Format o, collector
|
208
196
|
case o.col_type
|
209
|
-
when :date, :datetime
|
210
|
-
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
197
|
+
when :date, :datetime
|
211
198
|
collector << "DATE_FORMAT("
|
212
199
|
collector = visit o.left, collector
|
213
|
-
collector << COMMA
|
214
|
-
|
200
|
+
collector << Arel::Visitors::MySQL::COMMA
|
201
|
+
f = o.iso_format.dup
|
202
|
+
Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
203
|
+
collector = visit Arel::Nodes.build_quoted(f), collector
|
215
204
|
collector << ")"
|
216
205
|
when :integer, :float, :decimal
|
217
206
|
collector << "FORMAT("
|
@@ -228,15 +217,14 @@ module ArelExtensions
|
|
228
217
|
end
|
229
218
|
|
230
219
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
end
|
220
|
+
if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
|
221
|
+
collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
|
222
|
+
'TIMESTAMPDIFF(SECOND, '
|
223
|
+
else
|
224
|
+
'DATEDIFF('
|
225
|
+
end
|
238
226
|
collector = visit o.right, collector
|
239
|
-
collector << COMMA
|
227
|
+
collector << Arel::Visitors::MySQL::COMMA
|
240
228
|
collector = visit o.left, collector
|
241
229
|
collector << ")"
|
242
230
|
else
|
@@ -260,12 +248,13 @@ module ArelExtensions
|
|
260
248
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
261
249
|
collector << "DATE_ADD("
|
262
250
|
collector = visit o.left, collector
|
263
|
-
collector << COMMA
|
251
|
+
collector << Arel::Visitors::MySQL::COMMA
|
264
252
|
collector = visit o.mysql_value(o.right), collector
|
265
253
|
collector << ")"
|
266
254
|
collector
|
267
255
|
end
|
268
256
|
|
257
|
+
|
269
258
|
def visit_ArelExtensions_Nodes_Duration o, collector
|
270
259
|
if o.left == 'wd'
|
271
260
|
collector << "(WEEKDAY("
|
@@ -274,18 +263,18 @@ module ArelExtensions
|
|
274
263
|
else
|
275
264
|
if o.with_interval
|
276
265
|
case o.left
|
277
|
-
when
|
266
|
+
when 'd','m','y'
|
278
267
|
interval = 'DAY'
|
279
268
|
when 'h','mn','s'
|
280
269
|
interval = 'SECOND'
|
281
270
|
when /i\z/
|
282
|
-
interval = DATE_MAPPING[o.left[0..-2]]
|
271
|
+
interval = Arel::Visitors::MySQL::DATE_MAPPING[o.left[0..-2]]
|
283
272
|
else
|
284
273
|
interval = nil
|
285
274
|
end
|
286
275
|
end
|
287
276
|
collector << " INTERVAL " if o.with_interval && interval
|
288
|
-
collector << "#{DATE_MAPPING[o.left]}("
|
277
|
+
collector << "#{Arel::Visitors::MySQL::DATE_MAPPING[o.left]}("
|
289
278
|
collector = visit o.right, collector
|
290
279
|
collector << ")"
|
291
280
|
collector << " #{interval} " if o.with_interval && interval
|
@@ -293,6 +282,7 @@ module ArelExtensions
|
|
293
282
|
collector
|
294
283
|
end
|
295
284
|
|
285
|
+
|
296
286
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
297
287
|
collector << "ISNULL("
|
298
288
|
collector = visit o.expr, collector
|
@@ -318,25 +308,30 @@ module ArelExtensions
|
|
318
308
|
collector << "CAST("
|
319
309
|
collector = visit o.left, collector
|
320
310
|
collector << " AS "
|
321
|
-
as_attr
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
)
|
311
|
+
case o.as_attr
|
312
|
+
when :string
|
313
|
+
as_attr = Arel::Nodes::SqlLiteral.new('char')
|
314
|
+
when :time
|
315
|
+
as_attr = Arel::Nodes::SqlLiteral.new('time')
|
316
|
+
when :int
|
317
|
+
as_attr = Arel::Nodes::SqlLiteral.new('signed')
|
318
|
+
when :number, :decimal
|
319
|
+
as_attr = Arel::Nodes::SqlLiteral.new('decimal(20,6)')
|
320
|
+
when :datetime
|
321
|
+
as_attr = Arel::Nodes::SqlLiteral.new('datetime')
|
322
|
+
when :date
|
323
|
+
as_attr = Arel::Nodes::SqlLiteral.new('date')
|
324
|
+
when :binary
|
325
|
+
as_attr = Arel::Nodes::SqlLiteral.new('binary')
|
326
|
+
else
|
327
|
+
as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
|
328
|
+
end
|
334
329
|
collector = visit as_attr, collector
|
335
330
|
collector << ")"
|
336
331
|
collector
|
337
332
|
end
|
338
333
|
|
339
|
-
alias_method
|
334
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
340
335
|
def visit_Arel_Nodes_SelectStatement o, collector
|
341
336
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
342
337
|
o = o.dup
|
@@ -345,7 +340,7 @@ module ArelExtensions
|
|
345
340
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
346
341
|
end
|
347
342
|
|
348
|
-
alias_method
|
343
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
349
344
|
def visit_Arel_Nodes_As o, collector
|
350
345
|
if o.left.is_a?(Arel::Nodes::Binary)
|
351
346
|
collector << '('
|
@@ -368,21 +363,20 @@ module ArelExtensions
|
|
368
363
|
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
369
364
|
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
370
365
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
Arel::Nodes
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
0
|
381
|
-
])
|
366
|
+
if o.scientific_notation
|
367
|
+
number = ArelExtensions::Nodes::Concat.new([
|
368
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
369
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
|
370
|
+
]+params),
|
371
|
+
o.type,
|
372
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
373
|
+
col.abs.log10.floor,
|
374
|
+
0
|
382
375
|
])
|
383
|
-
|
384
|
-
|
385
|
-
|
376
|
+
])
|
377
|
+
else
|
378
|
+
number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
|
379
|
+
end
|
386
380
|
|
387
381
|
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
388
382
|
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
@@ -405,34 +399,10 @@ module ArelExtensions
|
|
405
399
|
collector
|
406
400
|
end
|
407
401
|
|
408
|
-
def visit_Aggregate_For_AggregateFunction o, collector
|
409
|
-
if !window_supported?
|
410
|
-
warn("Warning : ArelExtensions: Window Functions are not available in the current version of the DBMS.")
|
411
|
-
return collector
|
412
|
-
end
|
413
|
-
|
414
|
-
if !o.order.empty? || !o.group.empty?
|
415
|
-
collector << " OVER ("
|
416
|
-
if !o.group.empty?
|
417
|
-
collector << " PARTITION BY ("
|
418
|
-
visit o.group, collector
|
419
|
-
collector << ")"
|
420
|
-
end
|
421
|
-
if !o.order.empty?
|
422
|
-
collector << " ORDER BY ("
|
423
|
-
visit o.order, collector
|
424
|
-
collector << ")"
|
425
|
-
end
|
426
|
-
collector << ")"
|
427
|
-
end
|
428
|
-
collector
|
429
|
-
end
|
430
|
-
|
431
402
|
def visit_ArelExtensions_Nodes_Std o, collector
|
432
403
|
collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
|
433
404
|
visit o.left, collector
|
434
405
|
collector << ")"
|
435
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
436
406
|
collector
|
437
407
|
end
|
438
408
|
|
@@ -440,46 +410,25 @@ module ArelExtensions
|
|
440
410
|
collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
|
441
411
|
visit o.left, collector
|
442
412
|
collector << ")"
|
443
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
444
413
|
collector
|
445
414
|
end
|
446
415
|
|
447
|
-
# JSON if implemented only after 10.2.3
|
416
|
+
# JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
|
448
417
|
def json_supported?
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
version_supported?('10.2.3', '8.0')
|
454
|
-
end
|
455
|
-
|
456
|
-
def regexp_replace_supported?
|
457
|
-
version_supported?('10.0.5', '8.0')
|
458
|
-
end
|
459
|
-
|
460
|
-
def version_supported?(mariadb_v = '10.2.3', mysql_v = '5.7.0')
|
461
|
-
conn = Arel::Table.engine.connection
|
462
|
-
conn.send(:mariadb?) && \
|
463
|
-
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v || \
|
464
|
-
conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
|
465
|
-
conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
|
466
|
-
!conn.send(:mariadb?) && \
|
467
|
-
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
|
468
|
-
conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
|
469
|
-
conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
|
470
|
-
# ideally we should parse the instance_variable @full_version because @version contains only the supposedly
|
471
|
-
# corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
|
418
|
+
Arel::Table.engine.connection.send(:mariadb?) &&
|
419
|
+
Arel::Table.engine.connection.send(:version) >= '10.2.3' ||
|
420
|
+
!Arel::Table.engine.connection.send(:mariadb?) &&
|
421
|
+
Arel::Table.engine.connection.send(:version) >= '5.7.0'
|
472
422
|
end
|
473
423
|
|
474
424
|
def visit_ArelExtensions_Nodes_Json o,collector
|
475
425
|
return super if !json_supported?
|
476
|
-
|
477
426
|
case o.dict
|
478
427
|
when Array
|
479
428
|
collector << 'JSON_ARRAY('
|
480
429
|
o.dict.each.with_index do |v,i|
|
481
430
|
if i != 0
|
482
|
-
collector << COMMA
|
431
|
+
collector << Arel::Visitors::MySQL::COMMA
|
483
432
|
end
|
484
433
|
collector = visit v, collector
|
485
434
|
end
|
@@ -488,10 +437,10 @@ module ArelExtensions
|
|
488
437
|
collector << 'JSON_OBJECT('
|
489
438
|
o.dict.each.with_index do |(k,v),i|
|
490
439
|
if i != 0
|
491
|
-
collector << COMMA
|
440
|
+
collector << Arel::Visitors::MySQL::COMMA
|
492
441
|
end
|
493
442
|
collector = visit k, collector
|
494
|
-
collector << COMMA
|
443
|
+
collector << Arel::Visitors::MySQL::COMMA
|
495
444
|
collector = visit v, collector
|
496
445
|
end
|
497
446
|
collector << ')'
|
@@ -505,7 +454,7 @@ module ArelExtensions
|
|
505
454
|
collector << 'JSON_MERGE_PATCH('
|
506
455
|
o.expressions.each.with_index do |v,i|
|
507
456
|
if i != 0
|
508
|
-
collector << COMMA
|
457
|
+
collector << Arel::Visitors::MySQL::COMMA
|
509
458
|
end
|
510
459
|
collector = visit v, collector
|
511
460
|
end
|
@@ -516,7 +465,7 @@ module ArelExtensions
|
|
516
465
|
def visit_ArelExtensions_Nodes_JsonGet o,collector
|
517
466
|
collector << 'JSON_EXTRACT('
|
518
467
|
collector = visit o.dict, collector
|
519
|
-
collector << COMMA
|
468
|
+
collector << Arel::Visitors::MySQL::COMMA
|
520
469
|
if o.key.is_a?(Integer)
|
521
470
|
collector << "\"$[#{o.key}]\""
|
522
471
|
else
|
@@ -529,13 +478,13 @@ module ArelExtensions
|
|
529
478
|
def visit_ArelExtensions_Nodes_JsonSet o,collector
|
530
479
|
collector << 'JSON_SET('
|
531
480
|
collector = visit o.dict, collector
|
532
|
-
collector << COMMA
|
481
|
+
collector << Arel::Visitors::MySQL::COMMA
|
533
482
|
if o.key.is_a?(Integer)
|
534
483
|
collector << "\"$[#{o.key}]\""
|
535
484
|
else
|
536
485
|
collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
|
537
486
|
end
|
538
|
-
collector << COMMA
|
487
|
+
collector << Arel::Visitors::MySQL::COMMA
|
539
488
|
collector = visit o.value, collector
|
540
489
|
collector << ')'
|
541
490
|
collector
|
@@ -543,7 +492,6 @@ module ArelExtensions
|
|
543
492
|
|
544
493
|
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
545
494
|
return super if !json_supported?
|
546
|
-
|
547
495
|
if o.as_array
|
548
496
|
collector << 'JSON_ARRAYAGG('
|
549
497
|
collector = visit o.dict, collector
|
@@ -554,11 +502,11 @@ module ArelExtensions
|
|
554
502
|
collector << 'JSON_MERGE_PATCH(' if o.dict.length > 1
|
555
503
|
o.dict.each.with_index do |(k,v),i|
|
556
504
|
if i != 0
|
557
|
-
collector << COMMA
|
505
|
+
collector << Arel::Visitors::MySQL::COMMA
|
558
506
|
end
|
559
507
|
collector << 'JSON_OBJECTAGG('
|
560
508
|
collector = visit k, collector
|
561
|
-
collector << COMMA
|
509
|
+
collector << Arel::Visitors::MySQL::COMMA
|
562
510
|
collector = visit v, collector
|
563
511
|
collector << ')'
|
564
512
|
end
|
@@ -571,6 +519,7 @@ module ArelExtensions
|
|
571
519
|
end
|
572
520
|
collector
|
573
521
|
end
|
522
|
+
|
574
523
|
end
|
575
524
|
end
|
576
525
|
end
|