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
@@ -2,19 +2,22 @@ require 'arelx_test_helper'
|
|
2
2
|
require 'date'
|
3
3
|
|
4
4
|
module ArelExtensions
|
5
|
-
module
|
5
|
+
module WithAr
|
6
6
|
class ListTest < Minitest::Test
|
7
|
-
require 'minitest/pride'
|
8
7
|
def connect_db
|
9
8
|
ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
|
10
|
-
if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE ==
|
11
|
-
@env_db = (RUBY_PLATFORM == 'java' ?
|
12
|
-
skip "Platform not supported"
|
9
|
+
if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx') || (RUBY_PLATFORM == 'java')) # not supported
|
10
|
+
@env_db = (RUBY_PLATFORM == 'java' ? 'jdbc-sqlite' : 'sqlite')
|
11
|
+
skip "Platform not supported (DB: #{ENV['DB']}, RUBY_ENGINE: #{RUBY_ENGINE}, RUBY_PLATFORM: #{RUBY_PLATFORM})"
|
13
12
|
else
|
14
13
|
@env_db = ENV['DB']
|
15
14
|
end
|
16
15
|
ActiveRecord::Base.establish_connection(@env_db.try(:to_sym) || (RUBY_PLATFORM == 'java' ? :"jdbc-sqlite" : :sqlite))
|
17
|
-
ActiveRecord::
|
16
|
+
if ActiveRecord::VERSION::MAJOR >= 7
|
17
|
+
ActiveRecord.default_timezone = :utc
|
18
|
+
else
|
19
|
+
ActiveRecord::Base.default_timezone = :utc
|
20
|
+
end
|
18
21
|
@cnx = ActiveRecord::Base.connection
|
19
22
|
$sqlite = @cnx.adapter_name =~ /sqlite/i
|
20
23
|
$load_extension_disabled ||= false
|
@@ -29,14 +32,14 @@ module ArelExtensions
|
|
29
32
|
t.column :name, :string
|
30
33
|
t.column :comments, :text
|
31
34
|
t.column :created_at, :date
|
32
|
-
t.column :updated_at, :datetime
|
35
|
+
t.column :updated_at, :datetime, precision: nil
|
33
36
|
t.column :duration, :time
|
34
37
|
t.column :other, :string
|
35
|
-
t.column :score, :decimal, :
|
38
|
+
t.column :score, :decimal, precision: 20, scale: 10
|
36
39
|
end
|
37
40
|
@cnx.drop_table(:product_tests) rescue nil
|
38
41
|
@cnx.create_table :product_tests do |t|
|
39
|
-
t.column :price, :decimal, :
|
42
|
+
t.column :price, :decimal, precision: 20, scale: 10
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -51,24 +54,26 @@ module ArelExtensions
|
|
51
54
|
d = Date.new(2016, 5, 23)
|
52
55
|
connect_db
|
53
56
|
setup_db
|
54
|
-
u = User.create :
|
55
|
-
@lucas = User.where(:
|
56
|
-
u = User.create :
|
57
|
-
@sophie = User.where(:
|
58
|
-
u = User.create :
|
59
|
-
@camille = User.where(:
|
60
|
-
u = User.create :
|
61
|
-
@arthur = User.where(:
|
62
|
-
u = User.create :
|
63
|
-
@myung = User.where(:
|
64
|
-
u = User.create :
|
65
|
-
@laure = User.where(:
|
66
|
-
u = User.create :
|
67
|
-
@test = User.where(:
|
68
|
-
u = User.create :
|
69
|
-
@neg = User.where(:
|
70
|
-
u = User.create :
|
71
|
-
@justin = User.where(:
|
57
|
+
u = User.create age: 5, name: 'Lucas', created_at: d, score: 20.16, updated_at: Time.utc(2014, 3, 3, 12, 42, 0)
|
58
|
+
@lucas = User.where(id: u.id)
|
59
|
+
u = User.create age: 15, name: 'Sophie', created_at: d, score: 20.16
|
60
|
+
@sophie = User.where(id: u.id)
|
61
|
+
u = User.create age: 20, name: 'Camille', created_at: d, score: -20.16, comments: ''
|
62
|
+
@camille = User.where(id: u.id)
|
63
|
+
u = User.create age: 21, name: 'Arthur', created_at: d, score: 65.62, comments: 'arrêté'
|
64
|
+
@arthur = User.where(id: u.id)
|
65
|
+
u = User.create age: 23, name: 'Myung', created_at: d, score: 20.16, comments: ' '
|
66
|
+
@myung = User.where(id: u.id)
|
67
|
+
u = User.create age: 25, name: 'Laure', created_at: d, score: 20.16, duration: Time.utc(2001, 1, 1, 12, 42, 21), updated_at: Time.utc(2014, 3, 3, 12, 42, 0)
|
68
|
+
@laure = User.where(id: u.id)
|
69
|
+
u = User.create age: nil, name: 'Test', created_at: d, score: 1.62, other: 'toto'
|
70
|
+
@test = User.where(id: u.id)
|
71
|
+
u = User.create age: -42, name: 'Negatif', comments: '1,22,3,42,2', created_at: d, updated_at: d.to_time, score: 0.17
|
72
|
+
@neg = User.where(id: u.id)
|
73
|
+
u = User.create age: 15, name: 'Justin', created_at: d, score: 11.0
|
74
|
+
@justin = User.where(id: u.id)
|
75
|
+
u = User.create age: nil, name: 'nilly', created_at: nil, score: nil
|
76
|
+
@nilly = User.where(id: u.id)
|
72
77
|
|
73
78
|
@age = User.arel_table[:age]
|
74
79
|
@name = User.arel_table[:name]
|
@@ -103,6 +108,14 @@ module ArelExtensions
|
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
111
|
+
# Connection and column info
|
112
|
+
def test_column_of
|
113
|
+
assert_nil Arel.column_of('chupa', 'maflavla'), 'Non-existent table and column should return nil'
|
114
|
+
assert_nil Arel.column_of('chupa', 'updated_at'), 'Non-existent table but existent column should return nil'
|
115
|
+
assert_nil Arel.column_of('user_tests', 'maflavla'), 'Existent table but non-existent column should return nil'
|
116
|
+
assert_equal 'updated_at', Arel.column_of('user_tests', 'updated_at').name, 'An existing column name should be returned'
|
117
|
+
end
|
118
|
+
|
106
119
|
# Math Functions
|
107
120
|
def test_classical_arel
|
108
121
|
assert_in_epsilon 42.16, t(@laure, @score + 22), 0.01
|
@@ -137,7 +150,7 @@ module ArelExtensions
|
|
137
150
|
def test_rand
|
138
151
|
assert 42 != User.select(Arel.rand.as('res')).first.res
|
139
152
|
assert 0 <= User.select(Arel.rand.abs.as('res')).first.res
|
140
|
-
assert_equal
|
153
|
+
assert_equal 10, User.order(Arel.rand).limit(50).count
|
141
154
|
end
|
142
155
|
|
143
156
|
def test_round
|
@@ -149,16 +162,16 @@ module ArelExtensions
|
|
149
162
|
|
150
163
|
def test_sum
|
151
164
|
if @env_db == 'mssql'
|
152
|
-
skip
|
153
|
-
assert_equal 83, User.select((@age.sum + 1).as(
|
154
|
-
assert_equal 164, User.reorder(nil).select((@age.sum + @age.sum).as(
|
155
|
-
assert_equal 246, User.reorder(nil).select(((@age * 3).sum).as(
|
156
|
-
assert_equal 4234, User.reorder(nil).select(((@age * @age).sum).as(
|
165
|
+
skip 'SQL Server forces order?' # TODO
|
166
|
+
assert_equal 83, User.select((@age.sum + 1).as('res'), User.arel_table[:id].sum).take(50).reorder(@age).first.res
|
167
|
+
assert_equal 164, User.reorder(nil).select((@age.sum + @age.sum).as('res'), User.arel_table[:id].sum).take(50).first.res
|
168
|
+
assert_equal 246, User.reorder(nil).select(((@age * 3).sum).as('res'), User.arel_table[:id].sum).take(50).first.res
|
169
|
+
assert_equal 4234, User.reorder(nil).select(((@age * @age).sum).as('res'), User.arel_table[:id].sum).take(50).first.res
|
157
170
|
else
|
158
|
-
assert_equal 83, User.select((@age.sum + 1).as(
|
159
|
-
assert_equal 164, User.select((@age.sum + @age.sum).as(
|
160
|
-
assert_equal 246, User.select((@age * 3).sum.as(
|
161
|
-
assert_equal 4234, User.select(((@age * @age).sum).as(
|
171
|
+
assert_equal 83, User.select((@age.sum + 1).as('res')).take(50).first.res
|
172
|
+
assert_equal 164, User.select((@age.sum + @age.sum).as('res')).take(50).first.res
|
173
|
+
assert_equal 246, User.select((@age * 3).sum.as('res')).take(50).first.res
|
174
|
+
assert_equal 4234, User.select(((@age * @age).sum).as('res')).take(50).first.res
|
162
175
|
end
|
163
176
|
end
|
164
177
|
|
@@ -166,25 +179,74 @@ module ArelExtensions
|
|
166
179
|
# Since Arel10 (Rails6.1), some unwanted behaviors on aggregated calculation were present.
|
167
180
|
# This should works no matter which version of rails is used
|
168
181
|
assert User.group(:score).average(:id).values.all?{|e| !e.nil?}
|
182
|
+
|
183
|
+
# Since Rails 7, a patch to calculations.rb has tirggered a double
|
184
|
+
# quoting of the alias name. See https://github.com/rails/rails/commit/7e6e9091e55c3357b0162d44b6ab955ed0c718d5
|
185
|
+
# Before the patch that fixed this the following error would occur:
|
186
|
+
# ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: zero-length delimited identifier at or near """"
|
187
|
+
assert User.group(:score).count(:id).values.all?{|e| !e.nil?}
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_rollup
|
191
|
+
skip "sqlite not supported" if $sqlite
|
192
|
+
at = User.arel_table
|
193
|
+
# single
|
194
|
+
q = User.select(at[:name], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:name]]))
|
195
|
+
assert q.to_a.length > 0
|
196
|
+
|
197
|
+
# multi
|
198
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(Arel::Nodes::RollUp.new([at[:score], at[:name]]))
|
199
|
+
assert q.to_a.length > 0
|
200
|
+
|
201
|
+
# hybrid
|
202
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel::Nodes::RollUp.new([at[:name]]))
|
203
|
+
assert q.to_a.length > 0
|
204
|
+
|
205
|
+
## Using Arel.rollup which is less verbose than the original way
|
206
|
+
|
207
|
+
# simple
|
208
|
+
q = User.select(at[:name], at[:age].sum).group(Arel.rollup(at[:name]))
|
209
|
+
assert q.to_a.length > 0
|
210
|
+
|
211
|
+
# multi
|
212
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(Arel.rollup([at[:score], at[:name]]))
|
213
|
+
assert q.to_a.length > 0
|
214
|
+
|
215
|
+
# hybrid
|
216
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:score], Arel.rollup([at[:name]]))
|
217
|
+
assert q.to_a.length > 0
|
218
|
+
|
219
|
+
## Using at[:col].rollup which is handy for single column rollups
|
220
|
+
|
221
|
+
# simple
|
222
|
+
q = User.select(at[:name], at[:age].sum).group(at[:name].rollup)
|
223
|
+
assert q.to_a.length > 0
|
224
|
+
|
225
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name].rollup, at[:score].rollup)
|
226
|
+
assert q.to_a.length > 0
|
227
|
+
|
228
|
+
# hybrid
|
229
|
+
q = User.select(at[:name], at[:score], at[:age].sum).group(at[:name], at[:score].rollup)
|
230
|
+
assert q.to_a.length > 0
|
169
231
|
end
|
170
232
|
|
171
233
|
# String Functions
|
172
234
|
def test_concat
|
173
235
|
assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
|
174
236
|
assert_equal 'Laure 2', t(@laure, @name + ' ' + 2)
|
175
|
-
assert_equal 'Test Laure', t(@laure, Arel
|
176
|
-
|
177
|
-
skip
|
178
|
-
assert_equal
|
179
|
-
assert_equal
|
180
|
-
assert_equal
|
181
|
-
|
182
|
-
skip
|
183
|
-
assert_equal
|
184
|
-
assert_equal
|
185
|
-
assert_equal
|
186
|
-
assert_equal
|
187
|
-
assert_equal
|
237
|
+
assert_equal 'Test Laure', t(@laure, Arel.quoted('Test ') + @name)
|
238
|
+
|
239
|
+
skip 'No group_concat in SqlServer before 2017' if @env_db == 'mssql'
|
240
|
+
assert_equal 'Lucas Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(' '))
|
241
|
+
assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat(','))
|
242
|
+
assert_equal 'Lucas,Sophie', t(User.where(name: %w[Lucas Sophie]), @name.group_concat)
|
243
|
+
|
244
|
+
skip 'No order in group_concat in SqlLite' if $sqlite
|
245
|
+
assert_equal 'Arthur,Lucas,Sophie', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.asc))
|
246
|
+
assert_equal 'Sophie,Lucas,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @name.desc))
|
247
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', [@score.asc, @name.asc]))
|
248
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', @score.asc, @name.asc))
|
249
|
+
assert_equal 'Lucas,Sophie,Arthur', t(User.where(name: %w[Lucas Sophie Arthur]), @name.group_concat(',', order: [@score.asc, @name.asc]))
|
188
250
|
end
|
189
251
|
|
190
252
|
def test_length
|
@@ -195,15 +257,15 @@ module ArelExtensions
|
|
195
257
|
|
196
258
|
def test_md5
|
197
259
|
skip "Sqlite can't do md5" if $sqlite
|
198
|
-
assert_equal
|
199
|
-
assert_equal
|
260
|
+
assert_equal 'e2cf99ca82a7e829d2a4ac85c48154d0', t(@camille, @name.md5)
|
261
|
+
assert_equal 'c3d41bf5efb468a1bcce53bd53726c85', t(@lucas, @name.md5)
|
200
262
|
end
|
201
263
|
|
202
264
|
def test_locate
|
203
265
|
skip "Sqlite version can't load extension for locate" if $sqlite && $load_extension_disabled
|
204
|
-
assert_equal 1, t(@camille, @name.locate(
|
205
|
-
assert_equal 0, t(@lucas, @name.locate(
|
206
|
-
assert_equal 5, t(@lucas, @name.locate(
|
266
|
+
assert_equal 1, t(@camille, @name.locate('C'))
|
267
|
+
assert_equal 0, t(@lucas, @name.locate('z'))
|
268
|
+
assert_equal 5, t(@lucas, @name.locate('s'))
|
207
269
|
end
|
208
270
|
|
209
271
|
def test_substring
|
@@ -213,7 +275,7 @@ module ArelExtensions
|
|
213
275
|
else
|
214
276
|
assert_equal('', t(@lucas, @name.substring(42)))
|
215
277
|
end
|
216
|
-
assert_equal 'Lu', t(@lucas, @name.substring(1,2))
|
278
|
+
assert_equal 'Lu', t(@lucas, @name.substring(1, 2))
|
217
279
|
|
218
280
|
assert_equal 'C', t(@camille, @name[0, 1])
|
219
281
|
assert_equal 'C', t(@camille, @name[0])
|
@@ -222,17 +284,17 @@ module ArelExtensions
|
|
222
284
|
else
|
223
285
|
assert_equal('', t(@lucas, @name[42]))
|
224
286
|
end
|
225
|
-
assert_equal 'Lu', t(@lucas, @name[0,2])
|
287
|
+
assert_equal 'Lu', t(@lucas, @name[0, 2])
|
226
288
|
assert_equal 'Lu', t(@lucas, @name[0..1])
|
227
289
|
|
228
290
|
# substring should accept string function
|
229
291
|
assert_equal 'Ce', t(@camille, @name.substring(1, 1).concat('e'))
|
230
|
-
assert_equal 'Ce', t(@camille, @name.substring(1, 1)+'e')
|
292
|
+
assert_equal 'Ce', t(@camille, @name.substring(1, 1) + 'e')
|
231
293
|
end
|
232
294
|
|
233
295
|
def test_find_in_set
|
234
296
|
skip "Sqlite version can't load extension for find_in_set" if $sqlite && $load_extension_disabled
|
235
|
-
skip
|
297
|
+
skip 'SQL Server does not know about FIND_IN_SET' if @env_db == 'mssql'
|
236
298
|
assert_equal 5, t(@neg, @comments & 2)
|
237
299
|
assert_equal 0, t(@neg, @comments & 6) # not found
|
238
300
|
end
|
@@ -244,10 +306,10 @@ module ArelExtensions
|
|
244
306
|
assert t(@neg, @name >= 'Mest') == true || t(@neg, @name >= 'Mest') == 't' # depends of ar version
|
245
307
|
assert t(@neg, @name <= (@name + 'Z')) == true || t(@neg, @name <= (@name + 'Z')) == 't'
|
246
308
|
elsif @env_db == 'oracle'
|
247
|
-
assert_equal 1, t(@neg,
|
248
|
-
assert_equal 1, t(@neg,
|
249
|
-
assert_equal 1, t(@neg,
|
250
|
-
assert_equal 1, t(@neg,
|
309
|
+
assert_equal 1, t(@neg, Arel.when(@name >= 'Mest').then(1).else(0))
|
310
|
+
assert_equal 1, t(@neg, Arel.when(@name <= (@name + 'Z')).then(1).else(0))
|
311
|
+
assert_equal 1, t(@neg, Arel.when(@name > 'Mest').then(1).else(0))
|
312
|
+
assert_equal 1, t(@neg, Arel.when(@name < (@name + 'Z')).then(1).else(0))
|
251
313
|
else
|
252
314
|
assert_equal 1, t(@neg, @name >= 'Mest')
|
253
315
|
assert_equal 1, t(@neg, @name <= (@name + 'Z'))
|
@@ -260,74 +322,74 @@ module ArelExtensions
|
|
260
322
|
skip "Sqlite can't compare time" if $sqlite
|
261
323
|
skip "Oracle can't compare time" if @env_db == 'oracle'
|
262
324
|
# @created_at == 2016-05-23
|
263
|
-
assert_includes [true,'t',1], t(@laure,
|
264
|
-
assert_includes [false,'f',0], t(@laure,
|
325
|
+
assert_includes [true, 't', 1], t(@laure, Arel.when(@created_at >= '2014-01-01').then(1).else(0))
|
326
|
+
assert_includes [false, 'f', 0], t(@laure, Arel.when(@created_at >= '2018-01-01').then(1).else(0))
|
265
327
|
# @updated_at == 2014-03-03 12:42:00
|
266
|
-
assert_includes [true,'t',1], t(@laure,
|
267
|
-
assert_includes [false,'f',0], t(@laure,
|
328
|
+
assert_includes [true, 't', 1], t(@laure, Arel.when(@updated_at >= '2014-03-03 10:10:10').then(1).else(0))
|
329
|
+
assert_includes [false, 'f', 0], t(@laure, Arel.when(@updated_at >= '2014-03-03 13:10:10').then(1).else(0))
|
268
330
|
# @duration == 12:42:21
|
269
|
-
# puts @laure.select(
|
270
|
-
# puts @laure.select(
|
271
|
-
assert_includes [true,'t',1], t(@laure,
|
272
|
-
assert_includes [false,'f',0], t(@laure,
|
331
|
+
# puts @laure.select(Arel.when(@duration >= '10:10:10').then(1).else(0)).to_sql
|
332
|
+
# puts @laure.select(Arel.when(@duration >= '14:10:10').then(1).else(0)).to_sql
|
333
|
+
assert_includes [true, 't', 1], t(@laure, Arel.when(@duration >= '10:10:10').then(1).else(0))
|
334
|
+
assert_includes [false, 'f', 0], t(@laure, Arel.when(@duration >= '14:10:10').then(1).else(0))
|
273
335
|
end
|
274
336
|
|
275
337
|
def test_regexp_not_regexp
|
276
338
|
skip "Sqlite version can't load extension for regexp" if $sqlite && $load_extension_disabled
|
277
|
-
skip
|
339
|
+
skip 'SQL Server does not know about REGEXP without extensions' if @env_db == 'mssql'
|
278
340
|
assert_equal 1, User.where(@name =~ '^M').count
|
279
|
-
assert_equal
|
341
|
+
assert_equal 8, User.where(@name !~ '^L').count
|
280
342
|
assert_equal 1, User.where(@name =~ /^M/).count
|
281
|
-
assert_equal
|
343
|
+
assert_equal 8, User.where(@name !~ /^L/).count
|
282
344
|
end
|
283
345
|
|
284
346
|
def test_imatches
|
285
347
|
# puts User.where(@name.imatches('m%')).to_sql
|
286
348
|
assert_equal 1, User.where(@name.imatches('m%')).count
|
287
349
|
assert_equal 4, User.where(@name.imatches_any(['L%', '%e'])).count
|
288
|
-
assert_equal
|
350
|
+
assert_equal 8, User.where(@name.idoes_not_match('L%')).count
|
289
351
|
end
|
290
352
|
|
291
353
|
def test_replace
|
292
|
-
assert_equal
|
293
|
-
assert_equal
|
294
|
-
|
295
|
-
skip
|
296
|
-
skip
|
297
|
-
skip
|
298
|
-
assert_equal
|
299
|
-
assert_equal
|
300
|
-
assert_equal
|
354
|
+
assert_equal 'LucaX', t(@lucas, @name.replace('s', 'X'))
|
355
|
+
assert_equal 'replace', t(@lucas, @name.replace(@name, 'replace'))
|
356
|
+
|
357
|
+
skip 'Sqlite does not seem to support regexp_replace' if $sqlite
|
358
|
+
skip 'SQL Server does not know about REGEXP without extensions' if @env_db == 'mssql'
|
359
|
+
skip 'Travis mysql version does not support REGEXP_REPLACE' if @env_db == 'mysql'
|
360
|
+
assert_equal 'LXcXs', t(@lucas, @name.replace(/[ua]/, 'X'))
|
361
|
+
assert_equal 'LXcXs', t(@lucas, @name.regexp_replace(/[ua]/, 'X'))
|
362
|
+
assert_equal 'LXcXs', t(@lucas, @name.regexp_replace('[ua]', 'X'))
|
301
363
|
end
|
302
364
|
|
303
365
|
def test_replace_once
|
304
|
-
skip
|
366
|
+
skip 'TODO'
|
305
367
|
# skip "Sqlite version can't load extension for locate" if $sqlite && $load_extension_disabled
|
306
|
-
assert_equal
|
368
|
+
assert_equal 'LuCas', t(@lucas, @name.substring(1, @name.locate('c') - 1) + 'C' + @name.substring(@name.locate('c') + 1, @name.length))
|
307
369
|
end
|
308
370
|
|
309
371
|
def test_soundex
|
310
372
|
skip "Sqlite version can't load extension for soundex" if $sqlite && $load_extension_disabled
|
311
373
|
skip "PostgreSql version can't load extension for soundex" if @env_db == 'postgresql'
|
312
|
-
assert_equal
|
313
|
-
assert_equal
|
314
|
-
assert_equal
|
374
|
+
assert_equal 'C540', t(@camille, @name.soundex)
|
375
|
+
assert_equal 10, User.where(@name.soundex.eq(@name.soundex)).count
|
376
|
+
assert_equal 10, User.where(@name.soundex == @name.soundex).count
|
315
377
|
end
|
316
378
|
|
317
379
|
def test_change_case
|
318
|
-
assert_equal
|
319
|
-
assert_equal
|
320
|
-
assert_equal
|
380
|
+
assert_equal 'myung', t(@myung, @name.downcase)
|
381
|
+
assert_equal 'MYUNG', t(@myung, @name.upcase)
|
382
|
+
assert_equal 'myung', t(@myung, @name.upcase.downcase)
|
321
383
|
end
|
322
384
|
|
323
385
|
def test_trim
|
324
|
-
assert_equal
|
325
|
-
assert_equal
|
326
|
-
assert_equal
|
327
|
-
assert_equal
|
328
|
-
assert_equal
|
329
|
-
skip
|
330
|
-
assert_equal
|
386
|
+
assert_equal 'Myung', t(@myung, @name.trim)
|
387
|
+
assert_equal 'Myung', t(@myung, @name.trim.ltrim.rtrim)
|
388
|
+
assert_equal 'Myun', t(@myung, @name.rtrim('g'))
|
389
|
+
assert_equal 'yung', t(@myung, @name.ltrim('M'))
|
390
|
+
assert_equal 'yung', t(@myung, (@name + 'M').trim('M'))
|
391
|
+
skip 'Oracle does not accept multi char trim' if @env_db == 'oracle'
|
392
|
+
assert_equal '', t(@myung, @name.rtrim(@name))
|
331
393
|
end
|
332
394
|
|
333
395
|
def test_blank
|
@@ -356,33 +418,244 @@ module ArelExtensions
|
|
356
418
|
assert_equal 'true', t(@neg, @comments.not_blank.then('true', 'false'))
|
357
419
|
end
|
358
420
|
|
421
|
+
# This test repeats a lot of `test_blank` cases.
|
422
|
+
def test_present
|
423
|
+
if @env_db == 'postgresql'
|
424
|
+
assert_includes [true, 't'], t(@myung, @name.present) # depends of adapter
|
425
|
+
assert_includes [false, 'f'], t(@myung, @comments.present)
|
426
|
+
end
|
427
|
+
assert_equal 1, @myung.where(@name.present).count
|
428
|
+
assert_equal 0, @myung.where(@comments.present).count
|
429
|
+
assert_equal 0, @sophie.where(@comments.present).count
|
430
|
+
assert_equal 0, @camille.where(@comments.present).count
|
431
|
+
|
432
|
+
assert_equal 1, @neg.where(@comments.present).count
|
433
|
+
assert_equal 'true', t(@myung, @name.present.then('true', 'false'))
|
434
|
+
assert_equal 'false', t(@myung, @comments.present.then('true', 'false'))
|
435
|
+
assert_equal 'true', t(@neg, @comments.present.then('true', 'false'))
|
436
|
+
end
|
437
|
+
|
359
438
|
def test_format
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
439
|
+
%i[format format_date].each do |method|
|
440
|
+
assert_equal '2016-05-23', t(@lucas, @created_at.send(method, '%Y-%m-%d'))
|
441
|
+
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S'))
|
442
|
+
assert_equal '12:42%', t(@lucas, @updated_at.send(method, '%R%%'))
|
443
|
+
|
444
|
+
# The following tests will ensure proper conversion of timestamps to
|
445
|
+
# requested timezones.
|
446
|
+
#
|
447
|
+
# The names of the timezones is highly dependant on the underlying
|
448
|
+
# operating system, and this is why we need to handle each database
|
449
|
+
# separately: the images we're using to test these databases are
|
450
|
+
# different. So don't rely on the provided examples. Your setup is your
|
451
|
+
# reference.
|
452
|
+
#
|
453
|
+
# One could always have portable code if s/he uses standard
|
454
|
+
# abbreviations, like:
|
455
|
+
#
|
456
|
+
# 1. CET => Central European Time
|
457
|
+
# 2. CEST => Central European Summer Time
|
458
|
+
#
|
459
|
+
# Which implies that the caller should handle daylight saving detection.
|
460
|
+
# In fact, CET will handle daylight saving in MySQL but not Postgres.
|
461
|
+
#
|
462
|
+
# It looks like the posix convention is supported by mysql and
|
463
|
+
# postgresql, e.g.:
|
464
|
+
#
|
465
|
+
# posix/Europe/Paris
|
466
|
+
# posix/America/Nipigon
|
467
|
+
#
|
468
|
+
# so it looks like a more reliably portable way of specifying it.
|
469
|
+
time_zones = {
|
470
|
+
'mssql' => {
|
471
|
+
'utc' => 'UTC',
|
472
|
+
'sao_paulo' => 'Argentina Standard Time',
|
473
|
+
'tahiti' => 'Hawaiian Standard Time',
|
474
|
+
'paris' => 'Central European Standard Time'
|
475
|
+
},
|
476
|
+
'posix' => {
|
477
|
+
'utc' => 'UTC',
|
478
|
+
'sao_paulo' => 'America/Sao_Paulo',
|
479
|
+
'tahiti' => 'Pacific/Tahiti',
|
480
|
+
'paris' => 'Europe/Paris'
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if !%w[mssql mysql oracle postgresql].include?(ENV['DB'])
|
485
|
+
# TODO: Standarize timezone conversion across all databases.
|
486
|
+
# This test case will be refactored and should work the same across all vendors.
|
487
|
+
if ENV['DB'] == 'mssql' && /Microsoft SQL Server (\d+)/.match(ActiveRecord::Base.connection.select_value('SELECT @@version'))[1].to_i < 2016
|
488
|
+
skip "SQL Server < 2016 is not currently supported"
|
489
|
+
end
|
490
|
+
|
491
|
+
tz = ENV['DB'] == 'mssql' ? time_zones['mssql'] : time_zones['posix']
|
492
|
+
|
493
|
+
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['utc']))
|
494
|
+
assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['sao_paulo']}))
|
495
|
+
assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['tahiti']}))
|
496
|
+
|
497
|
+
# Skipping conversion from UTC to the desired timezones fails in SQL
|
498
|
+
# Server and Postgres. This is mainly due to the fact that timezone
|
499
|
+
# information is not preserved in the column itself.
|
500
|
+
#
|
501
|
+
# MySQL is happy to consider that times by default are in UTC.
|
502
|
+
assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
503
|
+
refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['paris'])) if !%w[mysql postgresql].include?(ENV['DB'])
|
504
|
+
|
505
|
+
# Winter/Summer time
|
506
|
+
assert_equal '2014/08/03 14:42:00', t(@lucas, (@updated_at + 5.months).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
507
|
+
if ENV['DB'] == 'mssql'
|
508
|
+
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
509
|
+
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
510
|
+
else
|
511
|
+
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel.quoted('2022-02-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
|
512
|
+
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel.quoted('2022-08-01 10:42:00').cast(:datetime).send(method, '%Y/%m/%d %H:%M:%S', tz['paris']))
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_format_iso_week
|
518
|
+
%i[format format_date].each do |method|
|
519
|
+
skip "Unsupported ISO week number for DB=#{ENV['DB']}" if ['sqlite'].include?(ENV['DB'])
|
520
|
+
assert_equal '10', t(@lucas, @updated_at.send(method, '%V'))
|
521
|
+
{
|
522
|
+
'2024-01-01 10:42:00' => '01', # Monday
|
523
|
+
'2030-01-01 10:42:00' => '01', # Tuesday
|
524
|
+
'2025-01-01 10:42:00' => '01', # Wednesday
|
525
|
+
'2026-01-01 10:42:00' => '01', # Thursday
|
526
|
+
'2027-01-01 10:42:00' => '53', # Friday
|
527
|
+
'2028-01-01 10:42:00' => '52', # Saturday
|
528
|
+
'2034-01-01 10:42:00' => '52', # Sunday
|
529
|
+
}.each do |date, exp|
|
530
|
+
assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%V'))
|
531
|
+
end
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
def test_format_iso_year_of_week
|
536
|
+
skip "Unsupported ISO year of week for DB=#{ENV['DB']}" if %w[mssql sqlite].include?(ENV['DB'])
|
537
|
+
%i[format format_date].each do |method|
|
538
|
+
assert_equal '2014', t(@lucas, @updated_at.send(method, '%G'))
|
539
|
+
|
540
|
+
{
|
541
|
+
'2024-01-01 10:42:00' => '2024', # Monday
|
542
|
+
'2030-01-01 10:42:00' => '2030', # Tuesday
|
543
|
+
'2025-01-01 10:42:00' => '2025', # Wednesday
|
544
|
+
'2026-01-01 10:42:00' => '2026', # Thursday
|
545
|
+
'2027-01-01 10:42:00' => '2026', # Friday
|
546
|
+
'2028-01-01 10:42:00' => '2027', # Saturday
|
547
|
+
'2034-01-01 10:42:00' => '2033', # Sunday
|
548
|
+
}.each do |date, exp|
|
549
|
+
assert_equal exp, t(@lucas, Arel.quoted(date).cast(:datetime).send(method, '%G'))
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_format_date_with_names
|
555
|
+
skip "#{ENV['DB']} does not support a variety of word-based formatting for month and day names" if %w[mssql sqlite].include?(ENV['DB'])
|
556
|
+
%i[format format_date].each do |method|
|
557
|
+
assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
|
558
|
+
assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
559
|
+
end
|
560
|
+
|
561
|
+
skip "#{ENV['DB']} does not support ALLCAPS month and day names" if ['mysql'].include?(ENV['DB'])
|
562
|
+
%i[format format_date].each do |method|
|
563
|
+
|
564
|
+
assert_equal 'Mon, 03 MAR 14', t(@lucas, @updated_at.send(method, '%a, %d %^b %y'))
|
565
|
+
assert_equal 'Monday, 03 MARCH 14', t(@lucas, @updated_at.send(method, '%A, %d %^B %y'))
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
def switch_to_lang(lang)
|
570
|
+
languages = {
|
571
|
+
'mssql' => {en: 'English', fr: 'French'},
|
572
|
+
'mysql' => {en: 'en_US', fr: 'fr_FR'},
|
573
|
+
'postgresql' => {en: 'en_US.utf8', fr: 'fr_FR.utf8'}
|
574
|
+
}
|
575
|
+
|
576
|
+
sql = {
|
577
|
+
'mssql' => ->(l) { "SET LANGUAGE #{l};" },
|
578
|
+
'mysql' => ->(l) { "SET lc_time_names = '#{l}';" },
|
579
|
+
'postgresql' => ->(l) { "SET lc_time to '#{l}';" }
|
580
|
+
}
|
581
|
+
|
582
|
+
User.connection.execute(sql[ENV['DB']][languages[ENV['DB']][lang]])
|
583
|
+
end
|
584
|
+
|
585
|
+
def test_format_date_with_names_and_lang_switch
|
586
|
+
skip "#{ENV['DB']} does not support word-based formatting for month and day names" if ['sqlite'].include?(ENV['DB'])
|
587
|
+
|
588
|
+
# the begin-rescue block is here to make sure we set the db back to en_US
|
589
|
+
# if we fail, so that other tests don't get contaminated.
|
590
|
+
#
|
591
|
+
# Tests should assert one single thing in principle, but until we
|
592
|
+
# refactor this whole thing, we'll have to do tricks of this sort.
|
593
|
+
%i[format format_date].each do |method|
|
594
|
+
begin
|
595
|
+
switch_to_lang(:en)
|
596
|
+
case ENV['DB']
|
597
|
+
when 'mysql', 'postgresql'
|
598
|
+
assert_equal 'Mon, 03 Mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
|
599
|
+
assert_equal 'Monday, 03 March 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
600
|
+
when 'mssql'
|
601
|
+
assert_equal 'Monday, 03 March 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
602
|
+
end
|
603
|
+
switch_to_lang(:fr)
|
604
|
+
case ENV['DB']
|
605
|
+
when 'mysql'
|
606
|
+
assert_equal 'lun, 03 mar 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
|
607
|
+
assert_equal 'lundi, 03 mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
608
|
+
when 'postgresql'
|
609
|
+
assert_equal 'Lun., 03 Mars 14', t(@lucas, @updated_at.send(method, '%a, %d %b %y'))
|
610
|
+
assert_equal 'Lundi, 03 Mars 14', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
611
|
+
when 'mssql'
|
612
|
+
assert_equal 'lundi, 03 mars 2014', t(@lucas, @updated_at.send(method, '%A, %d %B %y'))
|
613
|
+
end
|
614
|
+
ensure
|
615
|
+
switch_to_lang(:en)
|
616
|
+
end
|
617
|
+
end
|
364
618
|
end
|
365
619
|
|
366
620
|
def test_coalesce
|
367
|
-
assert_equal 'Camille concat', t(@camille, @name.coalesce(nil,
|
621
|
+
assert_equal 'Camille concat', t(@camille, @name.coalesce(nil, 'default') + ' concat')
|
368
622
|
|
369
|
-
assert_equal 'toto', t(@test, @other.coalesce(
|
623
|
+
assert_equal 'toto', t(@test, @other.coalesce(''))
|
370
624
|
|
371
|
-
assert_equal ' ', t(@myung, @comments.coalesce(
|
372
|
-
assert_equal 'Laure', t(@laure, @comments.coalesce(
|
625
|
+
assert_equal ' ', t(@myung, @comments.coalesce('Myung').coalesce('ignored'))
|
626
|
+
assert_equal 'Laure', t(@laure, @comments.coalesce('Laure'))
|
373
627
|
if @env_db == 'oracle'
|
374
|
-
assert_nil t(@laure, @comments.coalesce(
|
375
|
-
assert_nil t(@camille, @other.coalesce(
|
628
|
+
assert_nil t(@laure, @comments.coalesce(''))
|
629
|
+
assert_nil t(@camille, @other.coalesce(''))
|
376
630
|
else
|
377
|
-
assert_equal('', t(@laure, @comments.coalesce(
|
378
|
-
assert_equal '', t(@camille, @other.coalesce(
|
631
|
+
assert_equal('', t(@laure, @comments.coalesce('')))
|
632
|
+
assert_equal '', t(@camille, @other.coalesce(''))
|
379
633
|
end
|
380
634
|
assert_equal 100, t(@test, @age.coalesce(100))
|
381
|
-
assert_equal
|
635
|
+
assert_equal 'Camille', t(@camille, @name.coalesce(nil, 'default'))
|
382
636
|
assert_equal 20, t(@test, @age.coalesce(nil, 20))
|
383
637
|
|
384
|
-
assert_equal 20, t(@test, @age.coalesce(10)+10)
|
385
|
-
assert_equal 'Laure10', t(@laure, @comments.coalesce(
|
638
|
+
assert_equal 20, t(@test, @age.coalesce(10) + 10)
|
639
|
+
assert_equal 'Laure10', t(@laure, @comments.coalesce('Laure') + 10)
|
640
|
+
end
|
641
|
+
|
642
|
+
def test_coalesce_blank
|
643
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('Myung').coalesce_blank('ignored'))
|
644
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ').coalesce_blank('Myung'))
|
645
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank('', ' ', ' ', 'Myung'))
|
646
|
+
assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format('%Y-%m-%d'))
|
647
|
+
assert_equal '2016-05-23', t(@myung, @created_at.coalesce_blank(Date.new(2022, 1, 1)).format_date('%Y-%m-%d'))
|
648
|
+
assert_equal 'Laure', t(@laure, @comments.coalesce_blank('Laure'))
|
649
|
+
assert_equal 100, t(@test, @age.coalesce_blank(100))
|
650
|
+
assert_equal 20, t(@test, @age.coalesce_blank(20))
|
651
|
+
assert_equal 20, t(@test, @age.coalesce_blank(10) + 10)
|
652
|
+
assert_equal 'Laure10', t(@laure, @comments.coalesce_blank('Laure') + 10)
|
653
|
+
|
654
|
+
skip 'mssql does not support null in case results' if @env_db == 'mssql'
|
655
|
+
|
656
|
+
assert_equal 'Camille concat', t(@camille, @name.coalesce_blank(Arel.null, 'default') + ' concat')
|
657
|
+
assert_equal 'Myung', t(@myung, @comments.coalesce_blank(Arel.null, 'Myung'))
|
658
|
+
assert_equal 'Camille', t(@camille, @name.coalesce_blank(Arel.null, 'default'))
|
386
659
|
end
|
387
660
|
|
388
661
|
# Comparators
|
@@ -397,22 +670,31 @@ module ArelExtensions
|
|
397
670
|
def test_date_comparator
|
398
671
|
d = Date.new(2016, 5, 23)
|
399
672
|
assert_equal 0, User.where(@created_at < d).count
|
400
|
-
assert_equal
|
673
|
+
assert_equal 10, User.where(@created_at >= d).count
|
401
674
|
end
|
402
675
|
|
403
676
|
def test_date_duration
|
677
|
+
# When user `nilly` is created, with an explicit `created_at: nil`,
|
678
|
+
# activerecord will give it the current date.
|
679
|
+
#
|
680
|
+
# So depending on the month when we run this test, we will get different
|
681
|
+
# results for `User.where(@created_at.month.eq('05'))`.
|
682
|
+
count_for_may = Date.today.month == 5 ? 10 : 9
|
683
|
+
count_for_day = Date.today.day == 5 ? 1 : 0
|
684
|
+
|
404
685
|
# Year
|
405
686
|
assert_equal 2016, t(@lucas, @created_at.year).to_i
|
406
|
-
assert_equal 0, User.where(@created_at.year.eq(
|
687
|
+
assert_equal 0, User.where(@created_at.year.eq('2012')).count
|
407
688
|
# Month
|
408
689
|
assert_equal 5, t(@camille, @created_at.month).to_i
|
409
|
-
assert_equal
|
690
|
+
assert_equal count_for_may, User.where(@created_at.month.eq('05')).count
|
410
691
|
# Week
|
411
692
|
assert_equal(@env_db == 'mssql' ? 22 : 21, t(@arthur, @created_at.week).to_i)
|
412
|
-
assert_equal
|
693
|
+
assert_equal count_for_may, User.where(@created_at.month.eq('05')).count
|
413
694
|
# Day
|
414
695
|
assert_equal 23, t(@laure, @created_at.day).to_i
|
415
|
-
|
696
|
+
# Make sure we get the correct count on the date we run the test.
|
697
|
+
assert_equal count_for_day, User.where(@created_at.day.eq('05')).count
|
416
698
|
|
417
699
|
# skip "manage DATE" if @env_db == 'oracle'
|
418
700
|
# Hour
|
@@ -429,8 +711,8 @@ module ArelExtensions
|
|
429
711
|
def test_datetime_diff
|
430
712
|
assert_equal 0, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 42)).to_i
|
431
713
|
if @env_db == 'oracle' && Arel::VERSION.to_i > 6 # in rails 5, result is multiplied by 24*60*60 = 86400...
|
432
|
-
assert_equal 42 *
|
433
|
-
assert_equal(-3600 *
|
714
|
+
assert_equal 42 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
|
715
|
+
assert_equal(-3600 * 86_400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
|
434
716
|
else
|
435
717
|
assert_equal 42, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
|
436
718
|
assert_equal(-3600, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
|
@@ -442,7 +724,7 @@ module ArelExtensions
|
|
442
724
|
end
|
443
725
|
|
444
726
|
|
445
|
-
skip
|
727
|
+
skip 'not yet implemented' if $sqlite
|
446
728
|
|
447
729
|
date1 = Date.new(2016, 5, 23)
|
448
730
|
durPos = 10.years
|
@@ -455,27 +737,29 @@ module ArelExtensions
|
|
455
737
|
datetime1 = Time.utc(2014, 3, 3, 12, 42, 0)
|
456
738
|
# Pull Request #5 tests
|
457
739
|
# puts (@created_at + durPos).cast(:date).to_sql
|
458
|
-
assert_includes [date2,
|
459
|
-
assert_includes [date3,
|
740
|
+
assert_includes [date2, '2026-05-23'], t(@test, (@created_at + durPos).cast(:date))
|
741
|
+
assert_includes [date3, '2006-05-23'], t(@test, (@created_at + durNeg).cast(:date))
|
460
742
|
|
461
743
|
# puts (@created_at + @created_at.day).cast(:date).to_sql
|
462
|
-
assert_includes [date4,
|
744
|
+
assert_includes [date4, '2016-06-15'], t(@test, (@created_at + @created_at.day).cast(:date))
|
463
745
|
# puts (@created_at - @created_at.day).cast(:date).to_sql
|
464
|
-
assert_includes [date5,
|
746
|
+
assert_includes [date5, '2016-04-30'], t(@test, (@created_at - @created_at.day).cast(:date))
|
465
747
|
|
466
|
-
assert_includes [datetime1 + 42.seconds,
|
467
|
-
assert_includes [datetime1 - 42.seconds,
|
748
|
+
assert_includes [datetime1 + 42.seconds, '2014-03-03 12:42:42 UTC'], t(@lucas, (@updated_at + @updated_at.minute))
|
749
|
+
assert_includes [datetime1 - 42.seconds, '2014-03-03 12:41:18 UTC'], t(@lucas, (@updated_at - @updated_at.minute))
|
468
750
|
|
469
751
|
# (@updated_at + Arel.duration('s',(@updated_at.hour*60 + @updated_at.minute))).to_sql
|
470
|
-
assert_includes [datetime1 + (12*60+42).seconds,
|
471
|
-
t(@lucas,(@updated_at + Arel.duration('s',(@updated_at.hour*60 + @updated_at.minute))))
|
752
|
+
assert_includes [datetime1 + (12 * 60 + 42).seconds, '2014-03-03 12:54:42 UTC'],
|
753
|
+
t(@lucas, (@updated_at + Arel.duration('s', (@updated_at.hour * 60 + @updated_at.minute))))
|
472
754
|
|
473
|
-
assert_includes [datetime1 + (12*60+42).minutes,
|
474
|
-
t(@lucas,(@updated_at + Arel.duration('mn',(@updated_at.hour*60 + @updated_at.minute))))
|
755
|
+
assert_includes [datetime1 + (12 * 60 + 42).minutes, '2014-03-04 01:24:00 UTC'],
|
756
|
+
t(@lucas, (@updated_at + Arel.duration('mn', (@updated_at.hour * 60 + @updated_at.minute))))
|
475
757
|
|
476
|
-
assert_includes [
|
758
|
+
assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format('%Y-%m-%d'))
|
759
|
+
assert_includes ['2024-03-03'], t(@lucas, (@updated_at + durPos).format_date('%Y-%m-%d'))
|
477
760
|
# puts (@updated_at - durPos).to_sql
|
478
|
-
assert_includes [
|
761
|
+
assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format('%Y-%m-%d'))
|
762
|
+
assert_includes ['2004-03-03'], t(@lucas, (@updated_at - durPos).format_date('%Y-%m-%d'))
|
479
763
|
|
480
764
|
|
481
765
|
# we test with the ruby object or the string because some adapters don't return an object Date
|
@@ -484,28 +768,53 @@ module ArelExtensions
|
|
484
768
|
|
485
769
|
# TODO; cast types
|
486
770
|
def test_cast_types
|
487
|
-
assert_equal
|
488
|
-
skip
|
771
|
+
assert_equal '5', t(@lucas, @age.cast(:string))
|
772
|
+
skip 'jdbc adapters does not work properly here (v52 works fine)' if RUBY_PLATFORM.match?(/java/i)
|
489
773
|
if @env_db == 'mysql' || @env_db == 'postgresql' || @env_db == 'oracle' || @env_db == 'mssql'
|
490
|
-
assert_equal 1, t(@laure,Arel.when(@duration.cast(:time).cast(:string).eq(
|
491
|
-
assert_equal 1, t(@laure,Arel.when(@duration.cast(:time).eq(
|
492
|
-
assert_equal
|
493
|
-
assert_equal
|
494
|
-
assert_equal 21.16, t(@laure
|
495
|
-
assert_equal 21, t(@laure
|
496
|
-
|
497
|
-
assert_equal String, t(@lucas
|
498
|
-
|
499
|
-
assert_equal Date, t(@lucas
|
500
|
-
assert_equal Time, t(@lucas
|
501
|
-
assert_equal Time, t(@lucas
|
502
|
-
|
503
|
-
|
504
|
-
assert_equal
|
505
|
-
assert_equal Date.parse(
|
506
|
-
assert_equal
|
507
|
-
assert_equal
|
508
|
-
assert_equal
|
774
|
+
assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).cast(:string).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle' || @env_db == 'mssql'
|
775
|
+
assert_equal 1, t(@laure, Arel.when(@duration.cast(:time).eq('12:42:21')).then(1).else(0)) unless @env_db == 'oracle'
|
776
|
+
assert_equal '20.16', t(@laure, @score.cast(:string)).gsub(/0*\z/, '')
|
777
|
+
assert_equal '20.161', t(@laure, @score.cast(:string) + 1).gsub(/0*1\z/, '1')
|
778
|
+
assert_equal 21.16, t(@laure, @score.cast(:string).cast(:decimal) + 1)
|
779
|
+
assert_equal 21, t(@laure, @score.cast(:string).cast(:int) + 1)
|
780
|
+
|
781
|
+
assert_equal String, t(@lucas, @updated_at.cast(:string)).class
|
782
|
+
|
783
|
+
assert_equal Date, t(@lucas, @updated_at.cast(:date)).class unless @env_db == 'oracle' # DateTime
|
784
|
+
assert_equal Time, t(@lucas, @updated_at.cast(:string).cast(:datetime)).class
|
785
|
+
assert_equal Time, t(@lucas, @updated_at.cast(:time)).class
|
786
|
+
|
787
|
+
# mysql adapter in rails7 adds some infos we just squeeze here
|
788
|
+
assert_equal '2014-03-03 12:42:00', t(@lucas, @updated_at.cast(:string)).split('.').first unless @env_db == 'mssql' # locale dependent
|
789
|
+
assert_equal Date.parse('2014-03-03'), t(@lucas, Arel.quoted('2014-03-03').cast(:date))
|
790
|
+
assert_equal Date.parse('5014-03-03'), t(@lucas, (@age.cast(:string) + '014-03-03').cast(:date))
|
791
|
+
assert_equal Time.parse('2014-03-03 12:42:00 UTC'), t(@lucas, @updated_at.cast(:string).cast(:datetime))
|
792
|
+
assert_equal Date.parse('2014-03-03'), t(@lucas, @updated_at.cast(:date))
|
793
|
+
assert_equal '12:42:00', t(@lucas, @updated_at.cast(:time).cast(:string)).split('.').first unless @env_db == 'oracle' # DateTime
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
797
|
+
def test_if_present
|
798
|
+
assert_nil t(@myung, @comments.if_present)
|
799
|
+
assert_equal 0, t(@myung, @comments.if_present.count)
|
800
|
+
assert_equal 20.16, t(@myung, @score.if_present)
|
801
|
+
assert_equal '2016-05-23', t(@myung, @created_at.if_present.format('%Y-%m-%d'))
|
802
|
+
assert_equal '2016-05-23', t(@myung, @created_at.if_present.format_date('%Y-%m-%d'))
|
803
|
+
assert_nil t(@laure, @comments.if_present)
|
804
|
+
|
805
|
+
assert_nil t(@nilly, @duration.if_present.format('%Y-%m-%d'))
|
806
|
+
assert_nil t(@nilly, @duration.if_present.format_date('%Y-%m-%d'))
|
807
|
+
|
808
|
+
# NOTE: here we're testing the capacity to format a nil value,
|
809
|
+
# however, @comments is a text field, and not a date/datetime field,
|
810
|
+
# so Postgres will rightfully complain when we format the text:
|
811
|
+
# we need to cast it first.
|
812
|
+
if @env_db == 'postgresql'
|
813
|
+
assert_nil t(@laure, @comments.cast(:date).if_present.format('%Y-%m-%d'))
|
814
|
+
assert_nil t(@laure, @comments.cast(:date).if_present.format_date('%Y-%m-%d'))
|
815
|
+
else
|
816
|
+
assert_nil t(@laure, @comments.if_present.format('%Y-%m-%d'))
|
817
|
+
assert_nil t(@laure, @comments.if_present.format_date('%Y-%m-%d'))
|
509
818
|
end
|
510
819
|
end
|
511
820
|
|
@@ -515,42 +824,42 @@ module ArelExtensions
|
|
515
824
|
# puts @age.is_null.inspect
|
516
825
|
# puts @age.is_null.to_sql
|
517
826
|
# puts @age=='34'
|
518
|
-
assert_equal
|
827
|
+
assert_equal 'Test', User.select(@name).where(@age.is_null).first.name
|
519
828
|
end
|
520
829
|
|
521
830
|
def test_math_plus
|
522
831
|
d = Date.new(1997, 6, 15)
|
523
832
|
# Concat String
|
524
|
-
assert_equal
|
525
|
-
assert_equal
|
526
|
-
assert_equal
|
527
|
-
assert_equal
|
528
|
-
assert_equal
|
529
|
-
assert_equal
|
530
|
-
assert_equal
|
531
|
-
assert_equal
|
833
|
+
assert_equal 'SophiePhan', t(@sophie, @name + 'Phan')
|
834
|
+
assert_equal 'Sophie2', t(@sophie, @name + 2)
|
835
|
+
assert_equal 'Sophie1997-06-15', t(@sophie, @name + d)
|
836
|
+
assert_equal 'Sophie15', t(@sophie, @name + @age)
|
837
|
+
assert_equal 'SophieSophie', t(@sophie, @name + @name)
|
838
|
+
assert_equal 'SophieSophieSophie', t(@sophie, @name + @name + @name)
|
839
|
+
assert_equal 'SophieSophieSophie', t(@sophie, @name.concat(@name.concat(@name)))
|
840
|
+
assert_equal 'SophieSophieSophie', t(@sophie, @name.concat(@name).concat(@name))
|
532
841
|
# FIXME: should work as expected in Oracle
|
533
|
-
assert_equal
|
842
|
+
assert_equal 'Sophie2016-05-23', t(@sophie, @name + @created_at) unless @env_db == 'oracle'
|
534
843
|
# concat Integer
|
535
844
|
assert_equal 1, User.where((@age + 10).eq(33)).count
|
536
|
-
assert_equal 1, User.where((@age +
|
845
|
+
assert_equal 1, User.where((@age + '1').eq(6)).count
|
537
846
|
assert_equal 1, User.where((@age + @age).eq(10)).count
|
538
847
|
# concat Date
|
539
848
|
# puts((User.arel_table[:created_at] + 1).as("res").to_sql.inspect)
|
540
|
-
assert_equal
|
541
|
-
assert_equal
|
849
|
+
assert_equal '2016-05-24', t(@myung, @created_at + 1).to_date.to_s
|
850
|
+
assert_equal '2016-05-25', t(@myung, @created_at + 2.day).to_date.to_s
|
542
851
|
end
|
543
852
|
|
544
853
|
def test_math_minus
|
545
854
|
d = Date.new(2016, 5, 20)
|
546
855
|
# Datediff
|
547
|
-
assert_equal
|
548
|
-
assert_equal 3, @laure.select((@created_at - d).as(
|
856
|
+
assert_equal 10, User.where((@created_at - @created_at).eq(0)).count
|
857
|
+
assert_equal 3, @laure.select((@created_at - d).as('res')).first.res.abs.to_i
|
549
858
|
# Substraction
|
550
859
|
assert_equal 0, User.where((@age - 10).eq(50)).count
|
551
|
-
assert_equal 0, User.where((@age -
|
860
|
+
assert_equal 0, User.where((@age - '10').eq(50)).count
|
552
861
|
# assert_equal 0, User.where((@age - 9.5).eq(50.5)).count # should work: TODO
|
553
|
-
assert_equal 0, User.where((@age -
|
862
|
+
assert_equal 0, User.where((@age - '9.5').eq(50.5)).count
|
554
863
|
end
|
555
864
|
|
556
865
|
def test_wday
|
@@ -573,8 +882,8 @@ module ArelExtensions
|
|
573
882
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(23)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
|
574
883
|
assert_equal 2, User.select('*').from((@ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(20)) + @ut.project(@age).where(@age.eq(21))).as('my_union')).length
|
575
884
|
|
576
|
-
assert_equal 3, User.find_by_sql(
|
577
|
-
assert_equal 3, User.find_by_sql(
|
885
|
+
assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0))).to_sql).length
|
886
|
+
assert_equal 3, User.find_by_sql(@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21))).to_sql).length
|
578
887
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.gt(22)).union_all(@ut.project(@age).where(@age.lt(0)))).as('my_union')).length
|
579
888
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(23))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
|
580
889
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
|
@@ -586,116 +895,117 @@ module ArelExtensions
|
|
586
895
|
def test_case
|
587
896
|
assert_equal 4, User.find_by_sql(@ut.project(@score.when(20.16).then(1).else(0).as('score_bin')).to_sql).sum(&:score_bin)
|
588
897
|
assert_equal 4, User.where(@score.when(20.16).then(1).else(0).eq(1)).count
|
589
|
-
assert_equal 2, t(@arthur, @score.when(65.62,1).else(0)+1)
|
590
|
-
assert_equal 0, t(@arthur, @score.when(65.62,1).else(0)-1)
|
591
|
-
assert_equal
|
592
|
-
assert_equal 66.62, t(@arthur, @score.when(65.62).then(@score).else(@score)+1)
|
593
|
-
assert_equal
|
898
|
+
assert_equal 2, t(@arthur, @score.when(65.62, 1).else(0) + 1)
|
899
|
+
assert_equal 0, t(@arthur, @score.when(65.62, 1).else(0) - 1)
|
900
|
+
assert_equal '11', t(@arthur, @score.when(65.62).then('1').else('0') + '1')
|
901
|
+
assert_equal 66.62, t(@arthur, @score.when(65.62).then(@score).else(@score) + 1)
|
902
|
+
assert_equal '65.621', t(@arthur, @score.when(65.62).then(@score.cast(:string)).else(@score.cast(:string)) + 1).tr('0', '') # tr is here because of precision on cast for some DBMS
|
594
903
|
end
|
595
904
|
|
596
905
|
def test_format_numbers
|
597
906
|
# score of Arthur = 65.62
|
598
|
-
skip
|
599
|
-
|
600
|
-
assert_equal
|
601
|
-
assert_equal
|
602
|
-
assert_equal
|
603
|
-
assert_equal
|
604
|
-
assert_equal
|
605
|
-
assert_equal
|
606
|
-
assert_equal
|
607
|
-
assert_equal
|
608
|
-
assert_equal
|
609
|
-
assert_equal
|
610
|
-
assert_equal
|
611
|
-
assert_equal
|
612
|
-
assert_includes [
|
613
|
-
assert_includes [
|
614
|
-
assert_includes [
|
615
|
-
assert_equal
|
616
|
-
assert_equal
|
617
|
-
assert_equal
|
618
|
-
assert_equal
|
619
|
-
assert_equal
|
620
|
-
assert_equal
|
907
|
+
skip ' Works with SQLite if the version used knows printf' if $sqlite
|
908
|
+
|
909
|
+
assert_equal 'Wrong Format', t(@arthur, @score.format_number('$ %...234.6F €', 'fr_FR'))
|
910
|
+
assert_equal 'AZERTY65,62', t(@arthur, @score.format_number('AZERTY%.2f', 'fr_FR'))
|
911
|
+
assert_equal '65,62AZERTY', t(@arthur, @score.format_number('%.2fAZERTY', 'fr_FR'))
|
912
|
+
assert_equal '$ 65.62 €', t(@arthur, @score.format_number('$ %.2f €', 'en_US'))
|
913
|
+
assert_equal '$ 66 €', t(@arthur, @score.format_number('$ %.0f €', 'en_US'))
|
914
|
+
assert_equal '$ 0065,62 €', t(@arthur, @score.format_number('$ %07.2f €', 'fr_FR'))
|
915
|
+
assert_equal '$ 65,62 €', t(@arthur, @score.format_number('$ %-07.2f €', 'fr_FR'))
|
916
|
+
assert_equal '$ 65,62 €', t(@arthur, @score.format_number('$ %-7.2f €', 'fr_FR'))
|
917
|
+
assert_equal '$ 65,62 €', t(@arthur, @score.format_number('$ % 7.2f €', 'fr_FR'))
|
918
|
+
assert_equal '$ 65,6 €', t(@arthur, @score.format_number('$ % 7.1f €', 'fr_FR'))
|
919
|
+
assert_equal '$ +65,62 €', t(@arthur, @score.format_number('$ % +7.2f €', 'fr_FR'))
|
920
|
+
assert_equal '$ +065,62 €', t(@arthur, @score.format_number('$ %0+7.2f €', 'fr_FR'))
|
921
|
+
assert_includes ['$ 6,56e1 €', '$ 6,56e+01 €'], t(@arthur, @score.format_number('$ %.2e €', 'fr_FR'))
|
922
|
+
assert_includes ['$ 6,56E1 €', '$ 6,56E+01 €'], t(@arthur, @score.format_number('$ %.2E €', 'fr_FR'))
|
923
|
+
assert_includes ['$ 6,562E1 €', '$ 6,562E+01 €'], t(@arthur, @score.format_number('$ %.3E €', 'fr_FR'))
|
924
|
+
assert_equal '123 456 765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'sv_SE')).tr("\u00A0", ' ') # some DBMS put no-break space here (it makes sense thus)
|
925
|
+
assert_equal '123456765,6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'fr_FR')).delete("\u00A0") # because SqlServer does it like no one else
|
926
|
+
assert_equal '123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%.1f', 'en_US'))
|
927
|
+
assert_equal ' 123,456,765.6', t(@arthur, (@score + 123_456_700).format_number('%16.1f', 'en_US'))
|
928
|
+
assert_equal '$ 0,00 €', t(@arthur, @score.when(65.62).then(Arel.sql('null')).else(1).format_number('$ %.2f €', 'fr_FR'))
|
929
|
+
assert_equal '$ 0,00 €', t(@arthur, (@score - 65.62).format_number('$ %.2f €', 'fr_FR'))
|
621
930
|
end
|
622
931
|
|
623
932
|
def test_accent_insensitive
|
624
|
-
skip
|
625
|
-
skip
|
933
|
+
skip 'SQLite is natively Case Insensitive and Accent Sensitive' if $sqlite
|
934
|
+
skip 'Not finished' if @env_db == 'mysql'
|
626
935
|
# actual comments value: "arrêté"
|
627
936
|
# AI & CI
|
628
937
|
if !['postgresql'].include?(@env_db) # Extension unaccent required on PG
|
629
|
-
assert_equal
|
630
|
-
assert_equal
|
631
|
-
assert_equal
|
632
|
-
assert_equal
|
633
|
-
assert_equal
|
634
|
-
assert_equal
|
938
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_imatches('arrêté')).then('1').else('0'))
|
939
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_imatches('arrete')).then('1').else('0'))
|
940
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_imatches('àrrétè')).then('1').else('0'))
|
941
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.ai_imatches('arretez')).then('1').else('0'))
|
942
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_imatches('Arrete')).then('1').else('0'))
|
943
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_imatches('Arrêté')).then('1').else('0'))
|
635
944
|
# AI & CS
|
636
|
-
assert_equal
|
637
|
-
assert_equal
|
638
|
-
assert_equal
|
639
|
-
assert_equal
|
640
|
-
if
|
641
|
-
assert_equal
|
642
|
-
assert_equal
|
945
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('arrêté')).then('1').else('0'))
|
946
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('arrete')).then('1').else('0'))
|
947
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.ai_matches('àrrétè')).then('1').else('0'))
|
948
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('arretez')).then('1').else('0'))
|
949
|
+
if !%w[oracle postgresql mysql].include?(@env_db) # AI => CI
|
950
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrete')).then('1').else('0'))
|
951
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.ai_matches('Arrêté')).then('1').else('0'))
|
643
952
|
end
|
644
953
|
end
|
645
954
|
# AS & CI
|
646
|
-
assert_equal
|
955
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.imatches('arrêté')).then('1').else('0'))
|
647
956
|
if !['mysql'].include?(@env_db) # CI => AI in utf8 (AI not possible in latin1)
|
648
|
-
assert_equal
|
649
|
-
assert_equal
|
957
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.imatches('arrete')).then('1').else('0'))
|
958
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.imatches('àrrétè')).then('1').else('0'))
|
650
959
|
end
|
651
|
-
assert_equal
|
960
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.imatches('arretez')).then('1').else('0'))
|
652
961
|
if !['mysql'].include?(@env_db) # CI => AI in utf8 (AI not possible in latin1)
|
653
|
-
assert_equal
|
962
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.imatches('Arrete')).then('1').else('0'))
|
654
963
|
end
|
655
|
-
assert_equal
|
964
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.imatches('Arrêté')).then('1').else('0'))
|
656
965
|
# AS & CS
|
657
|
-
assert_equal
|
658
|
-
assert_equal
|
659
|
-
assert_equal
|
660
|
-
assert_equal
|
661
|
-
assert_equal
|
662
|
-
assert_equal
|
966
|
+
assert_equal '1', t(@arthur, Arel.when(@comments.smatches('arrêté')).then('1').else('0'))
|
967
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.smatches('arrete')).then('1').else('0'))
|
968
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.smatches('àrrétè')).then('1').else('0'))
|
969
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.smatches('arretez')).then('1').else('0'))
|
970
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.smatches('Arrete')).then('1').else('0'))
|
971
|
+
assert_equal '0', t(@arthur, Arel.when(@comments.smatches('Arrêté')).then('1').else('0'))
|
663
972
|
end
|
664
973
|
|
665
974
|
def test_subquery_with_order
|
666
|
-
|
667
|
-
assert_equal
|
668
|
-
|
669
|
-
|
670
|
-
|
975
|
+
skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
|
976
|
+
assert_equal 10, User.where(name: User.select(:name).order(:name)).count
|
977
|
+
assert_equal 10, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
|
978
|
+
if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
|
979
|
+
assert_equal 2, User.where(name: User.select(:name).order(:name).limit(2)).count
|
980
|
+
# assert_equal 6, User.where(name: User.select(:name).order(:name).offset(2)).count
|
671
981
|
end
|
672
982
|
end
|
673
983
|
|
674
984
|
def test_in_with_nil
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
985
|
+
assert_predicate @myung.where(@age.in(1)), :blank?
|
986
|
+
assert_predicate @myung.where(@age.in(23)), :present?
|
987
|
+
assert_predicate @myung.where(@age.in([1])), :blank?
|
988
|
+
assert_predicate @myung.where(@age.in([1, 2])), :blank?
|
989
|
+
assert_predicate @myung.where(@age.in([1, 23])), :present?
|
990
|
+
assert_predicate @myung.where(@age.in(nil)), :blank?
|
991
|
+
assert_predicate @myung.where(@age.in([nil])), :blank?
|
992
|
+
assert_predicate @myung.where(@age.in([nil, 1])), :blank?
|
993
|
+
assert_predicate @myung.where(@age.in([nil, 23])), :present?
|
994
|
+
assert_predicate @myung.where(@age.in([nil, 1, 2])), :blank?
|
995
|
+
assert_predicate @myung.where(@age.in([nil, 1, 23])), :present?
|
996
|
+
assert_predicate @test.where(@age.in(1)), :blank?
|
997
|
+
assert_predicate @test.where(@age.in([1])), :blank?
|
998
|
+
assert_predicate @test.where(@age.in([1, 2])), :blank?
|
999
|
+
assert_predicate @test.where(@age.in(nil)), :present?
|
1000
|
+
assert_predicate @test.where(@age.in([nil])), :present?
|
1001
|
+
assert_predicate @test.where(@age.in([nil, 1])), :present?
|
1002
|
+
assert_predicate @test.where(@age.in([nil, 1, 2])), :present?
|
693
1003
|
end
|
694
1004
|
|
695
1005
|
def test_scope_with_in_plus_new
|
696
1006
|
begin
|
697
|
-
@test.where(@age.in([1,2])).new
|
698
|
-
@test.where(@age.not_in([1,2])).new
|
1007
|
+
@test.where(@age.in([1, 2])).new
|
1008
|
+
@test.where(@age.not_in([1, 2])).new
|
699
1009
|
assert true
|
700
1010
|
rescue
|
701
1011
|
assert false
|
@@ -703,44 +1013,44 @@ module ArelExtensions
|
|
703
1013
|
end
|
704
1014
|
|
705
1015
|
def test_is_not_null
|
706
|
-
|
707
|
-
|
1016
|
+
assert_predicate @myung.where(@age.is_not_null), :present?
|
1017
|
+
assert_predicate @test.where(@age.is_not_null), :blank?
|
708
1018
|
end
|
709
1019
|
|
710
1020
|
def test_not_in_with_nil
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
1021
|
+
assert_predicate @myung.where(@age.not_in(1)), :present?
|
1022
|
+
assert_predicate @myung.where(@age.not_in(23)), :blank?
|
1023
|
+
assert_predicate @myung.where(@age.not_in([1])), :present?
|
1024
|
+
assert_predicate @myung.where(@age.not_in([1, 2])), :present?
|
1025
|
+
assert_predicate @myung.where(@age.not_in([1, 23])), :blank?
|
1026
|
+
assert_predicate @myung.where(@age.not_in(nil)), :present?
|
1027
|
+
assert_predicate @myung.where(@age.not_in([nil])), :present?
|
1028
|
+
assert_predicate @myung.where(@age.not_in([nil, 1])), :present?
|
1029
|
+
assert_predicate @myung.where(@age.not_in([nil, 23])), :blank?
|
1030
|
+
assert_predicate @myung.where(@age.not_in([nil, 1, 2])), :present?
|
1031
|
+
assert_predicate @myung.where(@age.not_in([nil, 1, 23])), :blank?
|
1032
|
+
|
1033
|
+
assert_predicate @myung.where(@age.not_in(1..2)), :present?
|
724
1034
|
|
725
1035
|
# if the column is null, the entry will never be selected with not in (like every DBMS does)
|
726
|
-
#
|
727
|
-
#
|
728
|
-
#
|
729
|
-
#
|
730
|
-
#
|
731
|
-
#
|
732
|
-
#
|
1036
|
+
# assert_predicate @test.where(@age.not_in(1)), :present?
|
1037
|
+
# assert_predicate @test.where(@age.not_in([1])), :present?
|
1038
|
+
# assert_predicate @test.where(@age.not_in([1,2])), :present?
|
1039
|
+
# assert_predicate @test.where(@age.not_in(nil)), :blank?
|
1040
|
+
# assert_predicate @test.where(@age.not_in([nil])), :blank?
|
1041
|
+
# assert_predicate @test.where(@age.not_in([nil,1])), :blank?
|
1042
|
+
# assert_predicate @test.where(@age.not_in([nil,1,2])), :blank?
|
733
1043
|
end
|
734
1044
|
|
735
1045
|
def test_in_on_grouping
|
736
|
-
skip
|
737
|
-
assert_equal 2, User.where(Arel.tuple(@name
|
738
|
-
assert_equal 1, User.where(Arel.tuple(@name
|
739
|
-
assert_equal 0, User.where(Arel.tuple(@name
|
1046
|
+
skip 'We should modify the visitor of IN to make it work' if $sqlite || @env_db == 'mssql'
|
1047
|
+
assert_equal 2, User.where(Arel.tuple(@name, @age).in(Arel.tuple('Myung', 23), Arel.tuple('Arthur', 21))).count
|
1048
|
+
assert_equal 1, User.where(Arel.tuple(@name, @age).in(Arel.tuple('Myung', 23))).count
|
1049
|
+
assert_equal 0, User.where(Arel.tuple(@name, @age).in([])).count
|
740
1050
|
end
|
741
1051
|
|
742
1052
|
def test_alias_shortened
|
743
|
-
if [
|
1053
|
+
if %w[postgresql oracle].include?(@env_db)
|
744
1054
|
new_alias = Arel.shorten('azerty' * 15)
|
745
1055
|
at = User.arel_table.alias('azerty' * 15)
|
746
1056
|
assert_equal "\"user_tests\" \"#{new_alias}\"".downcase, User.arel_table.alias('azerty' * 15).to_sql.downcase
|
@@ -763,64 +1073,64 @@ module ArelExtensions
|
|
763
1073
|
assert (479.82048 - t(User.where(nil), @score.variance(unbiased: false))).abs < 0.01
|
764
1074
|
assert ( 23.23355 - t(User.where(nil), @score.std)).abs < 0.01
|
765
1075
|
assert ( 21.90480 - t(User.where(nil), @score.std(unbiased: false))).abs < 0.01
|
766
|
-
skip
|
767
|
-
assert_equal 2, User.select(@score.std(group: Arel.when(@name >
|
768
|
-
assert_equal 2, User.select(@score.variance(group: Arel.when(@name >
|
769
|
-
assert_equal 2, User.select(@score.sum(group: Arel.when(@name >
|
770
|
-
assert_equal 2, User.select(@comments.group_concat(group: Arel.when(@name >
|
1076
|
+
skip 'Not Yet Implemented' # if !['postgresql'].include?(@env_db)
|
1077
|
+
assert_equal 2, User.select(@score.std(group: Arel.when(@name > 'M').then(0).else(1)).as('res')).map{|e| e['res']}.uniq.length
|
1078
|
+
assert_equal 2, User.select(@score.variance(group: Arel.when(@name > 'M').then(0).else(1)).as('res')).map{|e| e['res']}.uniq.length
|
1079
|
+
assert_equal 2, User.select(@score.sum(group: Arel.when(@name > 'M').then(0).else(1)).as('res')).map{|e| e['res']}.uniq.length
|
1080
|
+
assert_equal 2, User.select(@comments.group_concat(group: Arel.when(@name > 'M').then(0).else(1)).as('res')).map{|e| e['res']}.uniq.length
|
771
1081
|
end
|
772
1082
|
|
773
1083
|
def test_levenshtein_distance
|
774
|
-
skip
|
775
|
-
assert_equal 0, t(@arthur
|
776
|
-
assert_equal 2, t(@arthur
|
777
|
-
assert_equal 1, t(@arthur
|
1084
|
+
skip 'Not Yet Implemented' if $sqlite
|
1085
|
+
assert_equal 0, t(@arthur, @name.levenshtein_distance('Arthur'))
|
1086
|
+
assert_equal 2, t(@arthur, @name.levenshtein_distance('Artoor'))
|
1087
|
+
assert_equal 1, t(@arthur, @name.levenshtein_distance('Artehur'))
|
778
1088
|
end
|
779
1089
|
|
780
1090
|
def test_json
|
781
1091
|
skip "Can't be tested on travis"
|
782
1092
|
# creation
|
783
|
-
assert_equal 'Arthur', t(@arthur,Arel.json(@name))
|
784
|
-
assert_equal [
|
785
|
-
assert_equal ({
|
786
|
-
assert_equal ({
|
787
|
-
assert_equal
|
1093
|
+
assert_equal 'Arthur', t(@arthur, Arel.json(@name))
|
1094
|
+
assert_equal %w[Arthur Arthur], parse_json(t(@arthur, Arel.json(@name, @name)))
|
1095
|
+
assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 'ArthurArthur'}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => @name + @name})))
|
1096
|
+
assert_equal ({'Arthur' => 'Arthur', 'Arthur2' => 1}), parse_json(t(@arthur, Arel.json({@name => @name, @name + '2' => 1})))
|
1097
|
+
assert_equal [{'age' => 21}, {'name' => 'Arthur', 'score' => 65.62}], parse_json(t(@arthur, Arel.json([{age: @age}, {name: @name, score: @score}])))
|
788
1098
|
|
789
1099
|
# aggregate
|
790
|
-
assert_equal ({
|
791
|
-
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16),Arel.json({@age => @name}).group(false)))
|
792
|
-
assert_equal ({
|
793
|
-
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16),Arel.json({@age => @name
|
794
|
-
assert_equal
|
795
|
-
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score),Arel.json({@age => @name}).group(true,[@age])))
|
1100
|
+
assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure'}),
|
1101
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name}).group(false)))
|
1102
|
+
assert_equal ({'5' => 'Lucas', '15' => 'Sophie', '23' => 'Myung', '25' => 'Laure', 'Laure' => 25, 'Lucas' => 5, 'Myung' => 23, 'Sophie' => 15}),
|
1103
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16), Arel.json({@age => @name, @name => @age}).group(false)))
|
1104
|
+
assert_equal [{'5' => 'Lucas'}, {'15' => 'Sophie'}, {'23' => 'Myung'}, {'25' => 'Laure'}],
|
1105
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score), Arel.json({@age => @name}).group(true, [@age])))
|
796
1106
|
|
797
|
-
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score,Arel.json({@age => @name}).group(true,[@age])).to_sql
|
798
|
-
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score,Arel.json({@age => @name}).group(true,[@age])).to_a
|
1107
|
+
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_sql
|
1108
|
+
# puts User.group(:score).where(@age.is_not_null).where(@score == 20.16).select(@score, Arel.json({@age => @name}).group(true,[@age])).to_a
|
799
1109
|
|
800
|
-
skip
|
1110
|
+
skip 'Not Yet Implemented' if $sqlite || %w[oracle mssql].include?(@env_db)
|
801
1111
|
# get
|
802
|
-
h1 = Arel.json({@name => @name
|
803
|
-
assert_equal
|
804
|
-
h2 = Arel.json([{age: @age},{name: @name,score: @score}])
|
805
|
-
assert_equal ({
|
806
|
-
assert_equal 21, parse_json(t(@arthur,h2.get(0).get('age')))
|
807
|
-
assert_nil t(@arthur,h2.get('age'))
|
1112
|
+
h1 = Arel.json({@name => @name + @name, @name + '2' => 1})
|
1113
|
+
assert_equal 'ArthurArthur', parse_json(t(@arthur, h1.get(@name)))
|
1114
|
+
h2 = Arel.json([{age: @age}, {name: @name, score: @score}])
|
1115
|
+
assert_equal ({'age' => 21}), parse_json(t(@arthur, h2.get(0)))
|
1116
|
+
assert_equal 21, parse_json(t(@arthur, h2.get(0).get('age')))
|
1117
|
+
assert_nil t(@arthur, h2.get('age'))
|
808
1118
|
# set
|
809
|
-
assert_equal ({
|
810
|
-
assert_equal ({
|
811
|
-
assert_equal ({
|
812
|
-
assert_equal ({
|
1119
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1}), parse_json(t(@arthur, h1.set(@name, %w[toto tata])))
|
1120
|
+
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.set(@name + '3', 2)))
|
1121
|
+
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => nil}), parse_json(t(@arthur, h1.set(@name + '3', nil)))
|
1122
|
+
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1, 'Arthur3' => {'a' => 2}}), parse_json(t(@arthur, h1.set(@name + '3', {a: 2})))
|
813
1123
|
# merge
|
814
|
-
assert_equal ({
|
815
|
-
assert_equal ({
|
816
|
-
assert_equal ({
|
1124
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata]}, {@name + '3' => 2})))
|
1125
|
+
assert_equal ({'Arthur' => %w[toto tata], 'Arthur2' => 1, 'Arthur3' => 2}), parse_json(t(@arthur, h1.merge({@name => %w[toto tata], @name + '3' => 2})))
|
1126
|
+
assert_equal ({'Arthur' => 'ArthurArthur', 'Arthur2' => 1}), parse_json(t(@arthur, h1.merge({})))
|
817
1127
|
end
|
818
1128
|
|
819
1129
|
def test_as_on_everything
|
820
1130
|
name = @arthur.select(@name.as('NaMe')).first.attributes
|
821
|
-
assert_equal 'Arthur', name[
|
822
|
-
assert_equal 'Arthur', @arthur.select(@name.as('Na Me')).first.attributes[
|
823
|
-
assert_equal 'ArthurArthur', @arthur.select((@name
|
1131
|
+
assert_equal 'Arthur', name['NaMe'] || name['name'] # because of Oracle
|
1132
|
+
assert_equal 'Arthur', @arthur.select(@name.as('Na Me')).first.attributes['Na Me']
|
1133
|
+
assert_equal 'ArthurArthur', @arthur.select((@name + @name).as('Na-Me')).first.attributes['Na-Me']
|
824
1134
|
end
|
825
1135
|
|
826
1136
|
def test_exists_in_subquery
|