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,21 +1,22 @@
|
|
1
|
-
#
|
1
|
+
#require 'oracle_visitor'
|
2
2
|
module ArelExtensions
|
3
3
|
module Visitors
|
4
|
-
|
4
|
+
Arel::Visitors::Oracle.class_eval do
|
5
|
+
|
5
6
|
SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
|
6
|
-
DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
7
|
-
DATE_FORMAT_DIRECTIVES = {
|
7
|
+
Arel::Visitors::Oracle::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
8
|
+
Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES = {
|
8
9
|
'%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
|
9
10
|
'%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
|
10
11
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
11
12
|
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
12
13
|
}
|
13
|
-
NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
|
14
|
+
Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
|
14
15
|
|
15
16
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
16
17
|
collector << "LOG("
|
17
18
|
o.expressions.each_with_index { |arg, i|
|
18
|
-
collector << Arel::Visitors::ToSql::COMMA
|
19
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
19
20
|
collector = visit arg, collector
|
20
21
|
}
|
21
22
|
collector << ",10)"
|
@@ -25,7 +26,7 @@ module ArelExtensions
|
|
25
26
|
def visit_ArelExtensions_Nodes_Power o, collector
|
26
27
|
collector << "POWER("
|
27
28
|
o.expressions.each_with_index { |arg, i|
|
28
|
-
collector << Arel::Visitors::ToSql::COMMA
|
29
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
29
30
|
collector = visit arg, collector
|
30
31
|
}
|
31
32
|
collector << ")"
|
@@ -92,6 +93,7 @@ module ArelExtensions
|
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
96
|
+
|
95
97
|
def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
|
96
98
|
collector << 'LOWER('
|
97
99
|
collector = visit o.left, collector
|
@@ -110,35 +112,34 @@ module ArelExtensions
|
|
110
112
|
if o.ai
|
111
113
|
collector << "NLSSORT("
|
112
114
|
collector = visit o.expressions.first, collector
|
113
|
-
collector << COMMA
|
115
|
+
collector << Arel::Visitors::Oracle::COMMA
|
114
116
|
collector << "'NLS_SORT = BINARY_AI NLS_COMP = LINGUISTIC'"
|
115
117
|
collector << ")"
|
116
118
|
elsif o.ci
|
117
119
|
collector << "NLSSORT("
|
118
120
|
collector = visit o.expressions.first, collector
|
119
|
-
collector << COMMA
|
121
|
+
collector << Arel::Visitors::Oracle::COMMA
|
120
122
|
collector << "'NLS_SORT = BINARY_CI NLS_COMP = LINGUISTIC'"
|
121
123
|
collector << ")"
|
122
124
|
else
|
123
125
|
collector = visit o.expressions.first, collector
|
124
126
|
end
|
125
|
-
|
127
|
+
collector
|
126
128
|
end
|
127
129
|
|
128
130
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
129
131
|
collector << "(LISTAGG("
|
130
132
|
collector = visit o.left, collector
|
131
|
-
collector << COMMA
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
133
|
+
collector << Arel::Visitors::Oracle::COMMA
|
134
|
+
if o.right && o.right != 'NULL'
|
135
|
+
collector = visit o.right, collector
|
136
|
+
else
|
137
|
+
collector = visit Arel::Nodes.build_quoted(','), collector
|
138
|
+
end
|
138
139
|
collector << ") WITHIN GROUP (ORDER BY "
|
139
|
-
if !o.
|
140
|
-
o.
|
141
|
-
collector << COMMA
|
140
|
+
if !o.orders.blank?
|
141
|
+
o.orders.each_with_index do |order,i|
|
142
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
142
143
|
collector = visit order, collector
|
143
144
|
end
|
144
145
|
else
|
@@ -151,9 +152,9 @@ module ArelExtensions
|
|
151
152
|
def visit_ArelExtensions_Nodes_Coalesce o, collector
|
152
153
|
collector << "COALESCE("
|
153
154
|
o.expressions.each_with_index { |arg, i|
|
154
|
-
collector << COMMA
|
155
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
155
156
|
if i > 0 && o.left_node_type == :text
|
156
|
-
if arg == ''
|
157
|
+
if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
|
157
158
|
collector << "NULL"
|
158
159
|
else
|
159
160
|
collector << 'TO_CLOB('
|
@@ -194,7 +195,7 @@ module ArelExtensions
|
|
194
195
|
collector << 'TO_DATE(' if lc
|
195
196
|
collector = visit o.left, collector
|
196
197
|
collector << ')' if lc
|
197
|
-
collector << COMMA
|
198
|
+
collector << Arel::Visitors::Oracle::COMMA
|
198
199
|
collector << "'DDD') = "
|
199
200
|
collector << 'TO_DATE(' if lc
|
200
201
|
collector = visit o.left, collector
|
@@ -220,8 +221,8 @@ module ArelExtensions
|
|
220
221
|
when 'wd', 'w'
|
221
222
|
collector << "TO_CHAR("
|
222
223
|
collector = visit o.right, collector
|
223
|
-
collector << COMMA
|
224
|
-
collector = visit Arel::Nodes.build_quoted(DATE_MAPPING[o.left]), collector
|
224
|
+
collector << Arel::Visitors::Oracle::COMMA
|
225
|
+
collector = visit Arel::Nodes.build_quoted(Arel::Visitors::Oracle::DATE_MAPPING[o.left]), collector
|
225
226
|
else
|
226
227
|
right = case o.left
|
227
228
|
when 'd','m','y'
|
@@ -231,7 +232,7 @@ module ArelExtensions
|
|
231
232
|
interval = 'SECOND'
|
232
233
|
o.right.cast(:datetime)
|
233
234
|
when /i\z/
|
234
|
-
interval = DATE_MAPPING[o.left[0..-2]]
|
235
|
+
interval = Arel::Visitors::Oracle::DATE_MAPPING[o.left[0..-2]]
|
235
236
|
collector << '('
|
236
237
|
collector = visit o.right, collector
|
237
238
|
collector << ") * (INTERVAL '1' #{interval})"
|
@@ -240,7 +241,7 @@ module ArelExtensions
|
|
240
241
|
interval = nil
|
241
242
|
o.right
|
242
243
|
end
|
243
|
-
collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
|
244
|
+
collector << "EXTRACT(#{Arel::Visitors::Oracle::DATE_MAPPING[o.left]} FROM "
|
244
245
|
collector = visit right, collector
|
245
246
|
end
|
246
247
|
collector << ")"
|
@@ -255,16 +256,6 @@ module ArelExtensions
|
|
255
256
|
collector = visit o.left, collector
|
256
257
|
collector << ")"
|
257
258
|
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
|
268
259
|
when :time
|
269
260
|
if (o.left.respond_to?(:return_type) && o.left.return_type == :string) || o.left.is_a?(Arel::Nodes::Quoted)
|
270
261
|
collector << "TO_DATE("
|
@@ -330,7 +321,7 @@ module ArelExtensions
|
|
330
321
|
collector << "DBMS_RANDOM.VALUE("
|
331
322
|
if o.left && o.right
|
332
323
|
collector = visit o.left, collector
|
333
|
-
collector << COMMA
|
324
|
+
collector << Arel::Visitors::Oracle::COMMA
|
334
325
|
collector = visit o.right, collector
|
335
326
|
end
|
336
327
|
collector << ")"
|
@@ -340,7 +331,7 @@ module ArelExtensions
|
|
340
331
|
def visit_Arel_Nodes_Regexp o, collector
|
341
332
|
collector << " REGEXP_LIKE("
|
342
333
|
collector = visit o.left, collector
|
343
|
-
collector << COMMA
|
334
|
+
collector << Arel::Visitors::Oracle::COMMA
|
344
335
|
collector = visit o.right, collector
|
345
336
|
collector << ')'
|
346
337
|
collector
|
@@ -349,7 +340,7 @@ module ArelExtensions
|
|
349
340
|
def visit_Arel_Nodes_NotRegexp o, collector
|
350
341
|
collector << " NOT REGEXP_LIKE("
|
351
342
|
collector = visit o.left, collector
|
352
|
-
collector << COMMA
|
343
|
+
collector << Arel::Visitors::Oracle::COMMA
|
353
344
|
collector = visit o.right, collector
|
354
345
|
collector << ')'
|
355
346
|
collector
|
@@ -358,7 +349,7 @@ module ArelExtensions
|
|
358
349
|
def visit_ArelExtensions_Nodes_Locate o, collector
|
359
350
|
collector << "INSTR("
|
360
351
|
o.expressions.each_with_index { |arg, i|
|
361
|
-
collector << COMMA
|
352
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
362
353
|
collector = visit arg, collector
|
363
354
|
}
|
364
355
|
collector << ")"
|
@@ -368,7 +359,7 @@ module ArelExtensions
|
|
368
359
|
def visit_ArelExtensions_Nodes_Substring o, collector
|
369
360
|
collector << "SUBSTR("
|
370
361
|
o.expressions.each_with_index { |arg, i|
|
371
|
-
collector << COMMA
|
362
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
372
363
|
collector = visit arg, collector
|
373
364
|
}
|
374
365
|
collector << ")"
|
@@ -387,11 +378,11 @@ module ArelExtensions
|
|
387
378
|
if o.type_of_attribute(o.left) == :text
|
388
379
|
collector << 'dbms_lob.SUBSTR('
|
389
380
|
collector = visit o.left, collector
|
390
|
-
collector << COMMA
|
381
|
+
collector << Arel::Visitors::Oracle::COMMA
|
391
382
|
collector << 'COALESCE(dbms_lob.GETLENGTH('
|
392
383
|
collector = visit o.left, collector
|
393
384
|
collector << "), 0)"
|
394
|
-
collector << COMMA
|
385
|
+
collector << Arel::Visitors::Oracle::COMMA
|
395
386
|
collector << '1)'
|
396
387
|
else
|
397
388
|
collector = visit o.left, collector
|
@@ -438,25 +429,28 @@ module ArelExtensions
|
|
438
429
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
439
430
|
collector << '('
|
440
431
|
collector = visit o.left, collector
|
441
|
-
collector << ' + '
|
432
|
+
collector << ' + '# (o.right.value >= 0 ? ' + ' : ' - ')
|
442
433
|
collector = visit o.oracle_value(o.right), collector
|
443
434
|
collector << ')'
|
444
435
|
collector
|
445
436
|
end
|
446
437
|
|
447
438
|
def visit_ArelExtensions_Nodes_Format o, collector
|
448
|
-
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
449
439
|
collector << "TO_CHAR("
|
450
440
|
collector = visit o.left, collector
|
451
|
-
collector << COMMA
|
452
|
-
|
441
|
+
collector << Arel::Visitors::Oracle::COMMA
|
442
|
+
|
443
|
+
f = o.iso_format.gsub(/\ (\w+)/, ' "\1"')
|
444
|
+
Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
445
|
+
collector = visit Arel::Nodes.build_quoted(f), collector
|
446
|
+
|
453
447
|
collector << ")"
|
454
448
|
collector
|
455
449
|
end
|
456
450
|
|
457
451
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
458
452
|
collector << "LPAD("
|
459
|
-
collector = visit o.expressions[0], collector #
|
453
|
+
collector = visit o.expressions[0], collector #can't put empty string, otherwise it wouldn't work
|
460
454
|
collector << Arel::Visitors::ToSql::COMMA
|
461
455
|
collector = visit o.expressions[1], collector
|
462
456
|
collector << Arel::Visitors::ToSql::COMMA
|
@@ -465,24 +459,26 @@ module ArelExtensions
|
|
465
459
|
collector
|
466
460
|
end
|
467
461
|
|
468
|
-
|
462
|
+
# add primary_key if not present, avoid zip
|
469
463
|
if Arel::VERSION.to_i < 7
|
470
464
|
def visit_ArelExtensions_InsertManager_BulkValues o, collector
|
471
465
|
collector << "("
|
472
466
|
o.left.each_with_index do |row, idx| # values
|
473
467
|
collector << " UNION ALL " if idx != 0
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
468
|
+
collector << "(SELECT "
|
469
|
+
v = Arel::Nodes::Values.new(row, o.cols)
|
470
|
+
len = v.expressions.length - 1
|
471
|
+
v.expressions.each_with_index { |value, i|
|
472
|
+
case value
|
473
|
+
when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
|
474
|
+
collector = visit value, collector
|
475
|
+
else
|
476
|
+
attr = v.columns[i]
|
477
|
+
collector << quote(value, attr && column_for(attr)).to_s
|
478
|
+
end
|
479
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == len
|
480
|
+
}
|
481
|
+
collector << ' FROM DUAL)'
|
486
482
|
end
|
487
483
|
collector << ")"
|
488
484
|
collector
|
@@ -494,16 +490,15 @@ module ArelExtensions
|
|
494
490
|
collector << " UNION ALL " if idx != 0
|
495
491
|
collector << "(SELECT "
|
496
492
|
len = row.length - 1
|
497
|
-
row.
|
493
|
+
row.each_with_index { |value, i|
|
494
|
+
attr = o.cols[i]
|
498
495
|
case value
|
499
496
|
when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
|
500
497
|
collector = visit value, collector
|
501
|
-
when Integer
|
502
|
-
collector << value.to_s
|
503
498
|
else
|
504
499
|
collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
|
505
500
|
end
|
506
|
-
collector << COMMA unless i == len
|
501
|
+
collector << Arel::Visitors::Oracle::COMMA unless i == len
|
507
502
|
}
|
508
503
|
collector << ' FROM DUAL)'
|
509
504
|
end
|
@@ -562,7 +557,7 @@ module ArelExtensions
|
|
562
557
|
end
|
563
558
|
|
564
559
|
|
565
|
-
alias_method
|
560
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
566
561
|
def visit_Arel_Nodes_SelectStatement o, collector
|
567
562
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
568
563
|
o = o.dup
|
@@ -571,7 +566,7 @@ module ArelExtensions
|
|
571
566
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
572
567
|
end
|
573
568
|
|
574
|
-
alias_method
|
569
|
+
alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
|
575
570
|
def visit_Arel_Nodes_TableAlias o, collector
|
576
571
|
if o.name.length > 30
|
577
572
|
o = Arel::Table.new(o.table_name).alias(Base64.urlsafe_encode64(Digest::MD5.new.digest(o.name)).tr('=', '').tr('-', '_'))
|
@@ -579,7 +574,7 @@ module ArelExtensions
|
|
579
574
|
old_visit_Arel_Nodes_TableAlias(o,collector)
|
580
575
|
end
|
581
576
|
|
582
|
-
alias_method
|
577
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
583
578
|
def visit_Arel_Nodes_As o, collector
|
584
579
|
if o.left.is_a?(Arel::Nodes::Binary)
|
585
580
|
collector << '('
|
@@ -599,7 +594,7 @@ module ArelExtensions
|
|
599
594
|
visit_Arel_Nodes_As o, collector
|
600
595
|
end
|
601
596
|
|
602
|
-
alias_method
|
597
|
+
alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
|
603
598
|
def visit_Arel_Attributes_Attribute o, collector
|
604
599
|
join_name = o.relation.table_alias || o.relation.name
|
605
600
|
if join_name.length > 30
|
@@ -608,9 +603,10 @@ module ArelExtensions
|
|
608
603
|
collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
|
609
604
|
end
|
610
605
|
|
606
|
+
|
611
607
|
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
612
608
|
col = o.left.coalesce(0)
|
613
|
-
comma = NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
609
|
+
comma = Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
614
610
|
comma_in_format = o.precision == 0 ? '' : 'D'
|
615
611
|
nines_after = (1..o.precision-1).map{'9'}.join('')+'0'
|
616
612
|
if comma.length == 1
|
@@ -687,6 +683,7 @@ module ArelExtensions
|
|
687
683
|
collector << ')'
|
688
684
|
collector
|
689
685
|
end
|
686
|
+
|
690
687
|
end
|
691
688
|
end
|
692
689
|
end
|
@@ -1,7 +1,19 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
|
+
|
3
4
|
Arel::Visitors.send(:remove_const,'Oracle12') if Arel::Visitors.const_defined?('Oracle12')
|
4
5
|
Arel::Visitors.const_set('Oracle12',Class.new(Arel::Visitors::Oracle)).class_eval do
|
6
|
+
def visit_Arel_Nodes_SelectStatement(o, collector)
|
7
|
+
# Oracle does not allow LIMIT clause with select for update
|
8
|
+
if o.limit && o.lock
|
9
|
+
raise ArgumentError, <<-MSG
|
10
|
+
'Combination of limit and lock is not supported.
|
11
|
+
because generated SQL statements
|
12
|
+
`SELECT FOR UPDATE and FETCH FIRST n ROWS` generates ORA-02014.`
|
13
|
+
MSG
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
5
17
|
|
6
18
|
def visit_Arel_Nodes_SelectOptions(o, collector)
|
7
19
|
collector = maybe_visit o.offset, collector
|
@@ -56,7 +68,7 @@ module ArelExtensions
|
|
56
68
|
if i != 0
|
57
69
|
collector << Arel::Visitors::MySQL::COMMA
|
58
70
|
end
|
59
|
-
collector
|
71
|
+
collector = visit v, collector
|
60
72
|
end
|
61
73
|
collector << ')'
|
62
74
|
when Hash
|
@@ -72,7 +84,7 @@ module ArelExtensions
|
|
72
84
|
collector << 'FORMAT JSON'
|
73
85
|
end
|
74
86
|
collector << ')'
|
75
|
-
when String,
|
87
|
+
when String,Numeric,TrueClass,FalseClass
|
76
88
|
collector = visit Arel::Nodes.build_quoted("#{o.dict}"), collector
|
77
89
|
collector << ' FORMAT JSON'
|
78
90
|
when NilClass
|
@@ -85,6 +97,7 @@ module ArelExtensions
|
|
85
97
|
end
|
86
98
|
collector
|
87
99
|
end
|
100
|
+
|
88
101
|
end
|
89
102
|
end
|
90
103
|
end
|
@@ -1,29 +1,20 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
|
-
|
4
|
-
DATE_MAPPING = {
|
5
|
-
|
6
|
-
'
|
7
|
-
}.freeze
|
8
|
-
|
9
|
-
DATE_FORMAT_DIRECTIVES = {
|
10
|
-
'%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY',
|
11
|
-
'%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
|
3
|
+
Arel::Visitors::PostgreSQL.class_eval do
|
4
|
+
Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
5
|
+
Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
|
6
|
+
'%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
|
12
7
|
'%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
|
13
8
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
14
|
-
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz'
|
15
|
-
|
16
|
-
}
|
17
|
-
|
18
|
-
NUMBER_COMMA_MAPPING = {
|
19
|
-
'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '
|
20
|
-
}.freeze
|
9
|
+
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
10
|
+
}
|
11
|
+
Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
|
21
12
|
|
22
13
|
def visit_ArelExtensions_Nodes_Rand o, collector
|
23
14
|
collector << "RANDOM("
|
24
|
-
if
|
15
|
+
if(o.left != nil && o.right != nil)
|
25
16
|
collector = visit o.left, collector
|
26
|
-
collector << COMMA
|
17
|
+
collector << Arel::Visitors::PostgreSQL::COMMA
|
27
18
|
collector = isit o.right, collector
|
28
19
|
end
|
29
20
|
collector << ")"
|
@@ -33,7 +24,7 @@ module ArelExtensions
|
|
33
24
|
def visit_ArelExtensions_Nodes_Power o, collector
|
34
25
|
collector << "POWER("
|
35
26
|
o.expressions.each_with_index { |arg, i|
|
36
|
-
collector << Arel::Visitors::ToSql::COMMA
|
27
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
37
28
|
collector = visit arg, collector
|
38
29
|
}
|
39
30
|
collector << ")"
|
@@ -43,7 +34,7 @@ module ArelExtensions
|
|
43
34
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
44
35
|
collector << "LOG("
|
45
36
|
o.expressions.each_with_index { |arg, i|
|
46
|
-
collector << Arel::Visitors::ToSql::COMMA
|
37
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
47
38
|
collector = visit arg, collector
|
48
39
|
}
|
49
40
|
collector << ")"
|
@@ -77,7 +68,7 @@ module ArelExtensions
|
|
77
68
|
collector
|
78
69
|
end
|
79
70
|
|
80
|
-
alias_method
|
71
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
81
72
|
def visit_Arel_Nodes_As o, collector
|
82
73
|
if o.left.is_a?(Arel::Nodes::Binary)
|
83
74
|
collector << '('
|
@@ -92,49 +83,23 @@ module ArelExtensions
|
|
92
83
|
collector
|
93
84
|
end
|
94
85
|
|
95
|
-
def visit_Aggregate_For_AggregateFunction o, collector
|
96
|
-
if !o.order.blank? || !o.group.blank?
|
97
|
-
collector << " OVER ("
|
98
|
-
if !o.group.blank?
|
99
|
-
collector << " PARTITION BY "
|
100
|
-
o.group.each_with_index do |group, i|
|
101
|
-
collector << COMMA if i != 0
|
102
|
-
visit group, collector
|
103
|
-
end
|
104
|
-
end
|
105
|
-
if !o.order.blank?
|
106
|
-
collector << " ORDER BY "
|
107
|
-
o.order.each_with_index do |order, i|
|
108
|
-
collector << COMMA if i != 0
|
109
|
-
visit order, collector
|
110
|
-
end
|
111
|
-
end
|
112
|
-
collector << ")"
|
113
|
-
end
|
114
|
-
collector
|
115
|
-
end
|
116
|
-
|
117
86
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
118
87
|
collector << "array_to_string(array_agg("
|
119
88
|
collector = visit o.left, collector
|
120
|
-
if
|
121
|
-
collector <<
|
122
|
-
o.
|
123
|
-
collector << COMMA
|
124
|
-
collector
|
125
|
-
visit order, collector
|
89
|
+
if !o.orders.blank?
|
90
|
+
collector << ' ORDER BY '
|
91
|
+
o.orders.each_with_index do |order,i|
|
92
|
+
collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
|
93
|
+
collector = visit order, collector
|
126
94
|
end
|
127
95
|
end
|
128
96
|
collector << ")"
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
else
|
136
|
-
visit Arel::Nodes.build_quoted(','), collector
|
137
|
-
end
|
97
|
+
collector << Arel::Visitors::PostgreSQL::COMMA
|
98
|
+
if o.right && o.right != 'NULL'
|
99
|
+
collector = visit o.right, collector
|
100
|
+
else
|
101
|
+
collector = visit Arel::Nodes.build_quoted(','), collector
|
102
|
+
end
|
138
103
|
collector << ")"
|
139
104
|
collector
|
140
105
|
end
|
@@ -167,11 +132,14 @@ module ArelExtensions
|
|
167
132
|
end
|
168
133
|
|
169
134
|
def visit_ArelExtensions_Nodes_Format o, collector
|
170
|
-
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
171
135
|
collector << "TO_CHAR("
|
172
136
|
collector = visit o.left, collector
|
173
|
-
collector << COMMA
|
174
|
-
|
137
|
+
collector << Arel::Visitors::PostgreSQL::COMMA
|
138
|
+
|
139
|
+
f = o.iso_format.dup
|
140
|
+
Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
141
|
+
collector = visit Arel::Nodes.build_quoted(f), collector
|
142
|
+
|
175
143
|
collector << ")"
|
176
144
|
collector
|
177
145
|
end
|
@@ -179,7 +147,7 @@ module ArelExtensions
|
|
179
147
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
180
148
|
collector << "REPEAT("
|
181
149
|
o.expressions.each_with_index { |arg, i|
|
182
|
-
collector << Arel::Visitors::ToSql::COMMA
|
150
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
183
151
|
collector = visit arg, collector
|
184
152
|
}
|
185
153
|
collector << ")"
|
@@ -237,7 +205,7 @@ module ArelExtensions
|
|
237
205
|
|
238
206
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
239
207
|
collector = visit o.left, collector
|
240
|
-
collector << ' + ' #
|
208
|
+
collector << ' + ' #(o.right.value >= 0 ? ' + ' : ' - ')
|
241
209
|
collector = visit o.postgresql_value(o.right), collector
|
242
210
|
collector
|
243
211
|
end
|
@@ -251,7 +219,7 @@ module ArelExtensions
|
|
251
219
|
end
|
252
220
|
collector = visit o.right, collector
|
253
221
|
collector << (o.right_node_type == :date ? '::date' : '::timestamp')
|
254
|
-
collector << COMMA
|
222
|
+
collector << Arel::Visitors::PostgreSQL::COMMA
|
255
223
|
collector = visit o.left, collector
|
256
224
|
collector << (o.left_node_type == :date ? '::date' : '::timestamp')
|
257
225
|
collector << ")"
|
@@ -279,11 +247,11 @@ module ArelExtensions
|
|
279
247
|
collector << "("
|
280
248
|
collector = visit o.right, collector
|
281
249
|
collector << ")"
|
282
|
-
collector << " * (INTERVAL '1' #{DATE_MAPPING[o.left[0..-2]]})"
|
250
|
+
collector << " * (INTERVAL '1' #{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left[0..-2]]})"
|
283
251
|
return collector
|
284
252
|
end
|
285
253
|
end
|
286
|
-
collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
|
254
|
+
collector << "EXTRACT(#{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left]} FROM "
|
287
255
|
collector = visit o.right, collector
|
288
256
|
collector << ")"
|
289
257
|
collector << " * (INTERVAL '1' #{interval})" if interval && o.with_interval
|
@@ -302,29 +270,13 @@ module ArelExtensions
|
|
302
270
|
def visit_ArelExtensions_Nodes_Substring o, collector
|
303
271
|
collector << "SUBSTR("
|
304
272
|
o.expressions.each_with_index { |arg, i|
|
305
|
-
collector << COMMA
|
273
|
+
collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
|
306
274
|
collector = visit arg, collector
|
307
275
|
}
|
308
276
|
collector << ")"
|
309
277
|
collector
|
310
278
|
end
|
311
279
|
|
312
|
-
def visit_ArelExtensions_Nodes_RegexpReplace o, collector
|
313
|
-
collector << "REGEXP_REPLACE("
|
314
|
-
visit o.left, collector
|
315
|
-
collector << Arel::Visitors::ToSql::COMMA
|
316
|
-
tab = o.pattern.inspect+ 'g' # Make it always global
|
317
|
-
pattern = tab.split('/')[1..-2].join('/')
|
318
|
-
flags = tab.split('/')[-1]
|
319
|
-
visit Arel::Nodes.build_quoted(pattern), collector
|
320
|
-
collector << Arel::Visitors::ToSql::COMMA
|
321
|
-
visit o.substitute, collector
|
322
|
-
collector << Arel::Visitors::ToSql::COMMA
|
323
|
-
visit Arel::Nodes.build_quoted(flags+"g"), collector
|
324
|
-
collector << ")"
|
325
|
-
collector
|
326
|
-
end
|
327
|
-
|
328
280
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
329
281
|
collector = visit o.expr, collector
|
330
282
|
collector << ' IS NULL'
|
@@ -341,7 +293,6 @@ module ArelExtensions
|
|
341
293
|
collector << "sum("
|
342
294
|
collector = visit o.expr, collector
|
343
295
|
collector << ")"
|
344
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
345
296
|
collector
|
346
297
|
end
|
347
298
|
|
@@ -356,8 +307,6 @@ module ArelExtensions
|
|
356
307
|
as_attr = case o.as_attr
|
357
308
|
when :string
|
358
309
|
Arel::Nodes::SqlLiteral.new('varchar')
|
359
|
-
when :text, :ntext
|
360
|
-
Arel::Nodes::SqlLiteral.new('text')
|
361
310
|
when :time
|
362
311
|
Arel::Nodes::SqlLiteral.new('time')
|
363
312
|
when :int
|
@@ -386,8 +335,8 @@ module ArelExtensions
|
|
386
335
|
|
387
336
|
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
388
337
|
col = o.left.coalesce(0)
|
389
|
-
comma = o.precision == 0 ? '' : (NUMBER_COMMA_MAPPING[o.locale][0] || '.')
|
390
|
-
thousand_separator = NUMBER_COMMA_MAPPING[o.locale][1] || (NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
|
338
|
+
comma = o.precision == 0 ? '' : (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][0] || '.')
|
339
|
+
thousand_separator = Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][1] || (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
|
391
340
|
nines_after = (1..o.precision).map{'9'}.join('')
|
392
341
|
nines_before = ("999#{thousand_separator}"*4+"990")
|
393
342
|
|
@@ -396,28 +345,27 @@ module ArelExtensions
|
|
396
345
|
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
397
346
|
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
398
347
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
end
|
348
|
+
if o.scientific_notation
|
349
|
+
number = ArelExtensions::Nodes::Concat.new([
|
350
|
+
Arel::Nodes::NamedFunction.new('TRIM',[
|
351
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
352
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
353
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
354
|
+
])]),
|
355
|
+
o.type,
|
356
|
+
Arel::Nodes::NamedFunction.new('TRIM',[
|
357
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
358
|
+
col.abs.log10.floor,
|
359
|
+
Arel::Nodes.build_quoted('FM'+nines_before)
|
360
|
+
])])
|
361
|
+
])
|
362
|
+
else
|
363
|
+
number = Arel::Nodes::NamedFunction.new('TRIM',[
|
364
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
365
|
+
Arel::Nodes.build_quoted(col.abs),
|
366
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
367
|
+
])])
|
368
|
+
end
|
421
369
|
|
422
370
|
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
423
371
|
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
@@ -441,7 +389,7 @@ module ArelExtensions
|
|
441
389
|
end
|
442
390
|
|
443
391
|
|
444
|
-
alias_method
|
392
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
445
393
|
def visit_Arel_Nodes_SelectStatement o, collector
|
446
394
|
|
447
395
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
@@ -451,7 +399,7 @@ module ArelExtensions
|
|
451
399
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
452
400
|
end
|
453
401
|
|
454
|
-
alias_method
|
402
|
+
alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
|
455
403
|
def visit_Arel_Nodes_TableAlias o, collector
|
456
404
|
if o.name.length > 63
|
457
405
|
o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
|
@@ -459,7 +407,7 @@ module ArelExtensions
|
|
459
407
|
old_visit_Arel_Nodes_TableAlias(o,collector)
|
460
408
|
end
|
461
409
|
|
462
|
-
alias_method
|
410
|
+
alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
|
463
411
|
def visit_Arel_Attributes_Attribute o, collector
|
464
412
|
join_name = o.relation.table_alias || o.relation.name
|
465
413
|
if join_name.length > 63
|
@@ -472,7 +420,6 @@ module ArelExtensions
|
|
472
420
|
collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
|
473
421
|
visit o.left, collector
|
474
422
|
collector << ")"
|
475
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
476
423
|
collector
|
477
424
|
end
|
478
425
|
|
@@ -480,7 +427,6 @@ module ArelExtensions
|
|
480
427
|
collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
|
481
428
|
visit o.left, collector
|
482
429
|
collector << ")"
|
483
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
484
430
|
collector
|
485
431
|
end
|
486
432
|
|
@@ -492,7 +438,7 @@ module ArelExtensions
|
|
492
438
|
if i != 0
|
493
439
|
collector << Arel::Visitors::MySQL::COMMA
|
494
440
|
end
|
495
|
-
collector
|
441
|
+
collector = visit v, collector
|
496
442
|
end
|
497
443
|
collector << '])'
|
498
444
|
when Hash
|
@@ -577,6 +523,7 @@ module ArelExtensions
|
|
577
523
|
end
|
578
524
|
collector
|
579
525
|
end
|
526
|
+
|
580
527
|
end
|
581
528
|
end
|
582
529
|
end
|