arel_extensions 1.0.5 → 1.0.6

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +20 -6
  3. data/Gemfile +5 -3
  4. data/README.md +38 -1
  5. data/appveyor.yml +0 -4
  6. data/gemfiles/rails5_0.gemfile +1 -1
  7. data/gemfiles/{rails5_2_beta.gemfile → rails5_2.gemfile} +5 -5
  8. data/lib/arel_extensions/attributes.rb +2 -2
  9. data/lib/arel_extensions/date_duration.rb +1 -1
  10. data/lib/arel_extensions/math.rb +20 -16
  11. data/lib/arel_extensions/nodes/abs.rb +1 -1
  12. data/lib/arel_extensions/nodes/blank.rb +2 -2
  13. data/lib/arel_extensions/nodes/cast.rb +18 -13
  14. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  15. data/lib/arel_extensions/nodes/change_case.rb +2 -2
  16. data/lib/arel_extensions/nodes/coalesce.rb +1 -2
  17. data/lib/arel_extensions/nodes/collate.rb +18 -0
  18. data/lib/arel_extensions/nodes/concat.rb +8 -8
  19. data/lib/arel_extensions/nodes/date_diff.rb +3 -3
  20. data/lib/arel_extensions/nodes/duration.rb +4 -4
  21. data/lib/arel_extensions/nodes/find_in_set.rb +1 -1
  22. data/lib/arel_extensions/nodes/floor.rb +1 -2
  23. data/lib/arel_extensions/nodes/format.rb +2 -2
  24. data/lib/arel_extensions/nodes/formatted_number.rb +1 -1
  25. data/lib/arel_extensions/nodes/function.rb +10 -6
  26. data/lib/arel_extensions/nodes/is_null.rb +2 -1
  27. data/lib/arel_extensions/nodes/length.rb +1 -1
  28. data/lib/arel_extensions/nodes/locate.rb +1 -1
  29. data/lib/arel_extensions/nodes/log10.rb +1 -1
  30. data/lib/arel_extensions/nodes/matches.rb +10 -0
  31. data/lib/arel_extensions/nodes/power.rb +1 -1
  32. data/lib/arel_extensions/nodes/rand.rb +1 -1
  33. data/lib/arel_extensions/nodes/repeat.rb +1 -1
  34. data/lib/arel_extensions/nodes/replace.rb +1 -1
  35. data/lib/arel_extensions/nodes/round.rb +1 -1
  36. data/lib/arel_extensions/nodes/soundex.rb +1 -1
  37. data/lib/arel_extensions/nodes/substring.rb +1 -1
  38. data/lib/arel_extensions/nodes/trim.rb +3 -1
  39. data/lib/arel_extensions/nodes/wday.rb +3 -3
  40. data/lib/arel_extensions/string_functions.rb +31 -1
  41. data/lib/arel_extensions/version.rb +1 -1
  42. data/lib/arel_extensions/visitors/mssql.rb +88 -4
  43. data/lib/arel_extensions/visitors/mysql.rb +68 -4
  44. data/lib/arel_extensions/visitors/oracle.rb +67 -6
  45. data/lib/arel_extensions/visitors/postgresql.rb +49 -0
  46. data/lib/arel_extensions/visitors/sqlite.rb +53 -2
  47. data/lib/arel_extensions/visitors/to_sql.rb +2 -0
  48. data/lib/arel_extensions.rb +2 -1
  49. data/test/visitors/test_to_sql.rb +21 -1
  50. data/test/with_ar/all_agnostic_test.rb +65 -19
  51. metadata +4 -3
@@ -40,6 +40,7 @@ module ArelExtensions
40
40
  end
41
41
 
42
42
  it "should return right calculations on numbers" do
43
+ #puts (@price.abs + 42).inspect
43
44
  compile(@price.abs + 42).must_be_like %{(ABS("products"."price") + 42)}
44
45
  compile(@price.ceil + 42).must_be_like %{(CEIL("products"."price") + 42)}
45
46
  compile(@price.floor + 42).must_be_like %{(FLOOR("products"."price") + 42)}
