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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -7
  3. data/.travis.yml +91 -61
  4. data/Gemfile +20 -15
  5. data/README.md +12 -17
  6. data/Rakefile +29 -40
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +3 -3
  9. data/functions.html +3 -3
  10. data/gemfiles/rails3.gemfile +9 -9
  11. data/gemfiles/rails4.gemfile +13 -13
  12. data/gemfiles/rails5_0.gemfile +13 -13
  13. data/gemfiles/rails5_1_4.gemfile +13 -13
  14. data/gemfiles/rails5_2.gemfile +13 -13
  15. data/init/mssql.sql +4 -4
  16. data/init/mysql.sql +38 -38
  17. data/init/postgresql.sql +21 -21
  18. data/lib/arel_extensions.rb +19 -69
  19. data/lib/arel_extensions/attributes.rb +1 -0
  20. data/lib/arel_extensions/boolean_functions.rb +14 -55
  21. data/lib/arel_extensions/common_sql_functions.rb +8 -7
  22. data/lib/arel_extensions/comparators.rb +15 -14
  23. data/lib/arel_extensions/date_duration.rb +5 -4
  24. data/lib/arel_extensions/insert_manager.rb +16 -17
  25. data/lib/arel_extensions/math.rb +12 -11
  26. data/lib/arel_extensions/math_functions.rb +22 -29
  27. data/lib/arel_extensions/nodes.rb +1 -1
  28. data/lib/arel_extensions/nodes/abs.rb +1 -0
  29. data/lib/arel_extensions/nodes/blank.rb +1 -0
  30. data/lib/arel_extensions/nodes/case.rb +8 -11
  31. data/lib/arel_extensions/nodes/cast.rb +2 -4
  32. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  33. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  34. data/lib/arel_extensions/nodes/coalesce.rb +3 -2
  35. data/lib/arel_extensions/nodes/collate.rb +2 -1
  36. data/lib/arel_extensions/nodes/concat.rb +16 -7
  37. data/lib/arel_extensions/nodes/date_diff.rb +13 -10
  38. data/lib/arel_extensions/nodes/duration.rb +3 -0
  39. data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
  40. data/lib/arel_extensions/nodes/floor.rb +1 -1
  41. data/lib/arel_extensions/nodes/format.rb +8 -34
  42. data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
  43. data/lib/arel_extensions/nodes/function.rb +16 -25
  44. data/lib/arel_extensions/nodes/json.rb +36 -43
  45. data/lib/arel_extensions/nodes/length.rb +1 -0
  46. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  47. data/lib/arel_extensions/nodes/locate.rb +1 -0
  48. data/lib/arel_extensions/nodes/log10.rb +2 -1
  49. data/lib/arel_extensions/nodes/matches.rb +6 -4
  50. data/lib/arel_extensions/nodes/md5.rb +1 -0
  51. data/lib/arel_extensions/nodes/power.rb +5 -5
  52. data/lib/arel_extensions/nodes/rand.rb +1 -0
  53. data/lib/arel_extensions/nodes/repeat.rb +4 -2
  54. data/lib/arel_extensions/nodes/replace.rb +6 -22
  55. data/lib/arel_extensions/nodes/round.rb +6 -5
  56. data/lib/arel_extensions/nodes/soundex.rb +15 -15
  57. data/lib/arel_extensions/nodes/std.rb +21 -18
  58. data/lib/arel_extensions/nodes/substring.rb +16 -8
  59. data/lib/arel_extensions/nodes/then.rb +0 -0
  60. data/lib/arel_extensions/nodes/trim.rb +5 -3
  61. data/lib/arel_extensions/nodes/union.rb +5 -2
  62. data/lib/arel_extensions/nodes/union_all.rb +3 -0
  63. data/lib/arel_extensions/nodes/wday.rb +4 -0
  64. data/lib/arel_extensions/null_functions.rb +7 -5
  65. data/lib/arel_extensions/predications.rb +34 -35
  66. data/lib/arel_extensions/railtie.rb +5 -5
  67. data/lib/arel_extensions/set_functions.rb +4 -2
  68. data/lib/arel_extensions/string_functions.rb +22 -43
  69. data/lib/arel_extensions/tasks.rb +5 -5
  70. data/lib/arel_extensions/version.rb +1 -1
  71. data/lib/arel_extensions/visitors.rb +60 -68
  72. data/lib/arel_extensions/visitors/ibm_db.rb +12 -5
  73. data/lib/arel_extensions/visitors/mssql.rb +57 -63
  74. data/lib/arel_extensions/visitors/mysql.rb +98 -149
  75. data/lib/arel_extensions/visitors/oracle.rb +68 -71
  76. data/lib/arel_extensions/visitors/oracle12.rb +15 -2
  77. data/lib/arel_extensions/visitors/postgresql.rb +63 -116
  78. data/lib/arel_extensions/visitors/sqlite.rb +70 -83
  79. data/lib/arel_extensions/visitors/to_sql.rb +109 -141
  80. data/test/database.yml +0 -2
  81. data/test/helper.rb +18 -0
  82. data/test/real_db_test.rb +43 -28
  83. data/test/support/fake_record.rb +2 -2
  84. data/test/test_comparators.rb +12 -9
  85. data/test/visitors/test_bulk_insert_oracle.rb +8 -8
  86. data/test/visitors/test_bulk_insert_sqlite.rb +10 -9
  87. data/test/visitors/test_bulk_insert_to_sql.rb +10 -8
  88. data/test/visitors/test_oracle.rb +42 -42
  89. data/test/visitors/test_to_sql.rb +196 -361
  90. data/test/with_ar/all_agnostic_test.rb +160 -195
  91. data/test/with_ar/insert_agnostic_test.rb +4 -3
  92. data/test/with_ar/test_bulk_sqlite.rb +9 -6
  93. data/test/with_ar/test_math_sqlite.rb +12 -8
  94. data/test/with_ar/test_string_mysql.rb +11 -5
  95. data/test/with_ar/test_string_sqlite.rb +12 -4
  96. metadata +11 -22
  97. data/.github/workflows/ruby.yml +0 -102
  98. data/gemfiles/rails6.gemfile +0 -30
  99. data/gemfiles/rails6_1.gemfile +0 -30
  100. data/gemspecs/arel_extensions-v1.gemspec +0 -28
  101. data/gemspecs/arel_extensions-v2.gemspec +0 -28
  102. data/generate_gems.sh +0 -15
  103. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
  104. data/lib/arel_extensions/nodes/sum.rb +0 -7
  105. data/lib/arel_extensions/visitors/convert_format.rb +0 -37
  106. data/test/arelx_test_helper.rb +0 -26
  107. data/version_v1.rb +0 -3
  108. data/version_v2.rb +0 -3
