arel_extensions 1.3.9 → 2.0.0.rc3

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