arel_extensions 1.2.13 → 1.2.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/Gemfile +10 -10
- data/Rakefile +4 -4
- data/arel_extensions.gemspec +1 -1
- 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 +68 -60
- 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 +49 -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 +4 -3
@@ -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
|