arel_extensions 1.2.25 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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/attributes.rb +1 -0
  19. data/lib/arel_extensions/boolean_functions.rb +14 -55
  20. data/lib/arel_extensions/common_sql_functions.rb +8 -7
  21. data/lib/arel_extensions/comparators.rb +15 -14
  22. data/lib/arel_extensions/date_duration.rb +5 -4
  23. data/lib/arel_extensions/insert_manager.rb +16 -17
  24. data/lib/arel_extensions/math.rb +12 -11
  25. data/lib/arel_extensions/math_functions.rb +22 -29
  26. data/lib/arel_extensions/nodes/abs.rb +1 -0
  27. data/lib/arel_extensions/nodes/blank.rb +1 -0
  28. data/lib/arel_extensions/nodes/case.rb +8 -11
  29. data/lib/arel_extensions/nodes/cast.rb +2 -4
  30. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  31. data/lib/arel_extensions/nodes/change_case.rb +0 -0
  32. data/lib/arel_extensions/nodes/coalesce.rb +3 -2
  33. data/lib/arel_extensions/nodes/collate.rb +2 -1
  34. data/lib/arel_extensions/nodes/concat.rb +16 -7
  35. data/lib/arel_extensions/nodes/date_diff.rb +13 -10
  36. data/lib/arel_extensions/nodes/duration.rb +3 -0
  37. data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
  38. data/lib/arel_extensions/nodes/floor.rb +1 -1
  39. data/lib/arel_extensions/nodes/format.rb +8 -34
  40. data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
  41. data/lib/arel_extensions/nodes/function.rb +16 -25
  42. data/lib/arel_extensions/nodes/json.rb +36 -43
  43. data/lib/arel_extensions/nodes/length.rb +0 -5
  44. data/lib/arel_extensions/nodes/levenshtein_distance.rb +0 -0
  45. data/lib/arel_extensions/nodes/locate.rb +1 -0
  46. data/lib/arel_extensions/nodes/log10.rb +2 -1
  47. data/lib/arel_extensions/nodes/matches.rb +6 -4
  48. data/lib/arel_extensions/nodes/md5.rb +1 -0
  49. data/lib/arel_extensions/nodes/power.rb +5 -5
  50. data/lib/arel_extensions/nodes/rand.rb +1 -0
  51. data/lib/arel_extensions/nodes/repeat.rb +4 -2
  52. data/lib/arel_extensions/nodes/replace.rb +6 -22
  53. data/lib/arel_extensions/nodes/round.rb +6 -5
  54. data/lib/arel_extensions/nodes/soundex.rb +15 -15
  55. data/lib/arel_extensions/nodes/std.rb +21 -18
  56. data/lib/arel_extensions/nodes/substring.rb +16 -8
  57. data/lib/arel_extensions/nodes/then.rb +0 -0
  58. data/lib/arel_extensions/nodes/trim.rb +5 -3
  59. data/lib/arel_extensions/nodes/union.rb +5 -2
  60. data/lib/arel_extensions/nodes/union_all.rb +3 -0
  61. data/lib/arel_extensions/nodes/wday.rb +4 -0
  62. data/lib/arel_extensions/nodes.rb +1 -1
  63. data/lib/arel_extensions/null_functions.rb +7 -5
  64. data/lib/arel_extensions/predications.rb +34 -35
  65. data/lib/arel_extensions/railtie.rb +5 -5
  66. data/lib/arel_extensions/set_functions.rb +4 -2
  67. data/lib/arel_extensions/string_functions.rb +23 -52
  68. data/lib/arel_extensions/tasks.rb +5 -5
  69. data/lib/arel_extensions/version.rb +1 -1
  70. data/lib/arel_extensions/visitors/ibm_db.rb +12 -5
  71. data/lib/arel_extensions/visitors/mssql.rb +58 -64
  72. data/lib/arel_extensions/visitors/mysql.rb +98 -149
  73. data/lib/arel_extensions/visitors/oracle.rb +70 -73
  74. data/lib/arel_extensions/visitors/oracle12.rb +15 -2
  75. data/lib/arel_extensions/visitors/postgresql.rb +63 -116
  76. data/lib/arel_extensions/visitors/sqlite.rb +70 -83
  77. data/lib/arel_extensions/visitors/to_sql.rb +110 -142
  78. data/lib/arel_extensions/visitors.rb +60 -68
  79. data/lib/arel_extensions.rb +19 -81
  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