@@ -62,8 +63,9 @@ module ArelExtensions
62
63
  it "should accept functions on strings" do
63
64
  c = @table[:name]
64
65
  compile(c + 'test').must_be_like %{CONCAT(\"users\".\"name\", 'test')}
65
- compile(c + 'test' + ' chain').must_be_like %{CONCAT(\"users\".\"name\", 'test', ' chain')}
66
+ compile(c + 'test' + ' chain').must_be_like %{CONCAT(CONCAT(\"users\".\"name\", 'test'), ' chain')}
66
67
  compile(c.length).must_be_like %{LENGTH("users"."name")}
68
+ #puts (c.length.round + 42).inspect
67
69
  compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
68
70
  compile(c.locate('test')).must_be_like %{LOCATE('test', "users"."name")}
69
71
  compile(c & 42).must_be_like %{FIND_IN_SET(42, "users"."name")}
@@ -75,6 +77,11 @@ module ArelExtensions
75
77
  compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
76
78
  compile(c.imatches_any(['%test%', 't2'])).must_be_like %{("users"."name" ILIKE '%test%' OR "users"."name" ILIKE 't2')}
77
79
  compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
80
+
81
+ compile(c.substring(1)).must_be_like %{SUBSTRING("users"."name", 1)}
82
+ compile(c + '0').must_be_like %{CONCAT("users"."name", '0')}
83
+ compile(c.substring(1) + '0').must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
84
+ compile(c.substring(1) + c.substring(2)).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
78
85
  end
79
86
 
80
87
  # Comparators
@@ -235,10 +242,23 @@ module ArelExtensions
235
242
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
236
243
  end
237
244
 
245
+ it "should be possible to use as on anything" do
246
+ compile(@table[:name].as('alias')).must_be_like %{"users"."name" AS alias}
247
+ compile(@table[:name].concat(' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
248
+ compile((@table[:name] + ' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
249
+ compile((@table[:age] + 42).as('alias')).must_be_like %{("users"."age" + 42) AS alias}
250
+ compile(@table[:name].coalesce('').as('alias')).must_be_like %{COALESCE("users"."name", '') AS alias}
251
+ compile(Arel::Nodes.build_quoted('test').as('alias')).must_be_like %{'test' AS alias}
252
+ compile(@table.project(@table[:name]).as('alias')).must_be_like %{(SELECT "users"."name" FROM "users") alias}
253
+ compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')).
254
+ must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
255
+ end
238
256
 
239
257
  it "should accept comparators on functions" do
240
258
  c = @table[:name]
241
259
  compile(c.soundex == 'test').must_be_like %{SOUNDEX("users"."name") = 'test'}
260
+ compile(c.soundex != 'test').must_be_like %{SOUNDEX("users"."name") != 'test'}
261
+ compile(c.length >= 0 ).must_be_like %{LENGTH("users"."name") >= 0}
242
262
  end
243
263
 
244
264
 
@@ -57,7 +57,7 @@ module ArelExtensions
57
57
  @sophie = User.where(:id => u.id)
58
58
  u = User.create :age => 20, :name => "Camille", :created_at => d, :score => -20.16
59
59
  @camille = User.where(:id => u.id)
60
- u = User.create :age => 21, :name => "Arthur", :created_at => d, :score => 65.62
60
+ u = User.create :age => 21, :name => "Arthur", :created_at => d, :score => 65.62, :comments => 'arrêté'
61
61
  @arthur = User.where(:id => u.id)
62
62
  u = User.create :age => 23, :name => "Myung", :created_at => d, :score => 20.16, :comments => ' '
63
63
  @myung = User.where(:id => u.id)
@@ -200,6 +200,10 @@ module ArelExtensions
200
200
  end
201
201
  assert_equal 'Lu', t(@lucas, @name[0,2])
202
202
  assert_equal 'Lu', t(@lucas, @name[0..1])
203
+
204
+ #substring should accept string function
205
+ assert_equal 'Ce', t(@camille, @name.substring(1, 1).concat('e'))
206
+ assert_equal 'Ce', t(@camille, @name.substring(1, 1)+'e')
203
207
  end
204
208
 
205
209
  def test_find_in_set
@@ -255,6 +259,7 @@ module ArelExtensions
255
259
  end
256
260
 
257
261
  def test_imatches
262
+ #puts User.where(@name.imatches('m%')).to_sql
258
263
  assert_equal 1, User.where(@name.imatches('m%')).count
259
264
  assert_equal 4, User.where(@name.imatches_any(['L%', '%e'])).count
260
265
  assert_equal 6, User.where(@name.idoes_not_match('L%')).count
@@ -360,7 +365,7 @@ module ArelExtensions
360
365
 
361
366
  def test_date_duration
362
367
  #Year
363
- assert_equal 2016, t(@lucas, @created_at.year).to_i
368
+ assert_equal 2016, t(@lucas, @created_at.year).to_i
364
369
  assert_equal 0, User.where(@created_at.year.eq("2012")).count
365
370
  #Month
366
371
  assert_equal 5, t(@camille, @created_at.month).to_i
@@ -415,11 +420,13 @@ module ArelExtensions
415
420
  def test_cast_types
416
421
  assert_equal "5", t(@lucas, @age.cast(:string))
417
422
  if @env_db == 'mysql' || @env_db == 'postgresql' || @env_db == 'oracle'
418
- assert_equal "12:42:21", t(@laure, @duration.cast(:time).cast(:string))
423
+ assert_equal 1, t(@laure,ArelExtensions::Nodes::Case.new.when(@duration.cast(:time).cast(:string).eq("12:42:21")).then(1).else(0))
424
+ assert_equal 1, t(@laure,ArelExtensions::Nodes::Case.new.when(@duration.cast(:time).eq("12:42:21")).then(1).else(0))
419
425
  end
420
426
  end
421
427
 
422
- def test_is_null
428
+ def test_is_null
429
+ #puts User.where(@age.is_null).select(@name).to_sql
423
430
  assert_equal "Test", User.where(@age.is_null).select(@name).first.name
424
431
  end
425
432
 
@@ -490,24 +497,63 @@ module ArelExtensions
490
497
  end
491
498
 
492
499
  def test_format_numbers
500
+ skip "Not yet implemented" if @env_db != 'mysql'
493
501
  #score of Arthur = 65.62
494
- if @env_db == 'mysql'
495
- assert_equal "AZERTY65,62" , t(@arthur, @score.format_number("AZERTY%.2f","fr_FR"))
496
- assert_equal "65,62AZERTY" , t(@arthur, @score.format_number("%.2fAZERTY","fr_FR"))
497
- assert_equal "$ 65.62 €" , t(@arthur, @score.format_number("$ %.2f €","en_EN"))
498
- assert_equal "$ 0065,62 €" , t(@arthur, @score.format_number("$ %07.2f €","fr_FR"))
499
- assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-07.2f €","fr_FR"))
500
- assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-7.2f €","fr_FR"))
501
- assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ % 7.2f €","fr_FR"))
502
- assert_equal "$ +65,62 €" , t(@arthur, @score.format_number("$ % +7.2f €","fr_FR"))
503
- assert_equal "$ +065,62 €" , t(@arthur, @score.format_number("$ %0+7.2f €","fr_FR"))
504
- assert_equal "$ 6,56e1 €" , t(@arthur, @score.format_number("$ %.2e €","fr_FR"))
505
- assert_equal "$ 6,56E1 €" , t(@arthur, @score.format_number("$ %.2E €","fr_FR"))
506
- assert_equal "Wrong Format" , t(@arthur, @score.format_number("$ %...234.6F €","fr_FR"))
507
- end
502
+ assert_equal "AZERTY65,62" , t(@arthur, @score.format_number("AZERTY%.2f","fr_FR"))
503
+ assert_equal "65,62AZERTY" , t(@arthur, @score.format_number("%.2fAZERTY","fr_FR"))
504
+ assert_equal "$ 65.62 €" , t(@arthur, @score.format_number("$ %.2f €","en_EN"))
505
+ assert_equal "$ 0065,62 €" , t(@arthur, @score.format_number("$ %07.2f €","fr_FR"))
506
+ assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-07.2f €","fr_FR"))
507
+ assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-7.2f €","fr_FR"))
508
+ assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ % 7.2f €","fr_FR"))
509
+ assert_equal "$ +65,62 €" , t(@arthur, @score.format_number("$ % +7.2f €","fr_FR"))
510
+ assert_equal "$ +065,62 €" , t(@arthur, @score.format_number("$ %0+7.2f €","fr_FR"))
511
+ assert_equal "$ 6,56e1 €" , t(@arthur, @score.format_number("$ %.2e €","fr_FR"))
512
+ assert_equal "$ 6,56E1 €" , t(@arthur, @score.format_number("$ %.2E €","fr_FR"))
513
+ assert_equal "Wrong Format" , t(@arthur, @score.format_number("$ %...234.6F €","fr_FR"))
508
514
  end
509
515
 
510
-
516
+ def test_accent_insensitive
517
+ skip "SQLite is natively Case Insensitive and Accent Sensitive" if $sqlite
518
+ skip "Not finished" if @env_db == 'mysql'
519
+ # actual comments value: "arrêté"
520
+ #AI & CI
521
+ if !['postgresql'].include?(@env_db) # Extension unaccent required on PG
522
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("arrêté")).then("1").else("0"))
523
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("arrete")).then("1").else("0"))
524
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("àrrétè")).then("1").else("0"))
525
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("arretez")).then("1").else("0"))
526
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("Arrete")).then("1").else("0"))
527
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_imatches("Arrêté")).then("1").else("0"))
528
+ #AI & CS
529
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("arrêté")).then("1").else("0"))
530
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("arrete")).then("1").else("0"))
531
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("àrrétè")).then("1").else("0"))
532
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("arretez")).then("1").else("0"))
533
+ if !['oracle','postgresql','mysql'].include?(@env_db) # AI => CI
534
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("Arrete")).then("1").else("0"))
535
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.ai_matches("Arrêté")).then("1").else("0"))
536
+ end
537
+ end
538
+ #AS & CI
539
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("arrêté")).then("1").else("0"))
540
+ if !['mysql'].include?(@env_db) # CI => AI in utf8 (AI not possible in latin1)
541
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("arrete")).then("1").else("0"))
542
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("àrrétè")).then("1").else("0"))
543
+ end
544
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("arretez")).then("1").else("0"))
545
+ if !['mysql'].include?(@env_db) # CI => AI in utf8 (AI not possible in latin1)
546
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("Arrete")).then("1").else("0"))
547
+ end
548
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.imatches("Arrêté")).then("1").else("0"))
549
+ #AS & CS
550
+ assert_equal "1", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("arrêté")).then("1").else("0"))
551
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("arrete")).then("1").else("0"))
552
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("àrrétè")).then("1").else("0"))
553
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("arretez")).then("1").else("0"))
554
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrete")).then("1").else("0"))
555
+ assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrêté")).then("1").else("0"))
556
+ end
511
557
  end
512
558
  end
513
559
  end
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.0.5
4
+ version: 1.0.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: 2018-03-23 00:00:00.000000000 Z
13
+ date: 2018-04-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: arel
@@ -103,7 +103,7 @@ files:
103
103
  - gemfiles/rails4.gemfile
104
104
  - gemfiles/rails5_0.gemfile
105
105
  - gemfiles/rails5_1_4.gemfile
106
- - gemfiles/rails5_2_beta.gemfile
106
+ - gemfiles/rails5_2.gemfile
107
107
  - init/mssql.sql
108
108
  - init/mysql.sql
109
109
  - init/oracle.sql
@@ -127,6 +127,7 @@ files:
127
127
  - lib/arel_extensions/nodes/ceil.rb
128
128
  - lib/arel_extensions/nodes/change_case.rb
129
129
  - lib/arel_extensions/nodes/coalesce.rb
130
+ - lib/arel_extensions/nodes/collate.rb
130
131
  - lib/arel_extensions/nodes/concat.rb
131
132
  - lib/arel_extensions/nodes/date_diff.rb
132
133
  - lib/arel_extensions/nodes/duration.rb