@@ -1,4 +1,4 @@
1
- require 'arelx_test_helper'
1
+ require 'helper'
2
2
  require 'set'
3
3
 
4
4
  module ArelExtensions
@@ -22,530 +22,365 @@ module ArelExtensions
22
22
  end
23
23
  end
24
24
 
25
- describe "primitive methods" do
26
- it "should be able to recognize equal nodes" do
27
- c = @table[:id]
28
- _(c == 1).must_be :eql?, (c == 1)
29
- _((c == 1).right.hash).must_equal (c == 1).right.hash
30
- _((c == 1).hash).must_equal (c == 1).hash
31
-
32
- _([c == 1, c == 1].uniq).must_equal [c == 1]
33
- end
34
- end
35
-
36
25
  # Math Functions
37
26
  it "should not break Arel functions" do
38
- _(compile(@price + 42)).must_be_like %{("products"."price" + 42)}
39
- _(compile(@table[:id] + @table[:pas_en_base]))
27
+ compile(@price + 42).must_be_like %{("products"."price" + 42)}
28
+ compile(@table[:id] + @table[:pas_en_base])
40
29
  .must_be_like %{("users"."id" + "users"."pas_en_base")}
41
- _(compile(@table[:pas_en_base] + @table[:id]))
30
+ compile(@table[:pas_en_base] + @table[:id])
42
31
  .must_be_like %{("users"."pas_en_base" + "users"."id")}
43
- _(compile(@table[:id] - @table[:pas_en_base]))
32
+ compile(@table[:id] - @table[:pas_en_base])
44
33
  .must_be_like %{("users"."id" - "users"."pas_en_base")}
45
- _(compile(@table[:pas_en_base] - @table[:id]))
34
+ compile(@table[:pas_en_base] - @table[:id])
46
35
  .must_be_like %{("users"."pas_en_base" - "users"."id")}
47
- _(compile(@table[:id] * @table[:pas_en_base]))
36
+ compile(@table[:id] * @table[:pas_en_base])
48
37
  .must_be_like %{"users"."id" * "users"."pas_en_base"}
49
- _(compile(@table[:pas_en_base] * @table[:id]))
38
+ compile(@table[:pas_en_base] * @table[:id])
50
39
  .must_be_like %{"users"."pas_en_base" * "users"."id"}
51
40
  end
52
41
 
53
42
  it "should return right calculations on numbers" do
54
- # puts (@price.abs + 42).inspect
55
- _(compile(@price.abs + 42)).must_be_like %{(ABS("products"."price") + 42)}
56
- _(compile(@price.ceil + 42)).must_be_like %{(CEIL("products"."price") + 42)}
57
- _(compile(@price.floor + 42)).must_be_like %{(FLOOR("products"."price") + 42)}
58
- _(compile(@price.log10 + 42)).must_be_like %{(LOG10("products"."price") + 42)}
59
- _(compile(@price.power(42) + 42)).must_be_like %{(POW("products"."price", 42) + 42)}
60
- _(compile(@price.pow(42) + 42)).must_be_like %{(POW("products"."price", 42) + 42)}
61
- _(compile(@price.ceil + @price.floor)).must_be_like %{(CEIL("products"."price") + FLOOR("products"."price"))}
62
- _(compile((@price.ceil + @price.floor).abs)).must_be_like %{ABS((CEIL("products"."price") + FLOOR("products"."price")))}
63
- _(compile(@price.round + 42)).must_be_like %{(ROUND("products"."price") + 42)}
64
- _(compile(@price.round(2) + 42)).must_be_like %{(ROUND("products"."price", 2) + 42)}
65
- _(compile(Arel.rand + 42)).must_be_like %{(RAND() + 42)}
66
- _(compile(@price.sum + 42)).must_be_like %{(SUM("products"."price") + 42)}
67
- _(compile((@price + 42).sum)).must_be_like %{SUM(("products"."price" + 42))}
68
- _(compile((@price + 42).average)).must_be_like %{AVG(("products"."price" + 42))}
69
- _(compile((Arel.rand * 9).round + 42)).must_be_like %{(ROUND(RAND() * 9) + 42)}
70
- _(compile((Arel.rand * @price).round(2) + @price)).must_be_like %{(ROUND(RAND() * "products"."price", 2) + "products"."price")}
71
-
72
- _(compile(@price.std + 42)).must_be_like %{(STD("products"."price") + 42)}
73
- _(compile(@price.variance + 42)).must_be_like %{(VARIANCE("products"."price") + 42)}
74
-
75
- _(compile(@price.coalesce(0) - 42)).must_be_like %{(COALESCE("products"."price", 0) - 42)}
76
- _(compile(@price.sum - 42)).must_be_like %{(SUM("products"."price") - 42)}
77
- _(compile(@price.std - 42)).must_be_like %{(STD("products"."price") - 42)}
78
- _(compile(@price.variance - 42)).must_be_like %{(VARIANCE("products"."price") - 42)}
79
-
80
- _(compile(@price * 42.0)).must_be_like %{"products"."price" * 42.0}
81
- _(compile(@price / 42.0)).must_be_like %{"products"."price" / 42.0}
43
+ #puts (@price.abs + 42).inspect
44
+ compile(@price.abs + 42).must_be_like %{(ABS("products"."price") + 42)}
45
+ compile(@price.ceil + 42).must_be_like %{(CEIL("products"."price") + 42)}
46
+ compile(@price.floor + 42).must_be_like %{(FLOOR("products"."price") + 42)}
47
+ compile(@price.log10 + 42).must_be_like %{(LOG10("products"."price") + 42)}
48
+ compile(@price.power(42) + 42).must_be_like %{(POW("products"."price", 42) + 42)}
49
+ compile(@price.pow(42) + 42).must_be_like %{(POW("products"."price", 42) + 42)}
50
+ compile(@price.ceil + @price.floor).must_be_like %{(CEIL("products"."price") + FLOOR("products"."price"))}
51
+ compile((@price.ceil + @price.floor).abs).must_be_like %{ABS((CEIL("products"."price") + FLOOR("products"."price")))}
52
+ compile(@price.round + 42).must_be_like %{(ROUND("products"."price") + 42)}
53
+ compile(@price.round(2) + 42).must_be_like %{(ROUND("products"."price", 2) + 42)}
54
+ compile(Arel.rand + 42).must_be_like %{(RAND() + 42)}
55
+ compile(@price.sum + 42).must_be_like %{(SUM("products"."price") + 42)}
56
+ compile((@price + 42).sum).must_be_like %{SUM(("products"."price" + 42))}
57
+ compile((@price + 42).average).must_be_like %{AVG(("products"."price" + 42))}
58
+ compile((Arel.rand * 9).round + 42).must_be_like %{(ROUND(RAND() * 9) + 42)}
59
+ compile((Arel.rand * @price).round(2) + @price).must_be_like %{(ROUND(RAND() * "products"."price", 2) + "products"."price")}
60
+
61
+ compile(@price.std + 42).must_be_like %{(STD("products"."price") + 42)}
62
+ compile(@price.variance + 42).must_be_like %{(VARIANCE("products"."price") + 42)}
63
+
64
+ compile(@price.coalesce(0) - 42).must_be_like %{(COALESCE("products"."price", 0) - 42)}
65
+ compile(@price.sum - 42).must_be_like %{(SUM("products"."price") - 42)}
66
+ compile(@price.std - 42).must_be_like %{(STD("products"."price") - 42)}
67
+ compile(@price.variance - 42).must_be_like %{(VARIANCE("products"."price") - 42)}
68
+
69
+ compile(@price * 42.0).must_be_like %{"products"."price" * 42.0}
70
+ compile(@price / 42.0).must_be_like %{"products"."price" / 42.0}
82
71
 
