arel_extensions 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +258 -52
- data/Gemfile +8 -8
- data/README.md +44 -0
- data/gemfiles/rails5_2.gemfile +3 -3
- data/gemfiles/rails6.gemfile +3 -4
- data/gemfiles/rails6_1.gemfile +1 -2
- data/gemfiles/rails7.gemfile +5 -13
- data/lib/arel_extensions/date_duration.rb +2 -2
- data/lib/arel_extensions/helpers.rb +48 -0
- data/lib/arel_extensions/math.rb +17 -27
- data/lib/arel_extensions/nodes/case.rb +3 -5
- data/lib/arel_extensions/nodes/date_diff.rb +23 -4
- data/lib/arel_extensions/nodes/format.rb +3 -2
- data/lib/arel_extensions/nodes/function.rb +1 -7
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +109 -51
- data/lib/arel_extensions/visitors/mysql.rb +6 -0
- data/lib/arel_extensions/visitors/oracle.rb +6 -1
- data/lib/arel_extensions/visitors/postgresql.rb +9 -5
- data/lib/arel_extensions/visitors/sqlite.rb +6 -3
- data/lib/arel_extensions.rb +11 -1
- data/test/arelx_test_helper.rb +45 -0
- data/test/database.yml +8 -2
- data/test/support/fake_record.rb +1 -1
- data/test/visitors/test_to_sql.rb +21 -0
- data/test/with_ar/all_agnostic_test.rb +66 -3
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +3 -3
- data/appveyor.yml +0 -44
data/test/arelx_test_helper.rb
CHANGED
@@ -6,6 +6,51 @@ require 'active_record'
|
|
6
6
|
|
7
7
|
require 'support/fake_record'
|
8
8
|
|
9
|
+
def colored(color, msg)
|
10
|
+
ENV["TERM"] =~ /^xterm|-256color$/ ? "\x1b[#{color}m#{msg}\x1b[89m\x1b[0m" : "#{msg}"
|
11
|
+
end
|
12
|
+
|
13
|
+
YELLOW = "33"
|
14
|
+
|
15
|
+
def warn(msg)
|
16
|
+
$stderr.puts(colored(YELLOW, msg))
|
17
|
+
end
|
18
|
+
|
19
|
+
# Load gems specific to databases
|
20
|
+
# NOTE:
|
21
|
+
# It's strongly advised to test each database on its own. Loading multiple
|
22
|
+
# backend gems leads to undefined behavior according to tests; the backend
|
23
|
+
# might not recognize the correct DB visitor and will fallback to `ToSQL`
|
24
|
+
# and screw all tests.
|
25
|
+
#
|
26
|
+
# The issue also seems to be related to arel version: at some point, arel
|
27
|
+
# dropped its wide support for DBs and kept Postgres, MySQL and SQLite.
|
28
|
+
# Here, we're just trying to load the correct ones.
|
29
|
+
db_and_gem = if RUBY_ENGINE == 'jruby'
|
30
|
+
{
|
31
|
+
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
32
|
+
'mssql' => 'activerecord-jdbcsqlserver-adapter'
|
33
|
+
}
|
34
|
+
else
|
35
|
+
{
|
36
|
+
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
37
|
+
'mssql' => 'activerecord-sqlserver-adapter'
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_lib(gem)
|
42
|
+
if gem && (RUBY_ENGINE == 'jruby' || Arel::VERSION.to_i > 9)
|
43
|
+
begin
|
44
|
+
Gem::Specification.find_by_name(gem)
|
45
|
+
require gem
|
46
|
+
rescue Gem::MissingSpecError
|
47
|
+
warn "Warning: failed to load gem #{gem}. Are you sure it's installed?"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
load_lib(db_and_gem[ENV['DB']])
|
53
|
+
|
9
54
|
require 'arel_extensions'
|
10
55
|
Arel::Table.engine = FakeRecord::Base.new
|
11
56
|
|
data/test/database.yml
CHANGED
@@ -9,23 +9,29 @@ jdbc-sqlite:
|
|
9
9
|
mysql:
|
10
10
|
adapter: mysql2
|
11
11
|
database: arext_test
|
12
|
-
username:
|
12
|
+
username: root
|
13
13
|
host: 127.0.0.1
|
14
14
|
port: 3306
|
15
15
|
encoding: utf8
|
16
16
|
jdbc-mysql:
|
17
17
|
adapter: jdbcmysql
|
18
18
|
database: arext_test
|
19
|
-
username:
|
19
|
+
username: root
|
20
20
|
encoding: utf8
|
21
21
|
postgresql:
|
22
22
|
adapter: postgresql
|
23
23
|
database: arext_test
|
24
24
|
username: postgres
|
25
|
+
password: secret
|
26
|
+
host: 127.0.0.1
|
27
|
+
port: 5432
|
25
28
|
jdbc-postgresql:
|
26
29
|
adapter: jdbcpostgresql
|
27
30
|
database: arext_test
|
28
31
|
username: postgres
|
32
|
+
password: secret
|
33
|
+
host: 127.0.0.1
|
34
|
+
port: 5432
|
29
35
|
oracle:
|
30
36
|
adapter: oracle_enhanced
|
31
37
|
database: xe
|
data/test/support/fake_record.rb
CHANGED
@@ -105,7 +105,7 @@ module FakeRecord
|
|
105
105
|
attr_reader :spec, :connection
|
106
106
|
|
107
107
|
def initialize
|
108
|
-
@spec = Spec.new(:adapter => 'america')
|
108
|
+
@spec = Spec.new({:adapter => 'america'})
|
109
109
|
@connection = Connection.new
|
110
110
|
@connection.visitor = Arel::Visitors::ToSql.new(connection)
|
111
111
|
end
|
@@ -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 `ArelExtenstions::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
|
@@ -33,7 +33,7 @@ module ArelExtensions
|
|
33
33
|
t.column :name, :string
|
34
34
|
t.column :comments, :text
|
35
35
|
t.column :created_at, :date
|
36
|
-
t.column :updated_at, :datetime
|
36
|
+
t.column :updated_at, :datetime, precision: nil
|
37
37
|
t.column :duration, :time
|
38
38
|
t.column :other, :string
|
39
39
|
t.column :score, :decimal, :precision => 20, :scale => 10
|
@@ -171,7 +171,7 @@ module ArelExtensions
|
|
171
171
|
# This should works no matter which version of rails is used
|
172
172
|
assert User.group(:score).average(:id).values.all?{|e| !e.nil?}
|
173
173
|
|
174
|
-
# Since Rails 7, a patch to calculations.rb has tirggered a double
|
174
|
+
# Since Rails 7, a patch to calculations.rb has tirggered a double
|
175
175
|
# quoting of the alias name. See https://github.com/rails/rails/commit/7e6e9091e55c3357b0162d44b6ab955ed0c718d5
|
176
176
|
# Before the patch that fixed this the following error would occur:
|
177
177
|
# ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: zero-length delimited identifier at or near """"
|
@@ -370,6 +370,68 @@ module ArelExtensions
|
|
370
370
|
assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
|
371
371
|
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
|
372
372
|
assert_equal '12:42%', t(@lucas, @updated_at.format('%R%%'))
|
373
|
+
|
374
|
+
# The following tests will ensure proper conversion of timestamps to
|
375
|
+
# requested timezones.
|
376
|
+
#
|
377
|
+
# The names of the timezones is highly dependant on the underlying
|
378
|
+
# operating system, and this is why we need to handle each database
|
379
|
+
# separately: the images we're using to test these databases are
|
380
|
+
# different. So don't rely on the provided examples. Your setup is your
|
381
|
+
# reference.
|
382
|
+
#
|
383
|
+
# One could always have portable code if s/he uses standard
|
384
|
+
# abbreviations, like:
|
385
|
+
#
|
386
|
+
# 1. CET => Central European Time
|
387
|
+
# 2. CEST => Central European Summer Time
|
388
|
+
#
|
389
|
+
# Which implies that the caller should handle daylight saving detection.
|
390
|
+
# In fact, CET will handle daylight saving in MySQL but not Postgres.
|
391
|
+
#
|
392
|
+
# It looks like the posix convention is supported by mysql and
|
393
|
+
# postgresql, e.g.:
|
394
|
+
#
|
395
|
+
# posix/Europe/Paris
|
396
|
+
# posix/America/Nipigon
|
397
|
+
#
|
398
|
+
# so it looks like a more reliably portable way of specifying it.
|
399
|
+
time_zones = {
|
400
|
+
'mssql' => {
|
401
|
+
'utc' => 'UTC',
|
402
|
+
'sao_paulo' => 'Argentina Standard Time',
|
403
|
+
'tahiti' => 'Hawaiian Standard Time',
|
404
|
+
'paris' => 'Central European Standard Time'
|
405
|
+
},
|
406
|
+
'mysql' => {
|
407
|
+
'utc' => 'UTC',
|
408
|
+
'sao_paulo' => 'America/Sao_Paulo',
|
409
|
+
'tahiti' => 'Pacific/Tahiti',
|
410
|
+
'paris' => 'Europe/Paris'
|
411
|
+
},
|
412
|
+
'oracle' => {
|
413
|
+
'utc' => 'UTC',
|
414
|
+
'sao_paulo' => 'America/Sao_Paulo',
|
415
|
+
'tahiti' => 'Pacific/Tahiti',
|
416
|
+
'paris' => 'Europe/Paris'
|
417
|
+
},
|
418
|
+
'postgresql' => {
|
419
|
+
'utc' => 'UTC',
|
420
|
+
'sao_paulo' => 'America/Sao Paulo (-03)',
|
421
|
+
'tahiti' => 'Pacific/Tahiti (-10)',
|
422
|
+
'paris' => 'Europe/Paris'
|
423
|
+
},
|
424
|
+
}
|
425
|
+
|
426
|
+
tz = time_zones[ENV['DB']]
|
427
|
+
skip "Unsupported timezone conversion for DB=#{ENV['DB']}" if tz.nil?
|
428
|
+
assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['utc']))
|
429
|
+
assert_equal '2014/03/03 09:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['sao_paulo']))
|
430
|
+
assert_equal '2014/03/03 02:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S', tz['tahiti']))
|
431
|
+
|
432
|
+
# Winter/Summer time
|
433
|
+
assert_equal '2022/02/01 11:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-02-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
434
|
+
assert_equal '2022/08/01 12:42:00', t(@lucas, Arel::Nodes.build_quoted('2022-08-01 10:42:00').cast(:datetime).format('%Y/%m/%d %H:%M:%S', tz['paris']))
|
373
435
|
end
|
374
436
|
|
375
437
|
def test_coalesce
|
@@ -525,7 +587,7 @@ module ArelExtensions
|
|
525
587
|
# puts @age.is_null.inspect
|
526
588
|
# puts @age.is_null.to_sql
|
527
589
|
# puts @age=='34'
|
528
|
-
assert_equal "Test", User.select(@name).where(@age.is_null
|
590
|
+
assert_equal "Test", User.select(@name).where(@age.is_null).first.name
|
529
591
|
end
|
530
592
|
|
531
593
|
def test_math_plus
|
@@ -673,6 +735,7 @@ module ArelExtensions
|
|
673
735
|
end
|
674
736
|
|
675
737
|
def test_subquery_with_order
|
738
|
+
skip if ['mssql'].include?(@env_db) && Arel::VERSION.to_i < 10
|
676
739
|
assert_equal 9, User.where(:name => User.select(:name).order(:name)).count
|
677
740
|
assert_equal 9, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
|
678
741
|
if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
|
data/version_v1.rb
CHANGED
data/version_v2.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yann Azoury
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2022-
|
13
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -97,7 +97,6 @@ files:
|
|
97
97
|
- Rakefile
|
98
98
|
- SQL_Challenges.md
|
99
99
|
- TODO
|
100
|
-
- appveyor.yml
|
101
100
|
- arel_extensions.gemspec
|
102
101
|
- functions.html
|
103
102
|
- gemfiles/rails3.gemfile
|
@@ -123,6 +122,7 @@ files:
|
|
123
122
|
- lib/arel_extensions/common_sql_functions.rb
|
124
123
|
- lib/arel_extensions/comparators.rb
|
125
124
|
- lib/arel_extensions/date_duration.rb
|
125
|
+
- lib/arel_extensions/helpers.rb
|
126
126
|
- lib/arel_extensions/insert_manager.rb
|
127
127
|
- lib/arel_extensions/math.rb
|
128
128
|
- lib/arel_extensions/math_functions.rb
|
data/appveyor.yml
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
version: "{build}"
|
2
|
-
|
3
|
-
cache:
|
4
|
-
- vendor/bundle
|
5
|
-
|
6
|
-
branches:
|
7
|
-
only:
|
8
|
-
- master
|
9
|
-
|
10
|
-
services:
|
11
|
-
- mssql2014
|
12
|
-
|
13
|
-
|
14
|
-
install:
|
15
|
-
- set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
|
16
|
-
- bundle config --local path vendor/bundle
|
17
|
-
- bundle install
|
18
|
-
|
19
|
-
# Disable normal Windows builds in favor of our test script.
|
20
|
-
build: off
|
21
|
-
|
22
|
-
|
23
|
-
before_test:
|
24
|
-
- ruby -v
|
25
|
-
- gem -v
|
26
|
-
- bundle -v
|
27
|
-
|
28
|
-
test_script:
|
29
|
-
- ruby --version
|
30
|
-
- gem --version
|
31
|
-
- bundler --version
|
32
|
-
- bundle exec rake test
|
33
|
-
- ps: Start-Service 'MSSQL$SQL2014'
|
34
|
-
- timeout /t 4 /nobreak > NUL
|
35
|
-
- bundle exec rake test:mssql
|
36
|
-
|
37
|
-
environment:
|
38
|
-
matrix:
|
39
|
-
- RUBY_VERSION: 200
|
40
|
-
- RUBY_VERSION: 21
|
41
|
-
- RUBY_VERSION: 22
|
42
|
-
- RUBY_VERSION: 23
|
43
|
-
- RUBY_VERSION: 23-x64
|
44
|
-
|