arel_extensions 1.2.5 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -4
- data/README.md +7 -2
- data/Rakefile +23 -23
- data/arel_extensions.gemspec +1 -1
- data/functions.html +2 -2
- data/gemfiles/rails6.gemfile +30 -0
- data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
- data/generate_gems.sh +13 -0
- data/lib/arel_extensions.rb +4 -1
- data/lib/arel_extensions/boolean_functions.rb +0 -2
- data/lib/arel_extensions/common_sql_functions.rb +5 -4
- data/lib/arel_extensions/insert_manager.rb +24 -24
- data/lib/arel_extensions/math.rb +3 -3
- data/lib/arel_extensions/math_functions.rb +4 -4
- data/lib/arel_extensions/nodes/case.rb +0 -2
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/date_diff.rb +1 -3
- data/lib/arel_extensions/nodes/duration.rb +0 -2
- data/lib/arel_extensions/nodes/formatted_number.rb +20 -20
- data/lib/arel_extensions/nodes/json.rb +28 -30
- data/lib/arel_extensions/nodes/power.rb +5 -4
- data/lib/arel_extensions/nodes/replace.rb +23 -5
- data/lib/arel_extensions/nodes/round.rb +5 -5
- data/lib/arel_extensions/nodes/soundex.rb +14 -13
- data/lib/arel_extensions/nodes/substring.rb +8 -15
- data/lib/arel_extensions/nodes/trim.rb +1 -1
- data/lib/arel_extensions/nodes/union.rb +0 -1
- data/lib/arel_extensions/nodes/union_all.rb +0 -1
- data/lib/arel_extensions/predications.rb +16 -17
- data/lib/arel_extensions/string_functions.rb +12 -6
- data/lib/arel_extensions/tasks.rb +5 -5
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +13 -12
- data/lib/arel_extensions/visitors/mysql.rb +50 -35
- data/lib/arel_extensions/visitors/oracle.rb +7 -6
- data/lib/arel_extensions/visitors/oracle12.rb +1 -1
- data/lib/arel_extensions/visitors/postgresql.rb +45 -27
- data/lib/arel_extensions/visitors/sqlite.rb +41 -27
- data/lib/arel_extensions/visitors/to_sql.rb +18 -5
- data/test/visitors/test_bulk_insert_oracle.rb +6 -6
- data/test/visitors/test_bulk_insert_sqlite.rb +5 -5
- data/test/visitors/test_to_sql.rb +10 -2
- data/test/with_ar/all_agnostic_test.rb +44 -33
- data/test/with_ar/test_bulk_sqlite.rb +1 -1
- data/test/with_ar/test_math_sqlite.rb +1 -1
- data/test/with_ar/test_string_mysql.rb +1 -3
- data/test/with_ar/test_string_sqlite.rb +1 -5
- data/version_v1.rb +3 -0
- data/version_v2.rb +3 -0
- metadata +9 -4
@@ -97,26 +97,28 @@ module ArelExtensions
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def visit_ArelExtensions_Nodes_Collate o, collector
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
charset =
|
101
|
+
case o.expressions.first
|
102
|
+
when Arel::Attributes::Attribute
|
103
|
+
case o.option
|
103
104
|
when 'latin1','utf8'
|
104
105
|
o.option
|
105
106
|
else
|
106
107
|
Arel::Table.engine.connection.charset || 'utf8'
|
107
108
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
else
|
110
|
+
(o.option == 'latin1') ? 'latin1' : 'utf8'
|
111
|
+
end
|
111
112
|
collector = visit o.expressions.first, collector
|
112
|
-
|
113
|
-
|
113
|
+
collector <<
|
114
|
+
if o.ai
|
115
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
114
116
|
#doesn't work in latin1
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
117
|
+
elsif o.ci
|
118
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
119
|
+
else
|
120
|
+
" COLLATE #{charset}_bin"
|
121
|
+
end
|
120
122
|
collector
|
121
123
|
end
|
122
124
|
|
@@ -262,7 +264,7 @@ module ArelExtensions
|
|
262
264
|
else
|
263
265
|
if o.with_interval
|
264
266
|
case o.left
|
265
|
-
when
|
267
|
+
when 'd','m','y'
|
266
268
|
interval = 'DAY'
|
267
269
|
when 'h','mn','s'
|
268
270
|
interval = 'SECOND'
|
@@ -362,20 +364,21 @@ module ArelExtensions
|
|
362
364
|
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
363
365
|
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
364
366
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
367
|
+
number =
|
368
|
+
if o.scientific_notation
|
369
|
+
ArelExtensions::Nodes::Concat.new([
|
370
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
371
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
|
372
|
+
]+params),
|
373
|
+
o.type,
|
374
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
375
|
+
col.abs.log10.floor,
|
376
|
+
0
|
377
|
+
])
|
374
378
|
])
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
end
|
379
|
+
else
|
380
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
|
381
|
+
end
|
379
382
|
|
380
383
|
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
381
384
|
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
@@ -399,19 +402,19 @@ module ArelExtensions
|
|
399
402
|
end
|
400
403
|
|
401
404
|
def visit_Aggregate_For_AggregateFunction o, collector
|
402
|
-
if !
|
405
|
+
if !window_supported?
|
403
406
|
warn("Warning : ArelExtensions: Window Functions are not available in the current version on the DBMS.")
|
404
407
|
return collector
|
405
408
|
end
|
406
409
|
|
407
|
-
if o.order || o.group
|
410
|
+
if !o.order.empty? || !o.group.empty?
|
408
411
|
collector << " OVER ("
|
409
|
-
if o.group
|
412
|
+
if !o.group.empty?
|
410
413
|
collector << " PARTITION BY ("
|
411
414
|
visit o.group, collector
|
412
415
|
collector << ")"
|
413
416
|
end
|
414
|
-
if o.order
|
417
|
+
if !o.order.empty?
|
415
418
|
collector << " ORDER BY ("
|
416
419
|
visit o.order, collector
|
417
420
|
collector << ")"
|
@@ -433,15 +436,27 @@ module ArelExtensions
|
|
433
436
|
collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
|
434
437
|
visit o.left, collector
|
435
438
|
collector << ")"
|
439
|
+
visit_Aggregate_For_AggregateFunction o, collector
|
436
440
|
collector
|
437
441
|
end
|
438
442
|
|
439
443
|
# JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
|
440
444
|
def json_supported?
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
+
version_supported?('10.2.3', '5.7.0')
|
446
|
+
end
|
447
|
+
|
448
|
+
def window_supported?
|
449
|
+
version_supported?('10.2.3', '8.0')
|
450
|
+
end
|
451
|
+
|
452
|
+
def version_supported?(mysql_v = '10.2.3',mariadb_v = '5.7.0')
|
453
|
+
conn = Arel::Table.engine.connection
|
454
|
+
conn.send(:mariadb?) &&
|
455
|
+
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v ||
|
456
|
+
conn.respond_to?(:version) && conn.send(:version) >= mysql_v) ||
|
457
|
+
!Arel::Table.engine.connection.send(:mariadb?) &&
|
458
|
+
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v ||
|
459
|
+
conn.respond_to?(:version) && conn.send(:version) >= mariadb_v)
|
445
460
|
end
|
446
461
|
|
447
462
|
def visit_ArelExtensions_Nodes_Json o,collector
|
@@ -131,11 +131,12 @@ module ArelExtensions
|
|
131
131
|
collector << "(LISTAGG("
|
132
132
|
collector = visit o.left, collector
|
133
133
|
collector << Arel::Visitors::Oracle::COMMA
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
collector =
|
135
|
+
if o.separator && o.separator != 'NULL'
|
136
|
+
visit o.separator, collector
|
137
|
+
else
|
138
|
+
visit Arel::Nodes.build_quoted(','), collector
|
139
|
+
end
|
139
140
|
collector << ") WITHIN GROUP (ORDER BY "
|
140
141
|
if !o.order.blank?
|
141
142
|
o.order.each_with_index do |order,i|
|
@@ -154,7 +155,7 @@ module ArelExtensions
|
|
154
155
|
o.expressions.each_with_index { |arg, i|
|
155
156
|
collector << Arel::Visitors::Oracle::COMMA unless i == 0
|
156
157
|
if i > 0 && o.left_node_type == :text
|
157
|
-
if arg == ''
|
158
|
+
if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
|
158
159
|
collector << "NULL"
|
159
160
|
else
|
160
161
|
collector << 'TO_CLOB('
|
@@ -120,11 +120,12 @@ module ArelExtensions
|
|
120
120
|
o.order = nil
|
121
121
|
visit_Aggregate_For_AggregateFunction o, collector
|
122
122
|
collector << Arel::Visitors::PostgreSQL::COMMA
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
123
|
+
collector =
|
124
|
+
if o.separator && o.separator != 'NULL'
|
125
|
+
visit o.separator, collector
|
126
|
+
else
|
127
|
+
visit Arel::Nodes.build_quoted(','), collector
|
128
|
+
end
|
128
129
|
collector << ")"
|
129
130
|
collector
|
130
131
|
end
|
@@ -302,6 +303,22 @@ module ArelExtensions
|
|
302
303
|
collector
|
303
304
|
end
|
304
305
|
|
306
|
+
def visit_ArelExtensions_Nodes_RegexpReplace o, collector
|
307
|
+
collector << "REGEXP_REPLACE("
|
308
|
+
visit o.left, collector
|
309
|
+
collector << Arel::Visitors::ToSql::COMMA
|
310
|
+
tab = o.pattern.inspect+ 'g' # Make it always global
|
311
|
+
pattern = tab.split('/')[1..-2].join('/')
|
312
|
+
flags = tab.split('/')[-1]
|
313
|
+
visit Arel::Nodes.build_quoted(pattern), collector
|
314
|
+
collector << Arel::Visitors::ToSql::COMMA
|
315
|
+
visit o.substitute, collector
|
316
|
+
collector << Arel::Visitors::ToSql::COMMA
|
317
|
+
visit Arel::Nodes.build_quoted(flags+"g"), collector
|
318
|
+
collector << ")"
|
319
|
+
collector
|
320
|
+
end
|
321
|
+
|
305
322
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
306
323
|
collector = visit o.expr, collector
|
307
324
|
collector << ' IS NULL'
|
@@ -371,27 +388,28 @@ module ArelExtensions
|
|
371
388
|
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
372
389
|
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
373
390
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
391
|
+
number =
|
392
|
+
if o.scientific_notation
|
393
|
+
ArelExtensions::Nodes::Concat.new([
|
394
|
+
Arel::Nodes::NamedFunction.new('TRIM',[
|
395
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
396
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
397
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
398
|
+
])]),
|
399
|
+
o.type,
|
400
|
+
Arel::Nodes::NamedFunction.new('TRIM',[
|
401
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
402
|
+
col.abs.log10.floor,
|
403
|
+
Arel::Nodes.build_quoted('FM'+nines_before)
|
404
|
+
])])
|
405
|
+
])
|
406
|
+
else
|
407
|
+
Arel::Nodes::NamedFunction.new('TRIM',[
|
408
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
409
|
+
Arel::Nodes.build_quoted(col.abs),
|
410
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
411
|
+
])])
|
412
|
+
end
|
395
413
|
|
396
414
|
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
397
415
|
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
@@ -466,7 +484,7 @@ module ArelExtensions
|
|
466
484
|
if i != 0
|
467
485
|
collector << Arel::Visitors::MySQL::COMMA
|
468
486
|
end
|
469
|
-
collector
|
487
|
+
collector = visit v, collector
|
470
488
|
end
|
471
489
|
collector << '])'
|
472
490
|
when Hash
|
@@ -193,18 +193,28 @@ module ArelExtensions
|
|
193
193
|
collector
|
194
194
|
end
|
195
195
|
|
196
|
-
#
|
197
|
-
#
|
196
|
+
# CAST(
|
197
|
+
# CASE
|
198
|
+
# WHEN 3.42 >= 0 THEN CAST(3.42 AS INT)
|
199
|
+
# WHEN CAST(3.42 AS INT) = 3.42 THEN CAST(3.42 AS INT)
|
200
|
+
# ELSE CAST((3.42 - 1.0) AS INT)
|
201
|
+
# END
|
202
|
+
# AS FLOAT
|
203
|
+
# )
|
198
204
|
def visit_ArelExtensions_Nodes_Floor o, collector
|
199
|
-
collector << "CASE WHEN
|
205
|
+
collector << "CAST(CASE WHEN "
|
200
206
|
collector = visit o.left, collector
|
201
|
-
collector << "
|
207
|
+
collector << " >= 0 THEN CAST("
|
202
208
|
collector = visit o.left, collector
|
203
|
-
collector << ")
|
209
|
+
collector << " AS INT) WHEN CAST("
|
210
|
+
collector = visit o.left, collector
|
211
|
+
collector << " AS INT) = "
|
204
212
|
collector = visit o.left, collector
|
205
|
-
collector << "
|
213
|
+
collector << " THEN CAST("
|
206
214
|
collector = visit o.left, collector
|
207
|
-
collector << ")
|
215
|
+
collector << " AS INT) ELSE CAST(("
|
216
|
+
collector = visit o.left, collector
|
217
|
+
collector << " - 1.0) AS INT) END AS FLOAT)"
|
208
218
|
collector
|
209
219
|
end
|
210
220
|
|
@@ -270,32 +280,36 @@ module ArelExtensions
|
|
270
280
|
end
|
271
281
|
|
272
282
|
def visit_ArelExtensions_Nodes_Union o, collector
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
283
|
+
collector =
|
284
|
+
if o.left.is_a?(Arel::SelectManager)
|
285
|
+
visit o.left.ast, collector
|
286
|
+
else
|
287
|
+
visit o.left, collector
|
288
|
+
end
|
278
289
|
collector << " UNION "
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
290
|
+
collector =
|
291
|
+
if o.right.is_a?(Arel::SelectManager)
|
292
|
+
visit o.right.ast, collector
|
293
|
+
else
|
294
|
+
visit o.right, collector
|
295
|
+
end
|
284
296
|
collector
|
285
297
|
end
|
286
298
|
|
287
299
|
def visit_ArelExtensions_Nodes_UnionAll o, collector
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
300
|
+
collector =
|
301
|
+
if o.left.is_a?(Arel::SelectManager)
|
302
|
+
visit o.left.ast, collector
|
303
|
+
else
|
304
|
+
visit o.left, collector
|
305
|
+
end
|
293
306
|
collector << " UNION ALL "
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
307
|
+
collector =
|
308
|
+
if o.right.is_a?(Arel::SelectManager)
|
309
|
+
visit o.right.ast, collector
|
310
|
+
else
|
311
|
+
visit o.right, collector
|
312
|
+
end
|
299
313
|
collector
|
300
314
|
end
|
301
315
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Visitors
|
3
|
-
|
3
|
+
Arel::Visitors::ToSql.class_eval do
|
4
|
+
Arel::Visitors::ToSql::COMMA = ', ' unless defined?(Arel::Visitors::ToSql::COMMA)
|
4
5
|
|
5
6
|
# Math Functions
|
6
7
|
def visit_ArelExtensions_Nodes_Abs o, collector
|
@@ -134,10 +135,22 @@ module ArelExtensions
|
|
134
135
|
|
135
136
|
def visit_ArelExtensions_Nodes_Replace o, collector
|
136
137
|
collector << "REPLACE("
|
137
|
-
o.
|
138
|
-
|
139
|
-
|
140
|
-
|
138
|
+
visit o.left, collector
|
139
|
+
collector << Arel::Visitors::ToSql::COMMA
|
140
|
+
visit o.pattern, collector
|
141
|
+
collector << Arel::Visitors::ToSql::COMMA
|
142
|
+
visit o.substitute, collector
|
143
|
+
collector << ")"
|
144
|
+
collector
|
145
|
+
end
|
146
|
+
|
147
|
+
def visit_ArelExtensions_Nodes_RegexpReplace o, collector
|
148
|
+
collector << "REGEXP_REPLACE("
|
149
|
+
visit o.left, collector
|
150
|
+
collector << Arel::Visitors::ToSql::COMMA
|
151
|
+
visit Arel::Nodes.build_quoted(o.pattern.to_s), collector
|
152
|
+
collector << Arel::Visitors::ToSql::COMMA
|
153
|
+
visit o.substitute, collector
|
141
154
|
collector << ")"
|
142
155
|
collector
|
143
156
|
end
|
@@ -9,8 +9,8 @@ module ArelExtensions
|
|
9
9
|
@table = Arel::Table.new(:users)
|
10
10
|
@cols = ['name', 'comments', 'created_at']
|
11
11
|
@data = [
|
12
|
-
|
13
|
-
|
12
|
+
['nom1', "sdfdsfdsfsdf", '2016-01-01'],
|
13
|
+
['nom2', "sdfdsfdsfsdf", '2016-01-01']
|
14
14
|
]
|
15
15
|
end
|
16
16
|
|
@@ -24,11 +24,11 @@ module ArelExtensions
|
|
24
24
|
|
25
25
|
it "should import large set of data in Oracle" do
|
26
26
|
insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
insert_manager.bulk_insert(@cols, @data)
|
28
|
+
sql = compile(insert_manager.ast)
|
29
|
+
sql.must_be_like %Q[INSERT INTO "users" ("name", "comments", "created_at") ((SELECT 'nom1', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL) UNION ALL (SELECT 'nom2', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL))]
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
end
|
33
33
|
end
|
34
34
|
end
|
@@ -11,8 +11,8 @@ module ArelExtensions
|
|
11
11
|
Arel::Table.engine = @conn
|
12
12
|
@cols = ['id', 'name', 'comments', 'created_at']
|
13
13
|
@data = [
|
14
|
-
|
15
|
-
|
14
|
+
[23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
|
15
|
+
[25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
|
16
16
|
]
|
17
17
|
end
|
18
18
|
|
@@ -28,9 +28,9 @@ module ArelExtensions
|
|
28
28
|
insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
|
29
29
|
insert_manager.bulk_insert(@cols, @data)
|
30
30
|
sql = compile(insert_manager.ast)
|
31
|
-
|
31
|
+
sql.must_be_like %Q[INSERT INTO "users" ("id", "name", "comments", "created_at") SELECT 23 AS 'id', 'nom1' AS 'name', 'sdfdsfdsfsdf' AS 'comments', '2016-01-01' AS 'created_at' UNION ALL SELECT 25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01']
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
end
|
35
35
|
end
|
36
|
-
end
|
36
|
+
end
|