83
72
  fake_table = Arel::Table.new('fake_tables')
84
73
 
85
- _(compile(fake_table[:fake_att] - 42)).must_be_like %{("fake_tables"."fake_att" - 42)}
86
- _(compile(fake_table[:fake_att].coalesce(0) - 42)).must_be_like %{(COALESCE("fake_tables"."fake_att", 0) - 42)}
74
+ compile(fake_table[:fake_att] - 42).must_be_like %{("fake_tables"."fake_att" - 42)}
75
+ compile(fake_table[:fake_att].coalesce(0) - 42).must_be_like %{(COALESCE("fake_tables"."fake_att", 0) - 42)}
87
76
  end
88
77
 
89
78
  # String Functions
90
79
  it "should accept functions on strings" do
91
80
  c = @table[:name]
92
- _(compile(c + 'test')).must_be_like %{CONCAT(\"users\".\"name\", 'test')}
93
- _(compile(c.length)).must_be_like %{LENGTH("users"."name")}
94
- # puts (c.length.round + 42).inspect
95
- _(compile(c.length.round + 42)).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
96
- _(compile(c.locate('test'))).must_be_like %{LOCATE('test', "users"."name")}
97
- _(compile(c & 42)).must_be_like %{FIND_IN_SET(42, "users"."name")}
98
-
99
- _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
100
- _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
101
- _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
102
- _(compile(c =~ /\Atest\z/)).must_be_like %{"users"."name" REGEXP '^test$'}
103
- _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
104
- _(compile(c.imatches('%test%'))).must_be_like %{"users"."name" ILIKE '%test%'}
105
- _(compile(c.imatches_any(['%test%', 't2']))).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
106
- _(compile(c.idoes_not_match('%test%'))).must_be_like %{"users"."name" NOT ILIKE '%test%'}
107
-
108
- _(compile(c.substring(1))).must_be_like %{SUBSTRING("users"."name", 1)}
109
- _(compile(c + '0')).must_be_like %{CONCAT("users"."name", '0')}
110
- _(compile(c.substring(1) + '0')).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
111
- _(compile(c.substring(1) + c.substring(2))).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
112
- _(compile(c.concat(c).concat(c))).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
113
- _(compile(c + c + c)).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
81
+ compile(c + 'test').must_be_like %{CONCAT(\"users\".\"name\", 'test')}
82
+ compile(c.length).must_be_like %{LENGTH("users"."name")}
83
+ #puts (c.length.round + 42).inspect
84
+ compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
85
+ compile(c.locate('test')).must_be_like %{LOCATE('test', "users"."name")}
86
+ compile(c & 42).must_be_like %{FIND_IN_SET(42, "users"."name")}
87
+
88
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
89
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
90
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
91
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
92
+ compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
93
+ compile(c.imatches_any(['%test%', 't2'])).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
94
+ compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
95
+
96
+ compile(c.substring(1)).must_be_like %{SUBSTRING("users"."name", 1)}
97
+ compile(c + '0').must_be_like %{CONCAT("users"."name", '0')}
98
+ compile(c.substring(1) + '0').must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
99
+ compile(c.substring(1) + c.substring(2)).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
100
+ compile(c.concat(c).concat(c)).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
101
+ compile(c + c + c).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
114
102
 
115
103
  # some optimization on concat
116
- _(compile(c + 'test' + ' chain')).must_be_like %{CONCAT(\"users\".\"name\", 'test chain')}
117
- _(compile(Arel::Nodes.build_quoted('test') + ' chain')).must_be_like %{'test chain'}
118
- _(compile(c + '' + c)).must_be_like %{CONCAT(\"users\".\"name\", \"users\".\"name\")}
104
+ compile(c + 'test' + ' chain').must_be_like %{CONCAT(\"users\".\"name\", 'test chain')}
105
+ compile(Arel::Nodes.build_quoted('test') + ' chain').must_be_like %{'test chain'}
106
+ compile(c + '' + c).must_be_like %{CONCAT(\"users\".\"name\", \"users\".\"name\")}
119
107
 
120
- _(compile(c.md5)).must_be_like %{MD5(\"users\".\"name\")}
108
+ compile(c.md5).must_be_like %{MD5(\"users\".\"name\")}
121
109
  end
122
110
 
123
111
  # Comparators
124
112
 
125
113
  it "should accept comparators on integers" do
126
- _(compile(@table[:id] == 42)).must_match %{"users"."id" = 42}
127
- _(compile(@table[:id] == @table[:id])).must_be_like %{"users"."id" = "users"."id"}
128
- _(compile(@table[:id] != 42)).must_match %{"users"."id" != 42}
129
- _(compile(@table[:id] > 42)).must_match %{"users"."id" > 42}
130
- _(compile(@table[:id] >= 42)).must_match %{"users"."id" >= 42}
131
- _(compile(@table[:id] >= @table[:id])).must_be_like %{"users"."id" >= "users"."id"}
132
- _(compile(@table[:id] < 42)).must_match %{"users"."id" < 42}
133
- _(compile(@table[:id] <= 42)).must_match %{"users"."id" <= 42}
134
- _(compile((@table[:id] <= 42).as('new_name'))).must_match %{("users"."id" <= 42) AS new_name}
135
- _(compile(@table[:id].count.eq 42)).must_match %{COUNT("users"."id") = 42}
136
- # _(compile(@table[:id].count == 42)).must_match %{COUNT("users"."id") = 42} # TODO
137
- # _(compile(@table[:id].count != 42)).must_match %{COUNT("users"."id") != 42}
138
- # _(compile(@table[:id].count >= 42)).must_match %{COUNT("users"."id") >= 42}
114
+ compile(@table[:id] == 42).must_match %{"users"."id" = 42}
115
+ compile(@table[:id] == @table[:id]).must_be_like %{"users"."id" = "users"."id"}
116
+ compile(@table[:id] != 42).must_match %{"users"."id" != 42}
117
+ compile(@table[:id] > 42).must_match %{"users"."id" > 42}
118
+ compile(@table[:id] >= 42).must_match %{"users"."id" >= 42}
119
+ compile(@table[:id] >= @table[:id]).must_be_like %{"users"."id" >= "users"."id"}
120
+ compile(@table[:id] < 42).must_match %{"users"."id" < 42}
121
+ compile(@table[:id] <= 42).must_match %{"users"."id" <= 42}
122
+ compile((@table[:id] <= 42).as('new_name')).must_match %{("users"."id" <= 42) AS new_name}
139
123
  end
140
124
 
141
125
  it "should accept comparators on dates" do
142
126
  c = @table[:created_at]
143
127
  u = @table[:updated_at]
144
- _(compile(c > @date)).must_be_like %{"users"."created_at" > '2016-03-31'}
145
- _(compile(u >= @date)).must_be_like %{"users"."updated_at" >= '2016-03-31'}
146
- _(compile(c < u)).must_be_like %{"users"."created_at" < "users"."updated_at"}
128
+ compile(c > @date).must_be_like %{"users"."created_at" > '2016-03-31'}
129
+ compile(u >= @date).must_be_like %{"users"."updated_at" >= '2016-03-31'}
130
+ compile(c < u).must_be_like %{"users"."created_at" < "users"."updated_at"}
147
131
  end
148
132
 
149
133
  it "should accept comparators on strings" do
150
134
  c = @table[:name]
151
- _(compile(c == 'test')).must_be_like %{"users"."name" = 'test'}
152
- _(compile(c != 'test')).must_be_like %{"users"."name" != 'test'}
153
- _(compile(c > 'test')).must_be_like %{"users"."name" > 'test'}
154
- _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
155
- _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
156
- _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
157
- _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
158
- _(compile(c.imatches('%test%'))).must_be_like %{"users"."name" ILIKE '%test%'}
159
- _(compile(c.imatches_any(['%test%', 't2']))).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
160
- _(compile(c.idoes_not_match('%test%'))).must_be_like %{"users"."name" NOT ILIKE '%test%'}
135
+ compile(c == 'test').must_be_like %{"users"."name" = 'test'}
136
+ compile(c != 'test').must_be_like %{"users"."name" != 'test'}
137
+ compile(c > 'test').must_be_like %{"users"."name" > 'test'}
138
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
139
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
140
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
141
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
142
+ compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
143
+ compile(c.imatches_any(['%test%', 't2'])).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
144
+ compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
161
145
  end
162
146
 
163
147
  # Maths
164
148
  # DateDiff
165
149
  it "should diff date col and date" do
166
- _(compile(@table[:created_at] - Date.new(2016, 3, 31))).must_match %{DATEDIFF("users"."created_at", '2016-03-31')}
150
+ compile(@table[:created_at] - Date.new(2016, 3, 31)).must_match %{DATEDIFF("users"."created_at", '2016-03-31')}
167
151
  end
168
152
 
169
153
  it "should diff date col and datetime col" do
170
- _(compile(@table[:created_at] - @table[:updated_at])).must_match %{DATEDIFF("users"."created_at", "users"."updated_at")}
154
+ compile(@table[:created_at] - @table[:updated_at]).must_match %{DATEDIFF("users"."created_at", "users"."updated_at")}
171
155
  end
172
156
 
173
157
  it "should diff date col and datetime col with AS" do
174
- _(compile((@table[:updated_at] - @table[:created_at]).as('new_name')))
175
- .must_match %{TIMEDIFF("users"."updated_at", "users"."created_at") AS new_name}
158
+ sql = compile((@table[:updated_at] - @table[:created_at]).as('new_name'))
159
+ sql.must_match %{TIMEDIFF("users"."updated_at", "users"."created_at") AS new_name}
176
160
  end
177
161
 
178
162
  it "should diff between time values" do
179
163
  d2 = Time.new(2015,6,1)
180
164
  d1 = DateTime.new(2015,6,2)
181
- _(compile(ArelExtensions::Nodes::DateDiff.new([d1, d2])))
182
- .must_match("DATEDIFF('2015-06-02', '2015-06-01')")
165
+ sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, d2]))
166
+ sql.must_match("DATEDIFF('2015-06-02', '2015-06-01')")
183
167
  end
184
168
 
185
169
  it "should diff between time values and time col" do
186
170
  d1 = DateTime.new(2015,6,2)
187
- _(compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]])))
188
- .must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
171
+ sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]]))
172
+ sql.must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
189
173
  end
190
174
 
191
175
  it "should diff between date col and duration" do
192
176
  d1 = 10
193
177
  d2 = -10
194
- _(compile(@table[:created_at] - d1))
195
- .must_match %{DATE_SUB("users"."created_at", 10)}
196
- _(compile(@table[:created_at] - d2))
197
- .must_match %{DATE_SUB("users"."created_at", -10)}
178
+ compile(@table[:created_at] - d1).
179
+ must_match %{DATE_SUB("users"."created_at", 10)}
180
+ compile(@table[:created_at] - d2).
181
+ must_match %{DATE_SUB("users"."created_at", -10)}
198
182
  end
199
183
 
200
184
  it "should accept operators on dates with numbers" do
201
185
  c = @table[:created_at]
202
- # u = @table[:updated_at]
203
- _(compile(c - 42)).must_be_like %{DATE_SUB("users"."created_at", 42)}
204
- _(compile(c - @table[:id])).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
186
+ #u = @table[:updated_at]
187
+ compile(c - 42).must_be_like %{DATE_SUB("users"."created_at", 42)}
188
+ compile(c - @table[:id]).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
205
189
  end
206
190
 
207
191
  # Maths on sums
208
192
  it "should accept math operators on anything" do
209
193
  c = @table[:name]
210
- _((c == 'test').to_sql)
211
- .must_be_like %{"users"."name" = 'test'}
212
- _((c != 'test').to_sql)
213
- .must_be_like %{"users"."name" != 'test'}
214
- _((c > 'test').to_sql)
215
- .must_be_like %{"users"."name" > 'test'}
216
- _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
217
- _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
218
- _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
219
- _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
194
+ (c == 'test').to_sql.must_be_like %{"users"."name" = 'test'}
195
+ (c != 'test').to_sql.must_be_like %{"users"."name" != 'test'}
196
+ (c > 'test').to_sql.must_be_like %{"users"."name" > 'test'}
197
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
198
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
199
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
200
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
220
201
  end
221
202
 
222
203
  it "should manage complex formulas" do
223
204
  c = @table[:name]
224
- _(compile(
225
- (c.length / 42).round(2).floor > (@table[:updated_at] - Date.new(2000, 3, 31)).abs.ceil
226
- ))
227
- .must_be_like %{FLOOR(ROUND(LENGTH("users"."name") / 42, 2)) > CEIL(ABS(TIMEDIFF("users"."updated_at", '2000-03-31 00:00:00 UTC')))}
205
+ compile(
206
+ (c.length / 42).round(2).floor > (@table[:updated_at] - Date.new(2000, 3, 31)).abs.ceil
207
+ ).must_be_like %{FLOOR(ROUND(LENGTH("users"."name") / 42, 2)) > CEIL(ABS(TIMEDIFF("users"."updated_at", '2000-03-31 00:00:00 UTC')))}
228
208
  end
229
209
 
230
210
  it "should accept aggregator like GROUP CONCAT" do
231
- _(@table.project(@table[:first_name].group_concat).group(@table[:last_name]).to_sql)
211
+ @table.project(@table[:first_name].group_concat).group(@table[:last_name]).to_sql
232
212
  .must_be_like %{SELECT GROUP_CONCAT("users"."first_name") FROM "users" GROUP BY "users"."last_name"}
233
- _(@table.project(@table[:first_name].group_concat('++')).group(@table[:last_name]).to_sql)
213
+ @table.project(@table[:first_name].group_concat('++')).group(@table[:last_name]).to_sql
234
214
  .must_be_like %{SELECT GROUP_CONCAT("users"."first_name", '++') FROM "users" GROUP BY "users"."last_name"}
235
215
  end
236
216
 
237
217
  # Unions
238
218
  it "should accept union operators on queries and union nodes" do
239
219
  c = @table.project(@table[:name])
240
- _(compile(c + c))
220
+ compile(c + c)
241
221
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
242
- _((c + c).to_sql)
222
+ (c + c).to_sql
243
223
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
244
- _((c + (c + c)).to_sql)
224
+ (c + (c + c)).to_sql
245
225
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
246
- _(((c + c) + c).to_sql)
226
+ ((c + c) + c).to_sql
247
227
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
248
- _((c + c + c).to_sql)
228
+ (c + c + c).to_sql
249
229
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
250
- _((c + c).as('union_table').to_sql)
230
+ (c + c).as('union_table').to_sql
251
231
  .must_be_like %{((SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")) union_table}
252
232
  c = @table.project(@table[:name])
253
- _(compile(c.union_all(c)))
233
+ compile(c.union_all(c))
254
234
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
255
- _((c.union_all(c)).to_sql)
235
+ (c.union_all(c)).to_sql
256
236
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
257
- _((c.union_all(c.union_all(c))).to_sql)
237
+ (c.union_all(c.union_all(c))).to_sql
258
238
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
259
- _(((c.union_all(c)).union_all(c)).to_sql)
239
+ ((c.union_all(c)).union_all(c)).to_sql
260
240
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
261
- _((c.union_all(c).union_all(c)).to_sql)
241
+ (c.union_all(c).union_all(c)).to_sql
262
242
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
263
- _((c.union_all(c)).as('union_table').to_sql)
243
+ (c.union_all(c)).as('union_table').to_sql
264
244
  .must_be_like %{((SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")) union_table}
265
245
  end
266
246
 
267
247
  # Case
268
248
  it "should accept case clause" do
269
- _(@table[:name].when("smith").then("cool").when("doe").then("fine").else("uncool").to_sql)
249
+ @table[:name].when("smith").then("cool").when("doe").then("fine").else("uncool").to_sql
270
250
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' WHEN 'doe' THEN 'fine' ELSE 'uncool' END}
271
- _(@table[:name].when("smith").then(1).when("doe").then(2).else(0).to_sql)
251
+ @table[:name].when("smith").then(1).when("doe").then(2).else(0).to_sql
272
252
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
273
- _(ArelExtensions::Nodes::Case.new.when(@table[:name] == "smith").then(1).when(@table[:name] == "doe").then(2).else(0).to_sql)
253
+ ArelExtensions::Nodes::Case.new.when(@table[:name] == "smith").then(1).when(@table[:name] == "doe").then(2).else(0).to_sql
274
254
  .must_be_like %{CASE WHEN "users"."name" = 'smith' THEN 1 WHEN "users"."name" = 'doe' THEN 2 ELSE 0 END}
275
- _(ArelExtensions::Nodes::Case.new(@table[:name]).when("smith").then(1).when("doe").then(2).else(0).to_sql)
255
+ ArelExtensions::Nodes::Case.new(@table[:name]).when("smith").then(1).when("doe").then(2).else(0).to_sql
276
256
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
277
- _(@table[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql)
257
+ @table[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql
278
258
  .must_be_like %{SUM(CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END)}
279
- _(@table[:name].when("smith").then("cool").else("uncool").matches('value',false).to_sql)
259
+ @table[:name].when("smith").then("cool").else("uncool").matches('value',false).to_sql
280
260
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END LIKE 'value'}
281
- _(@table[:name].when("smith").then("cool").else("uncool").imatches('value',false).to_sql)
261
+ @table[:name].when("smith").then("cool").else("uncool").imatches('value',false).to_sql
282
262
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
283
263
  end
284
264
 
285
265
  it "should be possible to use as on anything" do
286
- _(compile(@table[:name].as('alias'))).must_be_like %{"users"."name" AS alias}
287
- _(compile(@table[:name].concat(' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
288
- _(compile((@table[:name] + ' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
289
- _(compile((@table[:age] + 42).as('alias'))).must_be_like %{("users"."age" + 42) AS alias}
290
- _(compile(@table[:name].coalesce('').as('alias'))).must_be_like %{COALESCE("users"."name", '') AS alias}
291
- _(compile(Arel::Nodes.build_quoted('test').as('alias'))).must_be_like %{'test' AS alias}
292
- _(compile(@table.project(@table[:name]).as('alias'))).must_be_like %{(SELECT "users"."name" FROM "users") alias}
293
- _(compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')))
294
- .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
266
+ compile(@table[:name].as('alias')).must_be_like %{"users"."name" AS alias}
267
+ compile(@table[:name].concat(' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
268
+ compile((@table[:name] + ' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
269
+ compile((@table[:age] + 42).as('alias')).must_be_like %{("users"."age" + 42) AS alias}
270
+ compile(@table[:name].coalesce('').as('alias')).must_be_like %{COALESCE("users"."name", '') AS alias}
271
+ compile(Arel::Nodes.build_quoted('test').as('alias')).must_be_like %{'test' AS alias}
272
+ compile(@table.project(@table[:name]).as('alias')).must_be_like %{(SELECT "users"."name" FROM "users") alias}
273
+ compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')).
274
+ must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
295
275
  end
296
276
 
297
277
  it "should accept comparators on functions" do
298
278
  c = @table[:name]
299
- _(compile(c.soundex == 'test')).must_be_like %{SOUNDEX("users"."name") = 'test'}
300
- _(compile(c.soundex != 'test')).must_be_like %{SOUNDEX("users"."name") != 'test'}
301
- _(compile(c.length >= 0)).must_be_like %{LENGTH("users"."name") >= 0}
279
+ compile(c.soundex == 'test').must_be_like %{SOUNDEX("users"."name") = 'test'}
280
+ compile(c.soundex != 'test').must_be_like %{SOUNDEX("users"."name") != 'test'}
281
+ compile(c.length >= 0 ).must_be_like %{LENGTH("users"."name") >= 0}
302
282
  end
303
283
 
304
284
  it "should accept in on select statement" do
305
285
  c = @table[:name]
306
- _(compile(c.in(@table.project(@table[:name]))))
286
+ compile(c.in(@table.project(@table[:name])))
307
287
  .must_be_like %{"users"."name" IN (SELECT "users"."name" FROM "users")}
308
288
  end
309
289
 
310
290
  it "should accept coalesce function properly even on none actual tables and attributes" do
311
291
  fake_at = Arel::Table.new('fake_table')
312
- _(compile(fake_at['fake_attribute'].coalesce('other_value')))
292
+ compile(fake_at['fake_attribute'].coalesce('other_value'))
313
293
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value')}
314
- _(compile(fake_at['fake_attribute'].coalesce('other_value1','other_value2')))
294
+ compile(fake_at['fake_attribute'].coalesce('other_value1','other_value2'))
315
295
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value1', 'other_value2')}
316
- _(compile(fake_at['fake_attribute'].coalesce('other_value1').coalesce('other_value2')))
296
+ compile(fake_at['fake_attribute'].coalesce('other_value1').coalesce('other_value2'))
317
297
  .must_be_like %{COALESCE(COALESCE("fake_table"."fake_attribute", 'other_value1'), 'other_value2')}
318
- _(compile(fake_at['fake_attribute'].coalesce('other_value').matches('truc')))
298
+ compile(fake_at['fake_attribute'].coalesce('other_value').matches('truc'))
319
299
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value') LIKE 'truc'}
320
- _(compile(fake_at['fake_attribute'].coalesce('other_value').imatches('truc')))
300
+ compile(fake_at['fake_attribute'].coalesce('other_value').imatches('truc'))
321
301
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value') ILIKE 'truc'}
322
302
  end
323
303
 
324
304
  it "should be possible to cast nodes types" do
325
- _(compile(@table[:id].cast('char')))
305
+ compile(@table[:id].cast('char'))
326
306
  .must_be_like %{CAST("users"."id" AS char)}
327
- _(compile(@table[:id].coalesce(' ').cast('char')))
307
+ compile(@table[:id].coalesce(' ').cast('char'))
328
308
  .must_be_like %{CAST(COALESCE("users"."id", ' ') AS char)}
329
- _(compile(@table[:id].coalesce(' ').cast(:string)))
309
+ compile(@table[:id].coalesce(' ').cast(:string))
330
310
  .must_be_like %{CAST(COALESCE("users"."id", ' ') AS char)}
331
- _(compile(@table[:id].cast(:string).coalesce(' ')))
311
+ compile(@table[:id].cast(:string).coalesce(' '))
332
312
  .must_be_like %{COALESCE(CAST(\"users\".\"id\" AS char), ' ')}
333
- _(compile(@table[:id].cast('char') + ' '))
313
+ compile(@table[:id].cast('char') + ' ')
334
314
  .must_be_like %{CONCAT(CAST("users"."id" AS char), ' ')}
335
- _(compile(@table[:id].cast('int') + 2))
315
+ compile(@table[:id].cast('int') + 2)
336
316
  .must_be_like %{(CAST("users"."id" AS int) + 2)}
337
317
  end
338
318
 
339
- describe "the function in" do
340
- it "should be possible to have nil element in the function IN" do
341
- _(compile(@table[:id].in(nil)))
342
- .must_be_like %{ISNULL("users"."id")}
343
- _(compile(@table[:id].in([nil])))
344
- .must_be_like %{ISNULL("users"."id")}
345
- _(compile(@table[:id].in([nil,1])))
346
- .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" = 1)}
347
- _(compile(@table[:id].in([nil,1,2])))
348
- .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" IN (1, 2))}
349
- _(compile(@table[:id].in(1)))
350
- .must_be_like %{"users"."id" IN (1)}
351
- _(compile(@table[:id].in([1])))
352
- .must_be_like %{"users"."id" = 1}
353
- _(compile(@table[:id].in([1,2])))
354
- .must_be_like %{"users"."id" IN (1, 2)}
355
- _(compile(@table[:id].in([])))
356
- .must_be_like %{1 = 0}
357
- end
358
-
359
- it "should be possible to correctly use a Range on an IN" do
360
- _(compile(@table[:id].in(1..4)))
361
- .must_be_like %{"users"."id" BETWEEN (1) AND (4)}
362
- _(compile(@table[:created_at].in(Date.new(2016, 3, 31)..Date.new(2017, 3, 31))))
363
- .must_be_like %{"users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')}
364
- end
365
-
366
- it "should be possible to use a list of values and ranges on an IN" do
367
- _(compile(@table[:id].in [1..10, 20, 30, 40..50]))
368
- .must_be_like %{("users"."id" IN (20, 30)) OR ("users"."id" BETWEEN (1) AND (10)) OR ("users"."id" BETWEEN (40) AND (50))}
369
- _(compile(@table[:created_at].in(Date.new(2016, 1, 1), Date.new(2016, 2, 1)..Date.new(2016, 2, 28), Date.new(2016, 3, 31)..Date.new(2017, 3, 31), Date.new(2018, 1, 1))))
370
- .must_be_like %{ ("users"."created_at" IN ('2016-01-01', '2018-01-01'))
371
- OR ("users"."created_at" BETWEEN ('2016-02-01') AND ('2016-02-28'))
372
- OR ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31'))}
373
- end
374
-
375
- it "should respecting Grouping" do
376
- g = ->(*v) { Arel::Nodes::Grouping.new(v) }
377
- _(compile(g[@table[:id], @table[:age]].in [g[1, 42]]))
378
- .must_be_like %{("users"."id", "users"."age") IN ((1, 42))}
379
- _(compile(g[@table[:id], @table[:age]].in [g[1, 42], g[2, 51]]))
380
- .must_be_like %{("users"."id", "users"."age") IN ((1, 42), (2, 51))}
381
-
382
- _(compile(g[@table[:id], @table[:age]].in(g[1, 42], g[2, 51])))
383
- .must_be_like %{("users"."id", "users"."age") IN ((1, 42), (2, 51))}
384
- end
319
+ it "should be possible to have nil element in the function NIL" do
320
+ compile(@table[:id].in(nil))
321
+ .must_be_like %{ISNULL("users"."id")}
322
+ compile(@table[:id].in([nil]))
323
+ .must_be_like %{ISNULL("users"."id")}
324
+ compile(@table[:id].in([nil,1]))
325
+ .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" = 1)}
326
+ compile(@table[:id].in([nil,1,2]))
327
+ .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" IN (1, 2))}
328
+ compile(@table[:id].in(1))
329
+ .must_be_like %{"users"."id" IN (1)}
330
+ compile(@table[:id].in([1]))
331
+ .must_be_like %{"users"."id" IN (1)}
332
+ compile(@table[:id].in([1,2]))
333
+ .must_be_like %{"users"."id" IN (1, 2)}
385
334
  end
386
335
 
387
- describe "the function not_in" do
388
- it "should be possible to have nil element in the function IN" do
389
- _(compile(@table[:id].not_in nil))
390
- .must_be_like %{NOT ISNULL("users"."id")}
391
- _(compile(@table[:id].not_in [nil]))
392
- .must_be_like %{NOT ISNULL("users"."id")}
393
- _(compile(@table[:id].not_in [nil,1]))
394
- .must_be_like %{(NOT ISNULL("users"."id")) AND ("users"."id" != 1)}
395
- _(compile(@table[:id].not_in [nil,1,2]))
396
- .must_be_like %{(NOT ISNULL("users"."id")) AND ("users"."id" NOT IN (1, 2))}
397
- _(compile(@table[:id].not_in 1))
398
- .must_be_like %{"users"."id" NOT IN (1)}
399
- _(compile(@table[:id].not_in [1]))
400
- .must_be_like %{"users"."id" != 1}
401
- _(compile(@table[:id].not_in [1,2]))
402
- .must_be_like %{"users"."id" NOT IN (1, 2)}
403
- _(compile(@table[:id].not_in []))
404
- .must_be_like %{1 = 1}
405
- end
406
-
407
- it "should be possible to correctly use a Range on an IN" do
408
- # FIXME: Should use NOT BETWEEN
409
- _(compile(@table[:id].not_in 1..4))
410
- .must_be_like %{NOT ("users"."id" BETWEEN (1) AND (4))}
411
- # FIXME: Should use NOT BETWEEN
412
- _(compile(@table[:created_at].not_in Date.new(2016, 3, 31)..Date.new(2017, 3, 31)))
413
- .must_be_like %{NOT ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31'))}
414
- end
415
-
416
- it "should be possible to use a list of values and ranges on an IN" do
417
- _(compile(@table[:id].not_in [1..10, 20, 30, 40..50]))
418
- .must_be_like %{ ("users"."id" NOT IN (20, 30))
419
- AND (NOT ("users"."id" BETWEEN (1) AND (10)))
420
- AND (NOT ("users"."id" BETWEEN (40) AND (50)))}
421
- _(compile(@table[:created_at].not_in Date.new(2016, 1, 1), Date.new(2016, 2, 1)..Date.new(2016, 2, 28), Date.new(2016, 3, 31)..Date.new(2017, 3, 31), Date.new(2018, 1, 1)))
422
- .must_be_like %{ ("users"."created_at" NOT IN ('2016-01-01', '2018-01-01'))
423
- AND (NOT ("users"."created_at" BETWEEN ('2016-02-01') AND ('2016-02-28')))
424
- AND (NOT ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')))}
425
- end
336
+ it "should be possible to correctly use a Range on an IN" do
337
+ compile(@table[:id].in(1..4))
338
+ .must_be_like %{"users"."id" BETWEEN (1) AND (4)}
339
+ compile(@table[:created_at].in(@date .. Date.new(2017, 3, 31))) # @date = Date.new(2016, 3, 31)
340
+ .must_be_like %{"users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')}
426
341
  end
427
342
 
428
343
  it "should be possible to add and substract as much as we want" do
429
344
  c = @table[:name]
430
- _(compile(c.locate('test')+1))
345
+ compile(c.locate('test')+1)
431
346
  .must_be_like %{(LOCATE('test', "users"."name") + 1)}
432
- _(compile(c.locate('test')-1))
347
+ compile(c.locate('test')-1)
433
348
  .must_be_like %{(LOCATE('test', "users"."name") - 1)}
434
- _(compile(c.locate('test')+c.locate('test')))
349
+ compile(c.locate('test')+c.locate('test'))
435
350
  .must_be_like %{(LOCATE('test', "users"."name") + LOCATE('test', "users"."name"))}
436
- _(compile(c.locate('test')+1+c.locate('test')-1 + 1))
351
+ compile(c.locate('test')+1+c.locate('test')-1 + 1)
437
352
  .must_be_like %{((((LOCATE('test', "users"."name") + 1) + LOCATE('test', "users"."name")) - 1) + 1)}
438
353
  end
439
354
 
440
355
  it "should be possible to add and substract on some nodes" do
441
356
  c = @table[:name]
442
- _(compile(c.when(0,0).else(42) + 42)).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END + 42)}
443
- _(compile(c.when(0,0).else(42) - 42)).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END - 42)}
444
- _(compile(c.when(0,"0").else("42") + "42")).must_be_like %{CONCAT(CASE "users"."name" WHEN 0 THEN '0' ELSE '42' END, '42')}
357
+ compile(c.when(0,0).else(42) + 42).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END + 42)}
358
+ compile(c.when(0,0).else(42) - 42).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END - 42)}
359
+ compile(c.when(0,"0").else("42") + "42").must_be_like %{CONCAT(CASE "users"."name" WHEN 0 THEN '0' ELSE '42' END, '42')}
445
360
  end
446
361
 
447
362
  it "should be possible to desc and asc on functions" do
448
363
  c = @table[:name]
449
- _(compile(c.asc))
364
+ compile(c.asc)
450
365
  .must_be_like %{"users"."name" ASC}
451
- _(compile(c.substring(2).asc))
366
+ compile(c.substring(2).asc)
452
367
  .must_be_like %{SUBSTRING("users"."name", 2) ASC}
453
- _(compile(c.substring(2).desc))
368
+ compile(c.substring(2).desc)
454
369
  .must_be_like %{SUBSTRING("users"."name", 2) DESC}
455
- _(compile((c.locate('test')+1).asc))
370
+ compile((c.locate('test')+1).asc)
456
371
  .must_be_like %{(LOCATE('test', "users"."name") + 1) ASC}
457
372
  end
458
373
 
459
- it "should be possible to call Table function on TableAlias" do
460
- t = @table
461
- a = t.alias("aliased_users")
462
- _(compile(a.join(t).join_sources))
463
- .must_be_like %{INNER JOIN \"users\"}
464
- end
465
-
466
- describe "logical functions" do
467
- it "should know about truth" do
468
- _(compile(Arel.false))
469
- .must_be_like %{1 = 0}
470
-
471
- _(compile(Arel::true))
472
- .must_be_like %{1 = 1}
473
- end
474
-
475
- it "boolean nodes should be variadic" do
476
- c = @table[:id]
477
-
478
- _(compile(Arel::Nodes::And.new))
479
- .must_be_like %{1 = 1}
480
- _(compile(Arel::Nodes::And.new(c == 1)))
481
- .must_be_like %{"users"."id" = 1}
482
- _(compile(Arel::Nodes::And.new(c == 1, c == 2)))
483
- .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2)}
484
- _(compile(Arel::Nodes::And.new [c == 1, c == 2, c == 3]))
485
- .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
486
-
487
-
488
- _(compile(Arel::Nodes::Or.new))
489
- .must_be_like %{1 = 0}
490
- _(compile(Arel::Nodes::Or.new(c == 1)))
491
- .must_be_like %{"users"."id" = 1}
492
- _(compile(Arel::Nodes::Or.new(c == 1, c == 2)))
493
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2)}
494
- _(compile(Arel::Nodes::Or.new(c == 1, c == 2, c == 3)))
495
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
496
- _(compile(Arel::Nodes::Or.new [c == 1, c == 2, c == 3]))
497
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
498
- end
499
-
500
- it "should know trivial identities" do
501
- skip "For future optimization"
502
- c = @table[:id]
503
- _(compile(Arel::Nodes::And.new(Arel.true, c == 1)))
504
- .must_be_like %{"users"."id" = 1}
505
- _(compile(Arel::Nodes::And.new(Arel.false, c == 1)))
506
- .must_be_like %{1 = 0}
507
- _(compile(Arel::Nodes::And.new(c == 1, c == 1)))
508
- .must_be_like %{"users"."id" = 1}
509
-
510
- _(compile(Arel::Nodes::Or.new(Arel.true, c == 1)))
511
- .must_be_like %{1 = 1}
512
- _(compile(Arel::Nodes::Or.new(Arel.false, c == 1)))
513
- .must_be_like %{"users"."id" = 1}
514
- _(compile(Arel::Nodes::Or.new(c == 1, c == 1)))
515
- .must_be_like %{"users"."id" = 1}
516
- end
517
-
518
- it "should be possible to have multiple arguments on an OR or an AND node" do
519
- c = @table[:id]
520
- _(compile((c == 1).and))
521
- .must_be_like %{"users"."id" = 1}
522
-
523
- _(compile((c == 1).and(c == 2, c == 3)))
524
- .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
525
- _(compile((c == 1).and([c == 2, c == 3])))
526
- .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
527
-
528
- _(compile((c == 1).or))
529
- .must_be_like %{"users"."id" = 1}
530
-
531
- _(compile((c == 1).or(c == 2, c == 3)))
532
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
533
- _(compile((c == 1).or([c == 2, c == 3])))
534
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
535
- end
536
-
537
- it "should avoid useless nesting" do
538
- c = @table[:id]
539
- _(compile(((c == 1).and(c == 2)).and ((c == 3).and(c == 4))))
540
- .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3) AND ("users"."id" = 4)}
541
- _(compile(((c == 1).or(c == 2)).or ((c == 3).or(c == 4))))
542
- .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3) OR ("users"."id" = 4)}
543
-
544
- _(compile(((c == 1).or(c == 2)).and ((c == 3).or(c == 4))))
545
- .must_be_like %{(("users"."id" = 1) OR ("users"."id" = 2)) AND (("users"."id" = 3) OR ("users"."id" = 4))}
546
- _(compile(((c == 1).and(c == 2)).or ((c == 3).and(c == 4))))
547
- .must_be_like %{(("users"."id" = 1) AND ("users"."id" = 2)) OR (("users"."id" = 3) AND ("users"."id" = 4))}
548
- end
374
+ it "should be possible to have multiple arguments on an OR or an AND node" do
375
+ c = @table[:id]
376
+ compile((c == 1).and(c == 2, c == 3)).
377
+ must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
378
+ compile((c == 1).and([c == 2, c == 3])).
379
+ must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
380
+ compile((c == 1).or(c == 2, c == 3)).
381
+ must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
382
+ compile((c == 1).or([c == 2, c == 3])).
383
+ must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
549
384
  end
550
385
 
551
386
  puts "AREL VERSION : " + Arel::VERSION.to_s