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