arel_extensions 1.3.4 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +162 -222
- data/.gitignore +7 -6
- data/.rubocop.yml +37 -0
- data/Gemfile +3 -3
- data/NEWS.md +15 -0
- data/README.md +119 -75
- data/appveyor.yml +82 -0
- data/arel_extensions.gemspec +0 -1
- data/gemfiles/rails3.gemfile +5 -5
- data/gemfiles/rails4_2.gemfile +38 -0
- data/gemfiles/{rails5_0.gemfile → rails5.gemfile} +6 -6
- data/gemfiles/rails5_1_4.gemfile +6 -6
- data/gemfiles/rails5_2.gemfile +6 -5
- data/gemfiles/rails6.gemfile +5 -4
- data/gemfiles/rails6_1.gemfile +5 -4
- data/gemfiles/rails7.gemfile +5 -4
- data/gemspecs/arel_extensions-v1.gemspec +0 -1
- data/gemspecs/arel_extensions-v2.gemspec +0 -1
- data/lib/arel_extensions/common_sql_functions.rb +2 -2
- data/lib/arel_extensions/helpers.rb +12 -12
- data/lib/arel_extensions/math.rb +32 -17
- data/lib/arel_extensions/nodes/case.rb +4 -3
- data/lib/arel_extensions/nodes/cast.rb +2 -2
- data/lib/arel_extensions/nodes/coalesce.rb +1 -1
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/date_diff.rb +6 -6
- data/lib/arel_extensions/nodes/locate.rb +1 -1
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/rollup.rb +36 -0
- data/lib/arel_extensions/nodes/select.rb +10 -0
- data/lib/arel_extensions/nodes/substring.rb +1 -1
- data/lib/arel_extensions/nodes/then.rb +1 -1
- data/lib/arel_extensions/nodes/trim.rb +2 -2
- data/lib/arel_extensions/nodes/union.rb +3 -3
- data/lib/arel_extensions/nodes/union_all.rb +2 -2
- data/lib/arel_extensions/null_functions.rb +16 -0
- data/lib/arel_extensions/string_functions.rb +1 -0
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +123 -17
- data/lib/arel_extensions/visitors/mysql.rb +78 -11
- data/lib/arel_extensions/visitors/oracle.rb +39 -17
- data/lib/arel_extensions/visitors/postgresql.rb +17 -12
- data/lib/arel_extensions/visitors/sqlite.rb +4 -4
- data/lib/arel_extensions/visitors/to_sql.rb +4 -1
- data/lib/arel_extensions/visitors.rb +8 -0
- data/lib/arel_extensions.rb +26 -0
- data/test/arelx_test_helper.rb +1 -1
- data/test/real_db_test.rb +5 -5
- data/test/support/fake_record.rb +1 -1
- data/test/visitors/test_bulk_insert_oracle.rb +3 -3
- data/test/visitors/test_bulk_insert_sqlite.rb +1 -1
- data/test/visitors/test_bulk_insert_to_sql.rb +1 -1
- data/test/visitors/test_to_sql.rb +6 -6
- data/test/with_ar/all_agnostic_test.rb +177 -70
- data/test/with_ar/insert_agnostic_test.rb +3 -3
- data/test/with_ar/test_bulk_sqlite.rb +1 -1
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +8 -18
- data/gemfiles/rails4.gemfile +0 -29
@@ -73,6 +73,8 @@ module ArelExtensions
|
|
73
73
|
@neg = User.where(id: u.id)
|
74
74
|
u = User.create age: 15, name: 'Justin', created_at: d, score: 11.0
|
75
75
|
@justin = User.where(id: u.id)
|
76
|
+
u = User.create age: nil, name: 'nilly', created_at: nil, score: nil
|
77
|
+
@nilly = User.where(id: u.id)
|
76
78
|
|
77
79
|
@age = User.arel_table[:age]
|
78
80
|
@name = User.arel_table[:name]
|
@@ -149,7 +151,7 @@ module ArelExtensions
|
|
149
151
|
def test_rand
|
150
152
|
assert 42 != User.select(Arel.rand.as('res')).first.res
|
151
153
|
assert 0 <= User.select(Arel.rand.abs.as('res')).first.res
|
152
|
-
assert_equal
|
154
|
+
assert_equal 10, User.order(Arel.rand).limit(50).count
|
153
155
|
end
|
154
156
|
|
155
157
|
def test_round
|
@@ -186,6 +188,49 @@ module ArelExtensions
|
|
186
188
|
assert User.group(:score).count(:id).values.all?{|e| !e.nil?}
|
187
189
|
end
|
188
190
|
|
191
|
+
def test_rollup
|
192
|
+
skip "sqlite not supported" if $sqlite
|
193
|
+
at = User.arel_table
|
194
|
+
# single
|
195
|
+
q = User.select(at[:name], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:name]]))
|
196
|
+
assert q.to_a.length > 0
|
197
|
+
|
198
|
+
# multi
|
199
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:score], at[:name]]))
|
200
|
+
assert q.to_a.length > 0
|
201
|
+
|
202
|
+
# hybrid
|
203
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel::Nodes::RollUp.new([at[:name]]))
|
204
|
+
assert q.to_a.length > 0
|
205
|
+
|
206
|
+
## Using Arel.rollup which is less verbose than the original way
|
207
|
+
|
208
|
+
# simple
|
209
|
+
q = User.select(at[:name], at[:age].sum).group(Arel.rollup(at[:name]))
|
210
|
+
assert q.to_a.length > 0
|
211
|
+
|
212
|
+
# multi
|
213
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(Arel.rollup([at[:score], at[:name]]))
|
214
|
+
assert q.to_a.length > 0
|
215
|
+
|
216
|
+
# hybrid
|
217
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel.rollup([at[:name]]))
|
218
|
+
assert q.to_a.length > 0
|
219
|
+
|
220
|
+
## Using at[:col].rollup which is handy for single column rollups
|
221
|
+
|
222
|
+
# simple
|
223
|
+
q = User.select(at[:name], at[:age].sum).group(at[:name].rollup)
|
224
|
+
assert q.to_a.length > 0
|
225
|
+
|
226
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name].rollup, at[:score].rollup)
|
227
|
+
assert q.to_a.length > 0
|
228
|
+
|
229
|
+
# hybrid
|
230
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name], at[:score].rollup)
|
231
|
+
assert q.to_a.length > 0
|
232
|
+
end
|
233
|
+
|
189
234
|
# String Functions
|
190
235
|
def test_concat
|
191
236
|
assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
|
@@ -193,16 +238,16 @@ module ArelExtensions
|
|
193
238
|
assert_equal 'Test Laure', t(@laure, Arel.quoted('Test ') + @name)
|
194
239
|
|
195
240
|
skip 'No group_concat in SqlServer before 2017' if @env_db == 'mssql'
|
196
|
-
assert_equal 'Lucas Sophie', t(User.where(name: [
|
197
|
-
assert_equal 'Lucas,Sophie', t(User.where(name: [
|
198
|
-
assert_equal 'Lucas,Sophie', t(User.where(name: [
|
241
|
+
assert_equal 'Lucas Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(' '))
|
242
|
+
assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(','))
|
243
|
+
assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat)
|
199
244
|
|
200
245
|
skip 'No order in group_concat in SqlLite' if $sqlite
|
201
|
-
assert_equal 'Arthur,Lucas,Sophie', t(User.where(name: [
|
202
|
-
assert_equal 'Sophie,Lucas,Arthur', t(User.where(name: [
|
203
|
-
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: [
|
204
|
-
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: [
|
205
|
-
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: [
|
246
|
+
assert_equal 'Arthur,Lucas,Sophie', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.asc))
|
247
|
+
assert_equal 'Sophie,Lucas,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.desc))
|
248
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', [@score.asc, @name.asc]))
|
249
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @score.asc, @name.asc))
|
250
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', order: [@score.asc, @name.asc]))
|
206
251
|
end
|
207
252
|
|
208
253
|
def test_length
|
@@ -294,16 +339,16 @@ module ArelExtensions
|
|
294
339
|
skip "Sqlite version can't load extension for regexp" if $sqlite && $load_extension_disabled
|
295
340
|
skip 'SQL Server does not know about REGEXP without extensions' if @env_db == 'mssql'
|
296
341
|
assert_equal 1, User.where(@name =~ '^M').count
|
297
|
-
assert_equal
|
342
|
+
assert_equal 8, User.where(@name !~ '^L').count
|
298
343
|
assert_equal 1, User.where(@name =~ /^M/).count
|
299
|
-
assert_equal
|
344
|
+
assert_equal 8, User.where(@name !~ /^L/).count
|
300
345
|
end
|
301
346
|
|
302
347
|
def test_imatches
|
303
348
|
# puts User.where(@name.imatches('m%')).to_sql
|
304
349
|
assert_equal 1, User.where(@name.imatches('m%')).count
|
305
350
|
assert_equal 4, User.where(@name.imatches_any(['L%', '%e'])).count
|
306
|
-
assert_equal
|
351
|
+
assert_equal 8, User.where(@name.idoes_not_match('L%')).count
|
307
352
|
end
|
308
353
|
|
309
354
|
def test_replace
|
@@ -328,8 +373,8 @@ module ArelExtensions
|
|
328
373
|
skip "Sqlite version can't load extension for soundex" if $sqlite && $load_extension_disabled
|
329
374
|
skip "PostgreSql version can't load extension for soundex" if @env_db == 'postgresql'
|
330
375
|
assert_equal 'C540', t(@camille, @name.soundex)
|
331
|
-
assert_equal
|
332
|
-
assert_equal
|
376
|
+
assert_equal 10, User.where(@name.soundex.eq(@name.soundex)).count
|
377
|
+
assert_equal 10, User.where(@name.soundex == @name.soundex).count
|
333
378
|
end
|
334
379
|
|
335
380
|
def test_change_case
|
@@ -374,6 +419,23 @@ module ArelExtensions
|
|
374
419
|
assert_equal 'true', t(@neg, @comments.not_blank.then('true', 'false'))
|
375
420
|
end
|
376
421
|
|
422
|
+
# This test repeats a lot of `test_blank` cases.
|
423
|
+
def test_present
|
424
|
+
if @env_db == 'postgresql'
|
425
|
+
assert_includes [true, 't'], t(@myung, @name.present) # depends of adapter
|
426
|
+
assert_includes [false, 'f'], t(@myung, @comments.present)
|
427
|
+
end
|
428
|
+
assert_equal 1, @myung.where(@name.present).count
|
429
|
+
assert_equal 0, @myung.where(@comments.present).count
|
430
|
+
assert_equal 0, @sophie.where(@comments.present).count
|
431
|
+
assert_equal 0, @camille.where(@comments.present).count
|
432
|
+
|
433
|
+
assert_equal 1, @neg.where(@comments.present).count
|
434
|
+
assert_equal 'true', t(@myung, @name.present.then('true', 'false'))
|
435
|
+
assert_equal 'false', t(@myung, @comments.present.then('true', 'false'))
|
436
|
+
assert_equal 'true', t(@neg, @comments.present.then('true', 'false'))
|
437
|
+
end
|
438
|
+
|
377
439
|
def test_format
|
378
440
|
assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
|
379
441
|
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
|
@@ -419,27 +481,32 @@ module ArelExtensions
|
|
419
481
|
}
|
420
482
|
}
|
421
483
|
|
422
|
-
skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if
|
484
|
+
skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
|
485
|
+
# TODO: Standarize timezone conversion across all databases.
|
486
|
+
# This test case will be refactored and should work the same across all vendors.
|
487
|
+
if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
|
488
|
+
skip "SQL Server < 2016 is not currently supported"
|
489
|
+
end
|
423
490
|
|
424
491
|
tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
|
425
492
|
|
426
493
|
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
|
427
|
-
assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {
|
428
|
-
assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {
|
494
|
+
assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
|
495
|
+
assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
|
429
496
|
|
430
497
|
# Skipping conversion from UTC to the desired timezones fails in SQL
|
431
498
|
# Server and Postgres. This is mainly due to the fact that timezone
|
432
499
|
# information is not preserved in the column itself.
|
433
500
|
#
|
434
501
|
# MySQL is happy to consider that times by default are in UTC.
|
435
|
-
assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {
|
502
|
+
assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
436
503
|
refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['paris'])) if !['mysql'].include?(ENV['DB'])
|
437
504
|
|
438
505
|
# Winter/Summer time
|
439
|
-
assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).format('%Y/%m/%d %H:%M:%S', {
|
506
|
+
assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
440
507
|
if ENV['DB'] == 'mssql'
|
441
|
-
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {
|
442
|
-
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {
|
508
|
+
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
509
|
+
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
443
510
|
else
|
444
511
|
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
445
512
|
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
@@ -463,7 +530,7 @@ module ArelExtensions
|
|
463
530
|
end
|
464
531
|
|
465
532
|
def test_format_iso_year_of_week
|
466
|
-
skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if [
|
533
|
+
skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if %w[mssql sqlite].include?(ENV['DB'])
|
467
534
|
assert_equal '2014', t(@lucas, @updated_at.format('%G'))
|
468
535
|
|
469
536
|
{
|
@@ -480,7 +547,7 @@ module ArelExtensions
|
|
480
547
|
end
|
481
548
|
|
482
549
|
def test_format_date_with_names
|
483
|
-
skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if [
|
550
|
+
skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if %w[mssql sqlite].include?(ENV['DB'])
|
484
551
|
assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
|
485
552
|
assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
486
553
|
|
@@ -491,9 +558,9 @@ module ArelExtensions
|
|
491
558
|
|
492
559
|
def switch_to_lang(lang)
|
493
560
|
languages = {
|
494
|
-
'mssql' => {
|
495
|
-
'mysql' => {
|
496
|
-
'postgresql' => {
|
561
|
+
'mssql' => {en: 'English', fr: 'French'},
|
562
|
+
'mysql' => {en: 'en_US', fr: 'fr_FR'},
|
563
|
+
'postgresql' => {en: 'en_US.utf8', fr: 'fr_FR.utf8'}
|
497
564
|
}
|
498
565
|
|
499
566
|
sql = {
|
@@ -513,27 +580,29 @@ module ArelExtensions
|
|
513
580
|
#
|
514
581
|
# Tests should assert one single thing in principle, but until we
|
515
582
|
# refactor this whole thing, we'll have to do tricks of this sort.
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
583
|
+
begin
|
584
|
+
switch_to_lang(:en)
|
585
|
+
case ENV['DB']
|
586
|
+
when 'mysql', 'postgresql'
|
587
|
+
assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
|
588
|
+
assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
589
|
+
when 'mssql'
|
590
|
+
assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
591
|
+
end
|
592
|
+
switch_to_lang(:fr)
|
593
|
+
case ENV['DB']
|
594
|
+
when 'mysql'
|
595
|
+
assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
|
596
|
+
assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
597
|
+
when 'postgresql'
|
598
|
+
assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.format('%a, %d %b %y'))
|
599
|
+
assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
600
|
+
when 'mssql'
|
601
|
+
assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.format('%A, %d %B %y'))
|
602
|
+
end
|
603
|
+
ensure
|
604
|
+
switch_to_lang(:en)
|
534
605
|
end
|
535
|
-
ensure
|
536
|
-
switch_to_lang(:en)
|
537
606
|
end
|
538
607
|
|
539
608
|
def test_coalesce
|
@@ -558,6 +627,24 @@ module ArelExtensions
|
|
558
627
|
assert_equal 'Laure10', t(@laure, @comments.coalesce('Laure') + 10)
|
559
628
|
end
|
560
629
|
|
630
|
+
def test_coalesce_blank
|
631
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('Myung').coalesce_blank('ignored'))
|
632
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ').coalesce_blank('Myung'))
|
633
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ', 'Myung'))
|
634
|
+
assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format('%Y-%m-%d'))
|
635
|
+
assert_equal 'Laure', t(@laure, @comments.coalesce_blank('Laure'))
|
636
|
+
assert_equal 100, t(@test, @age.coalesce_blank(100))
|
637
|
+
assert_equal 20, t(@test, @age.coalesce_blank(20))
|
638
|
+
assert_equal 20, t(@test, @age.coalesce_blank(10) + 10)
|
639
|
+
assert_equal 'Laure10', t(@laure, @comments.coalesce_blank('Laure') + 10)
|
640
|
+
|
641
|
+
skip 'mssql does not support null in case results' if @env_db == 'mssql'
|
642
|
+
|
643
|
+
assert_equal 'Camille concat', t(@camille, @name.coalesce_blank(Arel.null, 'default') + ' concat')
|
644
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank(Arel.null, 'Myung'))
|
645
|
+
assert_equal 'Camille', t(@camille, @name.coalesce_blank(Arel.null, 'default'))
|
646
|
+
end
|
647
|
+
|
561
648
|
# Comparators
|
562
649
|
def test_number_comparator
|
563
650
|
assert_equal 2, User.where(@age < 6).count
|
@@ -570,7 +657,7 @@ module ArelExtensions
|
|
570
657
|
def test_date_comparator
|
571
658
|
d = Date.new(2016, 5, 23)
|
572
659
|
assert_equal 0, User.where(@created_at < d).count
|
573
|
-
assert_equal
|
660
|
+
assert_equal 10, User.where(@created_at >= d).count
|
574
661
|
end
|
575
662
|
|
576
663
|
def test_date_duration
|
@@ -602,8 +689,8 @@ module ArelExtensions
|
|
602
689
|
def test_datetime_diff
|
603
690
|
assert_equal 0, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 42)).to_i
|
604
691
|
if @env_db == 'oracle' && Arel::VERSION.to_i > 6 # in rails 5, result is multiplied by 24*60*60 = 86400...
|
605
|
-
assert_equal 42 *
|
606
|
-
assert_equal(-3600 *
|
692
|
+
assert_equal 42 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
|
693
|
+
assert_equal(-3600 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
|
607
694
|
else
|
608
695
|
assert_equal 42, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
|
609
696
|
assert_equal(-3600, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
|
@@ -658,12 +745,12 @@ module ArelExtensions
|
|
658
745
|
# TODO; cast types
|
659
746
|
def test_cast_types
|
660
747
|
assert_equal '5', t(@lucas, @age.cast(:string))
|
661
|
-
skip 'jdbc adapters does not work properly here (v52 works fine)' if RUBY_PLATFORM
|
748
|
+
skip 'jdbc adapters does not work properly here (v52 works fine)' if RUBY_PLATFORM.match?(/java/i)
|
662
749
|
if @env_db == 'mysql' || @env_db == 'postgresql' || @env_db == 'oracle' || @env_db == 'mssql'
|
663
750
|
assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).cast(:string).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle' || @env_db == 'mssql'
|
664
751
|
assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle'
|
665
|
-
assert_equal '20.16', t(@laure, @score.cast(:string)).gsub(/
|
666
|
-
assert_equal '20.161', t(@laure, @score.cast(:string) + 1).gsub(/
|
752
|
+
assert_equal '20.16', t(@laure, @score.cast(:string)).gsub(/0*\z/, '')
|
753
|
+
assert_equal '20.161', t(@laure, @score.cast(:string) + 1).gsub(/0*1\z/, '1')
|
667
754
|
assert_equal 21.16, t(@laure, @score.cast(:string).cast(:decimal) + 1)
|
668
755
|
assert_equal 21, t(@laure, @score.cast(:string).cast(:int) + 1)
|
669
756
|
|
@@ -683,6 +770,26 @@ module ArelExtensions
|
|
683
770
|
end
|
684
771
|
end
|
685
772
|
|
773
|
+
def test_if_present
|
774
|
+
assert_nil t(@myung, @comments.if_present)
|
775
|
+
assert_equal 0, t(@myung, @comments.if_present.count)
|
776
|
+
assert_equal 20.16, t(@myung, @score.if_present)
|
777
|
+
assert_equal '2016-05-23', t(@myung, @created_at.if_present.format('%Y-%m-%d'))
|
778
|
+
assert_nil t(@laure, @comments.if_present)
|
779
|
+
|
780
|
+
assert_nil t(@nilly, @duration.if_present.format('%Y-%m-%d'))
|
781
|
+
|
782
|
+
# NOTE: here we're testing the capacity to format a nil value,
|
783
|
+
# however, @comments is a text field, and not a date/datetime field,
|
784
|
+
# so Postgres will rightfully complain when we format the text:
|
785
|
+
# we need to cast it first.
|
786
|
+
if @env_db == 'postgresql'
|
787
|
+
assert_nil t(@laure, @comments.cast(:date).if_present.format('%Y-%m-%d'))
|
788
|
+
else
|
789
|
+
assert_nil t(@laure, @comments.if_present.format('%Y-%m-%d'))
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
686
793
|
def test_is_null
|
687
794
|
# puts User.where(@age.is_null).select(@name).to_sql
|
688
795
|
# puts @age.is_null
|
@@ -718,7 +825,7 @@ module ArelExtensions
|
|
718
825
|
def test_math_minus
|
719
826
|
d = Date.new(2016, 5, 20)
|
720
827
|
# Datediff
|
721
|
-
assert_equal
|
828
|
+
assert_equal 10, User.where((@created_at - @created_at).eq(0)).count
|
722
829
|
assert_equal 3, @laure.select((@created_at - d).as('res')).first.res.abs.to_i
|
723
830
|
# Substraction
|
724
831
|
assert_equal 0, User.where((@age - 10).eq(50)).count
|
@@ -747,8 +854,8 @@ module ArelExtensions
|
|
747
854
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(23)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
|
748
855
|
assert_equal 2, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
|
749
856
|
|
750
|
-
assert_equal 3, User.find_by_sql(
|
751
|
-
assert_equal 3, User.find_by_sql(
|
857
|
+
assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0))).to_sql).length
|
858
|
+
assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21))).to_sql).length
|
752
859
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0)))).as('my_union')).length
|
753
860
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(23))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
|
754
861
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
|
@@ -786,10 +893,10 @@ module ArelExtensions
|
|
786
893
|
assert_includes ['$ 6,56e1 €', '$ 6,56e+01 €'], t(@arthur, @score.format_number('$ %.2e €', 'fr_FR'))
|
787
894
|
assert_includes ['$ 6,56E1 €', '$ 6,56E+01 €'], t(@arthur, @score.format_number('$ %.2E €', 'fr_FR'))
|
788
895
|
assert_includes ['$ 6,562E1 €', '$ 6,562E+01 €'], t(@arthur, @score.format_number('$ %.3E €', 'fr_FR'))
|
789
|
-
assert_equal '123 456 765,6', t(@arthur, (@score +
|
790
|
-
assert_equal '123456765,6', t(@arthur, (@score +
|
791
|
-
assert_equal '123,456,765.6', t(@arthur, (@score +
|
792
|
-
assert_equal ' 123,456,765.6', t(@arthur, (@score +
|
896
|
+
assert_equal '123 456 765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'sv_SE')).tr("\u00A0", ' ') # some DBMS put no-break space here (it makes sense thus)
|
897
|
+
assert_equal '123456765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'fr_FR')).delete("\u00A0") # because SqlServer does it like no one else
|
898
|
+
assert_equal '123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'en_US'))
|
899
|
+
assert_equal ' 123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%16.1f', 'en_US'))
|
793
900
|
assert_equal '$ 0,00 €', t(@arthur, @score.when(65.62).then(Arel.sql('null')).else(1).format_number('$ %.2f €', 'fr_FR'))
|
794
901
|
assert_equal '$ 0,00 €', t(@arthur, (@score - 65.62).format_number('$ %.2f €', 'fr_FR'))
|
795
902
|
end
|
@@ -811,7 +918,7 @@ module ArelExtensions
|
|
811
918
|
assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('arrete')).then('1').else('0'))
|
812
919
|
assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('àrrétè')).then('1').else('0'))
|
813
920
|
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('arretez')).then('1').else('0'))
|
814
|
-
if
|
921
|
+
if !%w[oracle postgresql mysql].include?(@env_db) # AI => CI
|
815
922
|
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrete')).then('1').else('0'))
|
816
923
|
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrêté')).then('1').else('0'))
|
817
924
|
end
|
@@ -838,8 +945,8 @@ module ArelExtensions
|
|
838
945
|
|
839
946
|
def test_subquery_with_order
|
840
947
|
skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
|
841
|
-
assert_equal
|
842
|
-
assert_equal
|
948
|
+
assert_equal 10, User.where(name: User.select(:name).order(:name)).count
|
949
|
+
assert_equal 10, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
|
843
950
|
if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
|
844
951
|
assert_equal 2, User.where(name: User.select(:name).order(:name).limit(2)).count
|
845
952
|
# assert_equal 6, User.where(name: User.select(:name).order(:name).offset(2)).count
|
@@ -915,7 +1022,7 @@ module ArelExtensions
|
|
915
1022
|
end
|
916
1023
|
|
917
1024
|
def test_alias_shortened
|
918
|
-
if [
|
1025
|
+
if %w[postgresql oracle].include?(@env_db)
|
919
1026
|
new_alias = Arel.shorten('azerty' * 15)
|
920
1027
|
at = User.arel_table.alias('azerty' * 15)
|
921
1028
|
assert_equal "\"user_tests\" \"#{new_alias}\"".downcase, User.arel_table.alias('azerty' * 15).to_sql.downcase
|
@@ -956,23 +1063,23 @@ module ArelExtensions
|
|
956
1063
|
skip "Can't be tested on travis"
|
957
1064
|
# creation
|
958
1065
|
assert_equal 'Arthur', t(@arthur, Arel.json(@name))
|
959
|
-
assert_equal [
|
1066
|
+
assert_equal %w[Arthur Arthur], parse_json(t(@arthur, Arel.json(@name, @name)))
|
960
1067
|
assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 'ArthurArthur'}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => @name + @name})))
|
961
1068
|
assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 1}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => 1})))
|
962
|
-
assert_equal
|
1069
|
+
assert_equal [{'age' => 21}, {'name' => 'Arthur', 'score' => 65.62}], parse_json(t(@arthur, Arel.json([{age: @age}, {name: @name, score: @score}])))
|
963
1070
|
|
964
1071
|
# aggregate
|
965
1072
|
assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure'}),
|
966
1073
|
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name}).group(false)))
|
967
1074
|
assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure', 'Laure' => 25, 'Lucas' => 5, 'Myung' => 23, 'Sophie' => 15}),
|
968
1075
|
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name, @name => @age}).group(false)))
|
969
|
-
assert_equal
|
1076
|
+
assert_equal [{'5' => 'Lucas'}, {'15' => 'Sophie'}, {'23' => 'Myung'}, {'25' => 'Laure'}],
|
970
1077
|
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score), Arel.json({@age => @name}).group(true, [@age])))
|
971
1078
|
|
972
1079
|
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_sql
|
973
1080
|
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_a
|
974
1081
|
|
975
|
-
skip 'Not Yet Implemented' if $sqlite || [
|
1082
|
+
skip 'Not Yet Implemented' if $sqlite || %w[oracle mssql].include?(@env_db)
|
976
1083
|
# get
|
977
1084
|
h1 = Arel.json({@name => @name + @name, @name + '2' => 1})
|
978
1085
|
assert_equal 'ArthurArthur', parse_json(t(@arthur, h1.get(@name)))
|
@@ -981,13 +1088,13 @@ module ArelExtensions
|
|
981
1088
|
assert_equal 21, parse_json(t(@arthur, h2.get(0).get('age')))
|
982
1089
|
assert_nil t(@arthur, h2.get('age'))
|
983
1090
|
# set
|
984
|
-
assert_equal ({'Arthur' => [
|
1091
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1}), parse_json(t(@arthur, h1.set(@name, %w[toto tata])))
|
985
1092
|
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.set(@name + '3', 2)))
|
986
1093
|
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => nil}), parse_json(t(@arthur, h1.set(@name + '3', nil)))
|
987
1094
|
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => {'a' => 2}}), parse_json(t(@arthur, h1.set(@name + '3', {a: 2})))
|
988
1095
|
# merge
|
989
|
-
assert_equal ({'Arthur' => [
|
990
|
-
assert_equal ({'Arthur' => [
|
1096
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata]}, {@name + '3' => 2})))
|
1097
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata], @name + '3' => 2})))
|
991
1098
|
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1}), parse_json(t(@arthur, h1.merge({})))
|
992
1099
|
end
|
993
1100
|
|
@@ -58,15 +58,15 @@ END;])
|
|
58
58
|
connect_db
|
59
59
|
setup_db
|
60
60
|
@table = Arel::Table.new(:user_tests)
|
61
|
-
@cols = [
|
61
|
+
@cols = %w[id name comments created_at]
|
62
62
|
@data = [
|
63
63
|
[23, 'nom1', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.', '2016-01-01'],
|
64
64
|
[25, 'nom2', 'sdfdsfdsfsdf', '2016-01-02']
|
65
65
|
]
|
66
|
-
@cols2 = [
|
66
|
+
@cols2 = %w[name comments created_at]
|
67
67
|
@data2 = [
|
68
68
|
['nom3', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor.', '2016-01-01'],
|
69
|
-
[
|
69
|
+
%w[nom4 sdfdsfdsfsdf 2016-01-04]
|
70
70
|
]
|
71
71
|
end
|
72
72
|
|
@@ -27,7 +27,7 @@ module ArelExtensions
|
|
27
27
|
t.column :price, :decimal
|
28
28
|
end
|
29
29
|
@table = Arel::Table.new(:users)
|
30
|
-
@cols = [
|
30
|
+
@cols = %w[id name comments created_at]
|
31
31
|
@data = [
|
32
32
|
[23, 'nom1', 'sdfdsfdsfsdf', '2016-01-01'],
|
33
33
|
[25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01']
|
data/version_v1.rb
CHANGED
data/version_v2.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yann Azoury
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-11-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -40,20 +40,6 @@ dependencies:
|
|
40
40
|
- - "~>"
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: '5.9'
|
43
|
-
- !ruby/object:Gem::Dependency
|
44
|
-
name: rdoc
|
45
|
-
requirement: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: 6.3.1
|
50
|
-
type: :development
|
51
|
-
prerelease: false
|
52
|
-
version_requirements: !ruby/object:Gem::Requirement
|
53
|
-
requirements:
|
54
|
-
- - ">="
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version: 6.3.1
|
57
43
|
- !ruby/object:Gem::Dependency
|
58
44
|
name: rake
|
59
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,15 +72,17 @@ files:
|
|
86
72
|
- ".rubocop.yml"
|
87
73
|
- Gemfile
|
88
74
|
- MIT-LICENSE.txt
|
75
|
+
- NEWS.md
|
89
76
|
- README.md
|
90
77
|
- Rakefile
|
91
78
|
- SQL_Challenges.md
|
92
79
|
- TODO
|
80
|
+
- appveyor.yml
|
93
81
|
- arel_extensions.gemspec
|
94
82
|
- functions.html
|
95
83
|
- gemfiles/rails3.gemfile
|
96
|
-
- gemfiles/
|
97
|
-
- gemfiles/
|
84
|
+
- gemfiles/rails4_2.gemfile
|
85
|
+
- gemfiles/rails5.gemfile
|
98
86
|
- gemfiles/rails5_1_4.gemfile
|
99
87
|
- gemfiles/rails5_2.gemfile
|
100
88
|
- gemfiles/rails6.gemfile
|
@@ -149,7 +137,9 @@ files:
|
|
149
137
|
- lib/arel_extensions/nodes/rand.rb
|
150
138
|
- lib/arel_extensions/nodes/repeat.rb
|
151
139
|
- lib/arel_extensions/nodes/replace.rb
|
140
|
+
- lib/arel_extensions/nodes/rollup.rb
|
152
141
|
- lib/arel_extensions/nodes/round.rb
|
142
|
+
- lib/arel_extensions/nodes/select.rb
|
153
143
|
- lib/arel_extensions/nodes/soundex.rb
|
154
144
|
- lib/arel_extensions/nodes/std.rb
|
155
145
|
- lib/arel_extensions/nodes/substring.rb
|
data/gemfiles/rails4.gemfile
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem 'arel', '~> 6.0'
|
4
|
-
|
5
|
-
group :development, :test do
|
6
|
-
gem 'activesupport', '~> 4.0'
|
7
|
-
gem 'activemodel', '~> 4.0'
|
8
|
-
gem 'activerecord', '~> 4.0'
|
9
|
-
|
10
|
-
gem 'sqlite3', '<= 1.3.13', platforms: [:mri, :mswin, :mingw]
|
11
|
-
gem 'mysql2', '0.4.10', platforms: [:mri, :mswin, :mingw]
|
12
|
-
gem 'pg', '< 1.0.0', platforms: [:mri, :mingw]
|
13
|
-
|
14
|
-
gem 'tiny_tds', platforms: [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
|
15
|
-
gem 'activerecord-sqlserver-adapter', '~> 4.2.0', platforms: [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
|
16
|
-
|
17
|
-
gem 'ruby-oci8', platforms: [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
18
|
-
gem 'activerecord-oracle_enhanced-adapter', '~> 1.6.0' if ENV.has_key? 'ORACLE_HOME'
|
19
|
-
|
20
|
-
# for JRuby
|
21
|
-
gem 'activerecord-jdbc-adapter', '~> 1.3', platforms: :jruby
|
22
|
-
gem 'jdbc-sqlite3', platforms: :jruby
|
23
|
-
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
24
|
-
gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
|
25
|
-
gem 'activerecord-jdbcpostgresql-adapter', platforms: :jruby
|
26
|
-
gem 'activerecord-jdbcmssql-adapter', platforms: :jruby
|
27
|
-
end
|
28
|
-
|
29
|
-
gemspec path: '../'
|