arel_extensions 2.0.9 → 2.0.14
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/.travis.yml +2 -0
- data/Gemfile +10 -10
- data/Rakefile +4 -4
- 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/gemfiles/rails6.gemfile +13 -13
- data/lib/arel_extensions.rb +3 -3
- data/lib/arel_extensions/attributes.rb +0 -0
- data/lib/arel_extensions/boolean_functions.rb +21 -5
- data/lib/arel_extensions/common_sql_functions.rb +2 -4
- data/lib/arel_extensions/comparators.rb +11 -14
- data/lib/arel_extensions/date_duration.rb +4 -5
- data/lib/arel_extensions/insert_manager.rb +16 -17
- data/lib/arel_extensions/math.rb +8 -9
- data/lib/arel_extensions/math_functions.rb +15 -17
- data/lib/arel_extensions/nodes/abs.rb +0 -1
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -1
- data/lib/arel_extensions/nodes/blank.rb +0 -1
- data/lib/arel_extensions/nodes/case.rb +3 -4
- data/lib/arel_extensions/nodes/cast.rb +4 -2
- 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 +0 -1
- data/lib/arel_extensions/nodes/collate.rb +0 -1
- data/lib/arel_extensions/nodes/concat.rb +1 -3
- data/lib/arel_extensions/nodes/date_diff.rb +7 -8
- data/lib/arel_extensions/nodes/duration.rb +0 -1
- data/lib/arel_extensions/nodes/find_in_set.rb +0 -1
- data/lib/arel_extensions/nodes/floor.rb +1 -1
- data/lib/arel_extensions/nodes/format.rb +27 -1
- data/lib/arel_extensions/nodes/formatted_number.rb +0 -1
- data/lib/arel_extensions/nodes/function.rb +18 -15
- data/lib/arel_extensions/nodes/is_null.rb +0 -0
- data/lib/arel_extensions/nodes/json.rb +39 -30
- data/lib/arel_extensions/nodes/length.rb +0 -1
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
- data/lib/arel_extensions/nodes/locate.rb +0 -1
- data/lib/arel_extensions/nodes/log10.rb +1 -2
- data/lib/arel_extensions/nodes/matches.rb +0 -2
- data/lib/arel_extensions/nodes/md5.rb +0 -1
- data/lib/arel_extensions/nodes/power.rb +0 -1
- data/lib/arel_extensions/nodes/rand.rb +0 -1
- data/lib/arel_extensions/nodes/repeat.rb +0 -2
- data/lib/arel_extensions/nodes/replace.rb +0 -2
- data/lib/arel_extensions/nodes/round.rb +0 -1
- data/lib/arel_extensions/nodes/soundex.rb +0 -1
- data/lib/arel_extensions/nodes/std.rb +0 -1
- data/lib/arel_extensions/nodes/substring.rb +0 -1
- data/lib/arel_extensions/nodes/sum.rb +0 -0
- data/lib/arel_extensions/nodes/then.rb +0 -0
- data/lib/arel_extensions/nodes/trim.rb +0 -2
- data/lib/arel_extensions/nodes/union.rb +0 -2
- data/lib/arel_extensions/nodes/union_all.rb +0 -2
- data/lib/arel_extensions/nodes/wday.rb +0 -4
- data/lib/arel_extensions/null_functions.rb +3 -5
- data/lib/arel_extensions/predications.rb +5 -6
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +0 -2
- data/lib/arel_extensions/string_functions.rb +21 -22
- data/lib/arel_extensions/tasks.rb +1 -1
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors.rb +9 -7
- data/lib/arel_extensions/visitors/convert_format.rb +37 -0
- data/lib/arel_extensions/visitors/ibm_db.rb +4 -11
- data/lib/arel_extensions/visitors/mssql.rb +48 -44
- data/lib/arel_extensions/visitors/mysql.rb +65 -67
- data/lib/arel_extensions/visitors/oracle.rb +58 -55
- data/lib/arel_extensions/visitors/oracle12.rb +2 -3
- data/lib/arel_extensions/visitors/postgresql.rb +41 -34
- data/lib/arel_extensions/visitors/sqlite.rb +23 -18
- data/lib/arel_extensions/visitors/to_sql.rb +69 -61
- data/test/arelx_test_helper.rb +0 -2
- data/test/real_db_test.rb +27 -42
- data/test/support/fake_record.rb +1 -1
- data/test/test_comparators.rb +0 -4
- data/test/visitors/test_bulk_insert_oracle.rb +0 -1
- data/test/visitors/test_bulk_insert_sqlite.rb +0 -2
- data/test/visitors/test_oracle.rb +1 -2
- data/test/visitors/test_to_sql.rb +16 -25
- data/test/with_ar/all_agnostic_test.rb +135 -139
- data/test/with_ar/insert_agnostic_test.rb +0 -2
- data/test/with_ar/test_bulk_sqlite.rb +0 -4
- data/test/with_ar/test_math_sqlite.rb +4 -8
- data/test/with_ar/test_string_mysql.rb +1 -5
- data/test/with_ar/test_string_sqlite.rb +1 -5
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +3 -2
@@ -1,20 +1,24 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
3
|
class Arel::Visitors::MySQL
|
4
|
-
|
5
|
-
|
4
|
+
DATE_MAPPING = {
|
5
|
+
'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY',
|
6
|
+
'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
|
6
10
|
'%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
|
7
11
|
'%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
|
8
12
|
'%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
|
9
13
|
'%M' => '%i', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => ''
|
10
|
-
}
|
14
|
+
}.freeze
|
11
15
|
|
12
16
|
|
13
|
-
#Math functions
|
17
|
+
# Math functions
|
14
18
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
15
19
|
collector << "LOG10("
|
16
20
|
o.expressions.each_with_index { |arg, i|
|
17
|
-
collector << Arel::Visitors::ToSql::COMMA
|
21
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
18
22
|
collector = visit arg, collector
|
19
23
|
}
|
20
24
|
collector << ")"
|
@@ -24,14 +28,14 @@ module ArelExtensions
|
|
24
28
|
def visit_ArelExtensions_Nodes_Power o, collector
|
25
29
|
collector << "POW("
|
26
30
|
o.expressions.each_with_index { |arg, i|
|
27
|
-
collector << Arel::Visitors::ToSql::COMMA
|
31
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
28
32
|
collector = visit arg, collector
|
29
33
|
}
|
30
34
|
collector << ")"
|
31
35
|
collector
|
32
36
|
end
|
33
37
|
|
34
|
-
#String functions
|
38
|
+
# String functions
|
35
39
|
def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
|
36
40
|
collector << 'LOWER('
|
37
41
|
collector = visit o.left, collector
|
@@ -112,10 +116,10 @@ module ArelExtensions
|
|
112
116
|
collector = visit o.expressions.first, collector
|
113
117
|
collector <<
|
114
118
|
if o.ai
|
115
|
-
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'
|
116
|
-
#doesn't work in latin1
|
119
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
|
120
|
+
# doesn't work in latin1
|
117
121
|
elsif o.ci
|
118
|
-
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'
|
122
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci'}"
|
119
123
|
else
|
120
124
|
" COLLATE #{charset}_bin"
|
121
125
|
end
|
@@ -125,7 +129,7 @@ module ArelExtensions
|
|
125
129
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
126
130
|
collector << "CONCAT("
|
127
131
|
o.expressions.each_with_index { |arg, i|
|
128
|
-
collector <<
|
132
|
+
collector << COMMA if i != 0
|
129
133
|
if (arg.is_a?(Numeric)) || (arg.is_a?(Arel::Attributes::Attribute))
|
130
134
|
collector << "CAST("
|
131
135
|
collector = visit arg, collector
|
@@ -144,7 +148,7 @@ module ArelExtensions
|
|
144
148
|
if !o.order.blank?
|
145
149
|
collector << ' ORDER BY '
|
146
150
|
o.order.each_with_index do |order,i|
|
147
|
-
collector << Arel::Visitors::ToSql::COMMA
|
151
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
148
152
|
collector = visit order, collector
|
149
153
|
end
|
150
154
|
end
|
@@ -165,7 +169,7 @@ module ArelExtensions
|
|
165
169
|
collector
|
166
170
|
end
|
167
171
|
|
168
|
-
def visit_ArelExtensions_Nodes_Ltrim o
|
172
|
+
def visit_ArelExtensions_Nodes_Ltrim o, collector
|
169
173
|
collector << 'TRIM(LEADING '
|
170
174
|
collector = visit o.right, collector
|
171
175
|
collector << " FROM "
|
@@ -174,7 +178,7 @@ module ArelExtensions
|
|
174
178
|
collector
|
175
179
|
end
|
176
180
|
|
177
|
-
def visit_ArelExtensions_Nodes_Rtrim o
|
181
|
+
def visit_ArelExtensions_Nodes_Rtrim o, collector
|
178
182
|
collector << 'TRIM(TRAILING '
|
179
183
|
collector = visit o.right, collector
|
180
184
|
collector << " FROM "
|
@@ -186,7 +190,7 @@ module ArelExtensions
|
|
186
190
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
187
191
|
collector << "REPEAT("
|
188
192
|
o.expressions.each_with_index { |arg, i|
|
189
|
-
collector << Arel::Visitors::ToSql::COMMA
|
193
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
190
194
|
collector = visit arg, collector
|
191
195
|
}
|
192
196
|
collector << ")"
|
@@ -202,13 +206,12 @@ module ArelExtensions
|
|
202
206
|
|
203
207
|
def visit_ArelExtensions_Nodes_Format o, collector
|
204
208
|
case o.col_type
|
205
|
-
when :date, :datetime
|
209
|
+
when :date, :datetime, :time
|
210
|
+
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
206
211
|
collector << "DATE_FORMAT("
|
207
212
|
collector = visit o.left, collector
|
208
|
-
collector <<
|
209
|
-
|
210
|
-
Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
211
|
-
collector = visit Arel::Nodes.build_quoted(f), collector
|
213
|
+
collector << COMMA
|
214
|
+
collector = visit Arel::Nodes.build_quoted(fmt), collector
|
212
215
|
collector << ")"
|
213
216
|
when :integer, :float, :decimal
|
214
217
|
collector << "FORMAT("
|
@@ -225,14 +228,15 @@ module ArelExtensions
|
|
225
228
|
end
|
226
229
|
|
227
230
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
231
|
+
case o.right_node_type
|
232
|
+
when :ruby_date, :ruby_time, :date, :datetime, :time
|
233
|
+
collector <<
|
234
|
+
case o.left_node_type
|
235
|
+
when :ruby_time, :datetime, :time then 'TIMESTAMPDIFF(SECOND, '
|
236
|
+
else 'DATEDIFF('
|
237
|
+
end
|
234
238
|
collector = visit o.right, collector
|
235
|
-
collector <<
|
239
|
+
collector << COMMA
|
236
240
|
collector = visit o.left, collector
|
237
241
|
collector << ")"
|
238
242
|
else
|
@@ -256,13 +260,12 @@ module ArelExtensions
|
|
256
260
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
257
261
|
collector << "DATE_ADD("
|
258
262
|
collector = visit o.left, collector
|
259
|
-
collector <<
|
263
|
+
collector << COMMA
|
260
264
|
collector = visit o.mysql_value(o.right), collector
|
261
265
|
collector << ")"
|
262
266
|
collector
|
263
267
|
end
|
264
268
|
|
265
|
-
|
266
269
|
def visit_ArelExtensions_Nodes_Duration o, collector
|
267
270
|
if o.left == 'wd'
|
268
271
|
collector << "(WEEKDAY("
|
@@ -276,13 +279,13 @@ module ArelExtensions
|
|
276
279
|
when 'h','mn','s'
|
277
280
|
interval = 'SECOND'
|
278
281
|
when /i\z/
|
279
|
-
interval =
|
282
|
+
interval = DATE_MAPPING[o.left[0..-2]]
|
280
283
|
else
|
281
284
|
interval = nil
|
282
285
|
end
|
283
286
|
end
|
284
287
|
collector << " INTERVAL " if o.with_interval && interval
|
285
|
-
collector << "#{
|
288
|
+
collector << "#{DATE_MAPPING[o.left]}("
|
286
289
|
collector = visit o.right, collector
|
287
290
|
collector << ")"
|
288
291
|
collector << " #{interval} " if o.with_interval && interval
|
@@ -290,7 +293,6 @@ module ArelExtensions
|
|
290
293
|
collector
|
291
294
|
end
|
292
295
|
|
293
|
-
|
294
296
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
295
297
|
collector << "ISNULL("
|
296
298
|
collector = visit o.expr, collector
|
@@ -316,30 +318,25 @@ module ArelExtensions
|
|
316
318
|
collector << "CAST("
|
317
319
|
collector = visit o.left, collector
|
318
320
|
collector << " AS "
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
when :binary
|
333
|
-
as_attr = Arel::Nodes::SqlLiteral.new('binary')
|
334
|
-
else
|
335
|
-
as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
|
336
|
-
end
|
321
|
+
as_attr =
|
322
|
+
Arel::Nodes::SqlLiteral.new(
|
323
|
+
case o.as_attr
|
324
|
+
when :string then 'char'
|
325
|
+
when :time then 'time'
|
326
|
+
when :int then 'signed'
|
327
|
+
when :number, :decimal then 'decimal(20,6)'
|
328
|
+
when :datetime then 'datetime'
|
329
|
+
when :date then 'date'
|
330
|
+
when :binary then 'binary'
|
331
|
+
else o.as_attr.to_s
|
332
|
+
end
|
333
|
+
)
|
337
334
|
collector = visit as_attr, collector
|
338
335
|
collector << ")"
|
339
336
|
collector
|
340
337
|
end
|
341
338
|
|
342
|
-
alias_method
|
339
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
343
340
|
def visit_Arel_Nodes_SelectStatement o, collector
|
344
341
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
345
342
|
o = o.dup
|
@@ -348,7 +345,7 @@ module ArelExtensions
|
|
348
345
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
349
346
|
end
|
350
347
|
|
351
|
-
alias_method
|
348
|
+
alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
|
352
349
|
def visit_Arel_Nodes_As o, collector
|
353
350
|
if o.left.is_a?(Arel::Nodes::Binary)
|
354
351
|
collector << '('
|
@@ -447,9 +444,9 @@ module ArelExtensions
|
|
447
444
|
collector
|
448
445
|
end
|
449
446
|
|
450
|
-
# JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
|
447
|
+
# JSON if implemented only after 10.2.3 (aggregations after 10.5.0) in MariaDb and 5.7 (aggregations after 5.7.22) in MySql
|
451
448
|
def json_supported?
|
452
|
-
version_supported?('10.
|
449
|
+
version_supported?('10.5.0', '5.7.22')
|
453
450
|
end
|
454
451
|
|
455
452
|
def window_supported?
|
@@ -467,21 +464,22 @@ module ArelExtensions
|
|
467
464
|
conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
|
468
465
|
conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
|
469
466
|
!conn.send(:mariadb?) && \
|
470
|
-
|
471
|
-
|
472
|
-
|
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)
|
473
470
|
# ideally we should parse the instance_variable @full_version because @version contains only the supposedly
|
474
471
|
# corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
|
475
472
|
end
|
476
473
|
|
477
474
|
def visit_ArelExtensions_Nodes_Json o,collector
|
478
475
|
return super if !json_supported?
|
476
|
+
|
479
477
|
case o.dict
|
480
478
|
when Array
|
481
479
|
collector << 'JSON_ARRAY('
|
482
480
|
o.dict.each.with_index do |v,i|
|
483
481
|
if i != 0
|
484
|
-
collector <<
|
482
|
+
collector << COMMA
|
485
483
|
end
|
486
484
|
collector = visit v, collector
|
487
485
|
end
|
@@ -490,10 +488,10 @@ module ArelExtensions
|
|
490
488
|
collector << 'JSON_OBJECT('
|
491
489
|
o.dict.each.with_index do |(k,v),i|
|
492
490
|
if i != 0
|
493
|
-
collector <<
|
491
|
+
collector << COMMA
|
494
492
|
end
|
495
493
|
collector = visit k, collector
|
496
|
-
collector <<
|
494
|
+
collector << COMMA
|
497
495
|
collector = visit v, collector
|
498
496
|
end
|
499
497
|
collector << ')'
|
@@ -507,7 +505,7 @@ module ArelExtensions
|
|
507
505
|
collector << 'JSON_MERGE_PATCH('
|
508
506
|
o.expressions.each.with_index do |v,i|
|
509
507
|
if i != 0
|
510
|
-
collector <<
|
508
|
+
collector << COMMA
|
511
509
|
end
|
512
510
|
collector = visit v, collector
|
513
511
|
end
|
@@ -518,7 +516,7 @@ module ArelExtensions
|
|
518
516
|
def visit_ArelExtensions_Nodes_JsonGet o,collector
|
519
517
|
collector << 'JSON_EXTRACT('
|
520
518
|
collector = visit o.dict, collector
|
521
|
-
collector <<
|
519
|
+
collector << COMMA
|
522
520
|
if o.key.is_a?(Integer)
|
523
521
|
collector << "\"$[#{o.key}]\""
|
524
522
|
else
|
@@ -531,13 +529,13 @@ module ArelExtensions
|
|
531
529
|
def visit_ArelExtensions_Nodes_JsonSet o,collector
|
532
530
|
collector << 'JSON_SET('
|
533
531
|
collector = visit o.dict, collector
|
534
|
-
collector <<
|
532
|
+
collector << COMMA
|
535
533
|
if o.key.is_a?(Integer)
|
536
534
|
collector << "\"$[#{o.key}]\""
|
537
535
|
else
|
538
536
|
collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
|
539
537
|
end
|
540
|
-
collector <<
|
538
|
+
collector << COMMA
|
541
539
|
collector = visit o.value, collector
|
542
540
|
collector << ')'
|
543
541
|
collector
|
@@ -545,6 +543,7 @@ module ArelExtensions
|
|
545
543
|
|
546
544
|
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
547
545
|
return super if !json_supported?
|
546
|
+
|
548
547
|
if o.as_array
|
549
548
|
collector << 'JSON_ARRAYAGG('
|
550
549
|
collector = visit o.dict, collector
|
@@ -555,11 +554,11 @@ module ArelExtensions
|
|
555
554
|
collector << 'JSON_MERGE_PATCH(' if o.dict.length > 1
|
556
555
|
o.dict.each.with_index do |(k,v),i|
|
557
556
|
if i != 0
|
558
|
-
collector <<
|
557
|
+
collector << COMMA
|
559
558
|
end
|
560
559
|
collector << 'JSON_OBJECTAGG('
|
561
560
|
collector = visit k, collector
|
562
|
-
collector <<
|
561
|
+
collector << COMMA
|
563
562
|
collector = visit v, collector
|
564
563
|
collector << ')'
|
565
564
|
end
|
@@ -572,7 +571,6 @@ module ArelExtensions
|
|
572
571
|
end
|
573
572
|
collector
|
574
573
|
end
|
575
|
-
|
576
574
|
end
|
577
575
|
end
|
578
576
|
end
|
@@ -1,22 +1,21 @@
|
|
1
|
-
#require 'oracle_visitor'
|
1
|
+
# require 'oracle_visitor'
|
2
2
|
module ArelExtensions
|
3
3
|
module Visitors
|
4
4
|
class Arel::Visitors::Oracle
|
5
|
-
|
6
5
|
SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
|
7
|
-
|
8
|
-
|
6
|
+
DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
7
|
+
DATE_FORMAT_DIRECTIVES = {
|
9
8
|
'%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
|
10
9
|
'%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
|
11
10
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
12
11
|
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
13
12
|
}
|
14
|
-
|
13
|
+
NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
|
15
14
|
|
16
15
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
17
16
|
collector << "LOG("
|
18
17
|
o.expressions.each_with_index { |arg, i|
|
19
|
-
collector << Arel::Visitors::ToSql::COMMA
|
18
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
20
19
|
collector = visit arg, collector
|
21
20
|
}
|
22
21
|
collector << ",10)"
|
@@ -26,7 +25,7 @@ module ArelExtensions
|
|
26
25
|
def visit_ArelExtensions_Nodes_Power o, collector
|
27
26
|
collector << "POWER("
|
28
27
|
o.expressions.each_with_index { |arg, i|
|
29
|
-
collector << Arel::Visitors::ToSql::COMMA
|
28
|
+
collector << Arel::Visitors::ToSql::COMMA if i != 0
|
30
29
|
collector = visit arg, collector
|
31
30
|
}
|
32
31
|
collector << ")"
|
@@ -93,7 +92,6 @@ module ArelExtensions
|
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
|
-
|
97
95
|
def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
|
98
96
|
collector << 'LOWER('
|
99
97
|
collector = visit o.left, collector
|
@@ -112,25 +110,25 @@ module ArelExtensions
|
|
112
110
|
if o.ai
|
113
111
|
collector << "NLSSORT("
|
114
112
|
collector = visit o.expressions.first, collector
|
115
|
-
collector <<
|
113
|
+
collector << COMMA
|
116
114
|
collector << "'NLS_SORT = BINARY_AI NLS_COMP = LINGUISTIC'"
|
117
115
|
collector << ")"
|
118
116
|
elsif o.ci
|
119
117
|
collector << "NLSSORT("
|
120
118
|
collector = visit o.expressions.first, collector
|
121
|
-
collector <<
|
119
|
+
collector << COMMA
|
122
120
|
collector << "'NLS_SORT = BINARY_CI NLS_COMP = LINGUISTIC'"
|
123
121
|
collector << ")"
|
124
122
|
else
|
125
123
|
collector = visit o.expressions.first, collector
|
126
124
|
end
|
127
|
-
|
125
|
+
collector
|
128
126
|
end
|
129
127
|
|
130
128
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
131
129
|
collector << "(LISTAGG("
|
132
130
|
collector = visit o.left, collector
|
133
|
-
collector <<
|
131
|
+
collector << COMMA
|
134
132
|
collector =
|
135
133
|
if o.separator && o.separator != 'NULL'
|
136
134
|
visit o.separator, collector
|
@@ -140,7 +138,7 @@ module ArelExtensions
|
|
140
138
|
collector << ") WITHIN GROUP (ORDER BY "
|
141
139
|
if !o.order.blank?
|
142
140
|
o.order.each_with_index do |order,i|
|
143
|
-
collector <<
|
141
|
+
collector << COMMA if i != 0
|
144
142
|
collector = visit order, collector
|
145
143
|
end
|
146
144
|
else
|
@@ -153,7 +151,7 @@ module ArelExtensions
|
|
153
151
|
def visit_ArelExtensions_Nodes_Coalesce o, collector
|
154
152
|
collector << "COALESCE("
|
155
153
|
o.expressions.each_with_index { |arg, i|
|
156
|
-
collector <<
|
154
|
+
collector << COMMA if i != 0
|
157
155
|
if i > 0 && o.left_node_type == :text
|
158
156
|
if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
|
159
157
|
collector << "NULL"
|
@@ -196,7 +194,7 @@ module ArelExtensions
|
|
196
194
|
collector << 'TO_DATE(' if lc
|
197
195
|
collector = visit o.left, collector
|
198
196
|
collector << ')' if lc
|
199
|
-
collector <<
|
197
|
+
collector << COMMA
|
200
198
|
collector << "'DDD') = "
|
201
199
|
collector << 'TO_DATE(' if lc
|
202
200
|
collector = visit o.left, collector
|
@@ -222,8 +220,8 @@ module ArelExtensions
|
|
222
220
|
when 'wd', 'w'
|
223
221
|
collector << "TO_CHAR("
|
224
222
|
collector = visit o.right, collector
|
225
|
-
collector <<
|
226
|
-
collector = visit Arel::Nodes.build_quoted(
|
223
|
+
collector << COMMA
|
224
|
+
collector = visit Arel::Nodes.build_quoted(DATE_MAPPING[o.left]), collector
|
227
225
|
else
|
228
226
|
right = case o.left
|
229
227
|
when 'd','m','y'
|
@@ -233,7 +231,7 @@ module ArelExtensions
|
|
233
231
|
interval = 'SECOND'
|
234
232
|
o.right.cast(:datetime)
|
235
233
|
when /i\z/
|
236
|
-
interval =
|
234
|
+
interval = DATE_MAPPING[o.left[0..-2]]
|
237
235
|
collector << '('
|
238
236
|
collector = visit o.right, collector
|
239
237
|
collector << ") * (INTERVAL '1' #{interval})"
|
@@ -242,7 +240,7 @@ module ArelExtensions
|
|
242
240
|
interval = nil
|
243
241
|
o.right
|
244
242
|
end
|
245
|
-
collector << "EXTRACT(#{
|
243
|
+
collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
|
246
244
|
collector = visit right, collector
|
247
245
|
end
|
248
246
|
collector << ")"
|
@@ -257,6 +255,16 @@ module ArelExtensions
|
|
257
255
|
collector = visit o.left, collector
|
258
256
|
collector << ")"
|
259
257
|
return collector
|
258
|
+
when :text
|
259
|
+
collector << "TO_CLOB("
|
260
|
+
collector = visit o.left, collector
|
261
|
+
collector << ")"
|
262
|
+
return collector
|
263
|
+
when :ntext
|
264
|
+
collector << "TO_NCLOB("
|
265
|
+
collector = visit o.left, collector
|
266
|
+
collector << ")"
|
267
|
+
return collector
|
260
268
|
when :time
|
261
269
|
if (o.left.respond_to?(:return_type) && o.left.return_type == :string) || o.left.is_a?(Arel::Nodes::Quoted)
|
262
270
|
collector << "TO_DATE("
|
@@ -322,7 +330,7 @@ module ArelExtensions
|
|
322
330
|
collector << "DBMS_RANDOM.VALUE("
|
323
331
|
if o.left && o.right
|
324
332
|
collector = visit o.left, collector
|
325
|
-
collector <<
|
333
|
+
collector << COMMA
|
326
334
|
collector = visit o.right, collector
|
327
335
|
end
|
328
336
|
collector << ")"
|
@@ -332,7 +340,7 @@ module ArelExtensions
|
|
332
340
|
def visit_Arel_Nodes_Regexp o, collector
|
333
341
|
collector << " REGEXP_LIKE("
|
334
342
|
collector = visit o.left, collector
|
335
|
-
collector <<
|
343
|
+
collector << COMMA
|
336
344
|
collector = visit o.right, collector
|
337
345
|
collector << ')'
|
338
346
|
collector
|
@@ -341,7 +349,7 @@ module ArelExtensions
|
|
341
349
|
def visit_Arel_Nodes_NotRegexp o, collector
|
342
350
|
collector << " NOT REGEXP_LIKE("
|
343
351
|
collector = visit o.left, collector
|
344
|
-
collector <<
|
352
|
+
collector << COMMA
|
345
353
|
collector = visit o.right, collector
|
346
354
|
collector << ')'
|
347
355
|
collector
|
@@ -350,7 +358,7 @@ module ArelExtensions
|
|
350
358
|
def visit_ArelExtensions_Nodes_Locate o, collector
|
351
359
|
collector << "INSTR("
|
352
360
|
o.expressions.each_with_index { |arg, i|
|
353
|
-
collector <<
|
361
|
+
collector << COMMA if i != 0
|
354
362
|
collector = visit arg, collector
|
355
363
|
}
|
356
364
|
collector << ")"
|
@@ -360,7 +368,7 @@ module ArelExtensions
|
|
360
368
|
def visit_ArelExtensions_Nodes_Substring o, collector
|
361
369
|
collector << "SUBSTR("
|
362
370
|
o.expressions.each_with_index { |arg, i|
|
363
|
-
collector <<
|
371
|
+
collector << COMMA if i != 0
|
364
372
|
collector = visit arg, collector
|
365
373
|
}
|
366
374
|
collector << ")"
|
@@ -379,11 +387,11 @@ module ArelExtensions
|
|
379
387
|
if o.type_of_attribute(o.left) == :text
|
380
388
|
collector << 'dbms_lob.SUBSTR('
|
381
389
|
collector = visit o.left, collector
|
382
|
-
collector <<
|
390
|
+
collector << COMMA
|
383
391
|
collector << 'COALESCE(dbms_lob.GETLENGTH('
|
384
392
|
collector = visit o.left, collector
|
385
393
|
collector << "), 0)"
|
386
|
-
collector <<
|
394
|
+
collector << COMMA
|
387
395
|
collector << '1)'
|
388
396
|
else
|
389
397
|
collector = visit o.left, collector
|
@@ -430,28 +438,25 @@ module ArelExtensions
|
|
430
438
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
431
439
|
collector << '('
|
432
440
|
collector = visit o.left, collector
|
433
|
-
collector << ' + '# (o.right.value >= 0 ? ' + ' : ' - ')
|
441
|
+
collector << ' + ' # (o.right.value >= 0 ? ' + ' : ' - ')
|
434
442
|
collector = visit o.oracle_value(o.right), collector
|
435
443
|
collector << ')'
|
436
444
|
collector
|
437
445
|
end
|
438
446
|
|
439
447
|
def visit_ArelExtensions_Nodes_Format o, collector
|
448
|
+
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
440
449
|
collector << "TO_CHAR("
|
441
450
|
collector = visit o.left, collector
|
442
|
-
collector <<
|
443
|
-
|
444
|
-
f = o.iso_format.gsub(/\ (\w+)/, ' "\1"')
|
445
|
-
Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
446
|
-
collector = visit Arel::Nodes.build_quoted(f), collector
|
447
|
-
|
451
|
+
collector << COMMA
|
452
|
+
collector = visit Arel::Nodes.build_quoted(fmt), collector
|
448
453
|
collector << ")"
|
449
454
|
collector
|
450
455
|
end
|
451
456
|
|
452
457
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
453
458
|
collector << "LPAD("
|
454
|
-
collector = visit o.expressions[0], collector #can't put empty string, otherwise it wouldn't work
|
459
|
+
collector = visit o.expressions[0], collector # can't put empty string, otherwise it wouldn't work
|
455
460
|
collector << Arel::Visitors::ToSql::COMMA
|
456
461
|
collector = visit o.expressions[1], collector
|
457
462
|
collector << Arel::Visitors::ToSql::COMMA
|
@@ -460,24 +465,24 @@ module ArelExtensions
|
|
460
465
|
collector
|
461
466
|
end
|
462
467
|
|
463
|
-
|
468
|
+
# add primary_key if not present, avoid zip
|
464
469
|
if Arel::VERSION.to_i < 7
|
465
470
|
def visit_ArelExtensions_InsertManager_BulkValues o, collector
|
466
471
|
collector << "("
|
467
472
|
o.left.each_with_index do |row, idx| # values
|
468
473
|
collector << " UNION ALL " if idx != 0
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
474
|
+
collector << "(SELECT "
|
475
|
+
len = row.length - 1
|
476
|
+
row.zip(o.cols).each_with_index { |(value, attr), i|
|
477
|
+
case value
|
478
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
|
479
|
+
collector = visit value, collector
|
480
|
+
else
|
481
|
+
collector << quote(value, attr && column_for(attr)).to_s
|
482
|
+
end
|
483
|
+
collector << COMMA unless i == len
|
484
|
+
}
|
485
|
+
collector << ' FROM DUAL)'
|
481
486
|
end
|
482
487
|
collector << ")"
|
483
488
|
collector
|
@@ -498,7 +503,7 @@ module ArelExtensions
|
|
498
503
|
else
|
499
504
|
collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
|
500
505
|
end
|
501
|
-
collector <<
|
506
|
+
collector << COMMA unless i == len
|
502
507
|
}
|
503
508
|
collector << ' FROM DUAL)'
|
504
509
|
end
|
@@ -557,7 +562,7 @@ module ArelExtensions
|
|
557
562
|
end
|
558
563
|
|
559
564
|
|
560
|
-
alias_method
|
565
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
561
566
|
def visit_Arel_Nodes_SelectStatement o, collector
|
562
567
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
563
568
|
o = o.dup
|
@@ -566,7 +571,7 @@ module ArelExtensions
|
|
566
571
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
567
572
|
end
|
568
573
|
|
569
|
-
alias_method
|
574
|
+
alias_method(:old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias) rescue nil
|
570
575
|
def visit_Arel_Nodes_TableAlias o, collector
|
571
576
|
if o.name.length > 30
|
572
577
|
o = Arel::Table.new(o.table_name).alias(Base64.urlsafe_encode64(Digest::MD5.new.digest(o.name)).tr('=', '').tr('-', '_'))
|
@@ -574,7 +579,7 @@ module ArelExtensions
|
|
574
579
|
old_visit_Arel_Nodes_TableAlias(o,collector)
|
575
580
|
end
|
576
581
|
|
577
|
-
alias_method
|
582
|
+
alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
|
578
583
|
def visit_Arel_Nodes_As o, collector
|
579
584
|
if o.left.is_a?(Arel::Nodes::Binary)
|
580
585
|
collector << '('
|
@@ -594,7 +599,7 @@ module ArelExtensions
|
|
594
599
|
visit_Arel_Nodes_As o, collector
|
595
600
|
end
|
596
601
|
|
597
|
-
alias_method
|
602
|
+
alias_method(:old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute) rescue nil
|
598
603
|
def visit_Arel_Attributes_Attribute o, collector
|
599
604
|
join_name = o.relation.table_alias || o.relation.name
|
600
605
|
if join_name.length > 30
|
@@ -603,10 +608,9 @@ module ArelExtensions
|
|
603
608
|
collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
|
604
609
|
end
|
605
610
|
|
606
|
-
|
607
611
|
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
608
612
|
col = o.left.coalesce(0)
|
609
|
-
comma =
|
613
|
+
comma = NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
610
614
|
comma_in_format = o.precision == 0 ? '' : 'D'
|
611
615
|
nines_after = (1..o.precision-1).map{'9'}.join('')+'0'
|
612
616
|
if comma.length == 1
|
@@ -683,7 +687,6 @@ module ArelExtensions
|
|
683
687
|
collector << ')'
|
684
688
|
collector
|
685
689
|
end
|
686
|
-
|
687
690
|
end
|
688
691
|
end
|
689
692
|
end
|