arel_extensions 1.3.8 → 1.3.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/publish.yml +29 -0
- data/.github/workflows/release.yml +30 -0
- data/.github/workflows/ruby.yml +173 -147
- data/NEWS.md +37 -3
- data/README.md +4 -4
- data/bin/build +15 -0
- data/bin/publish +8 -0
- data/dev/compose.yaml +8 -0
- data/gemfiles/rails6.gemfile +4 -3
- data/gemfiles/rails6_1.gemfile +4 -3
- data/gemfiles/rails7.gemfile +9 -1
- data/gemfiles/rails7_1.gemfile +8 -0
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +97 -61
- data/lib/arel_extensions/visitors/mysql.rb +2 -2
- data/lib/arel_extensions/visitors/postgresql.rb +2 -2
- data/lib/arel_extensions/visitors.rb +56 -61
- data/lib/arel_extensions.rb +20 -0
- data/test/arelx_test_helper.rb +20 -13
- data/test/real_db_test.rb +16 -2
- data/test/with_ar/all_agnostic_test.rb +1 -1
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +7 -3
data/gemfiles/rails7.gemfile
CHANGED
@@ -13,11 +13,19 @@ group :development, :test do
|
|
13
13
|
gem 'pg', '~> 1.1', platforms: [:mri]
|
14
14
|
|
15
15
|
gem 'tiny_tds', platforms: %i[mri mingw x64_mingw mswin]
|
16
|
-
gem 'activerecord-sqlserver-adapter', '~> 7.0.
|
16
|
+
gem 'activerecord-sqlserver-adapter', '~> 7.0.7', platforms: %i[mri mingw x64_mingw mswin]
|
17
17
|
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw]
|
18
18
|
|
19
19
|
gem 'ruby-oci8', platforms: %i[mri mswin mingw] if ENV.has_key? 'ORACLE_HOME'
|
20
20
|
gem 'activerecord-oracle_enhanced-adapter', '~> 6.0.0' if ENV.has_key? 'ORACLE_HOME'
|
21
|
+
|
22
|
+
# for JRuby
|
23
|
+
gem 'jdbc-mssql', platforms: :jruby, require: true
|
24
|
+
gem 'jdbc-sqlite3', platform: :jruby
|
25
|
+
gem 'activerecord-jdbc-alt-adapter', '~> 70.0', platform: :jruby, require: true
|
26
|
+
gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
|
27
|
+
gem 'activerecord-jdbcpostgresql-adapter', platforms: :jruby
|
28
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
21
29
|
end
|
22
30
|
|
23
31
|
gemspec path: Dir.pwd
|
data/gemfiles/rails7_1.gemfile
CHANGED
@@ -17,6 +17,14 @@ group :development, :test do
|
|
17
17
|
|
18
18
|
gem 'ruby-oci8', platforms: %i[mri mswin mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
19
|
gem 'activerecord-oracle_enhanced-adapter', '~> 7.0.0' if ENV.has_key? 'ORACLE_HOME'
|
20
|
+
|
21
|
+
# for JRuby
|
22
|
+
gem 'jdbc-mssql', platforms: :jruby, require: true
|
23
|
+
gem 'jdbc-sqlite3', platform: :jruby
|
24
|
+
gem 'activerecord-jdbc-alt-adapter', '~> 71.0.0.alpha1', platform: :jruby, require: true
|
25
|
+
gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
|
26
|
+
gem 'activerecord-jdbcpostgresql-adapter', platforms: :jruby
|
27
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
20
28
|
end
|
21
29
|
|
22
30
|
gemspec path: Dir.pwd
|
@@ -2,52 +2,68 @@ module ArelExtensions
|
|
2
2
|
module Visitors
|
3
3
|
module MSSQL
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
5
|
+
MSSQL_CLASS_NAMES = %i[MSSQL SQLServer].freeze
|
6
|
+
|
7
|
+
mssql_class =
|
8
|
+
Arel::Visitors
|
9
|
+
.constants
|
10
|
+
.select { |c| Arel::Visitors.const_get(c).is_a?(Class) }
|
11
|
+
.find { |c| MSSQL_CLASS_NAMES.include?(c) }
|
12
|
+
|
13
|
+
# This guard is necessary because:
|
14
|
+
#
|
15
|
+
# 1. const_get(mssql_class) will fail when mssql_class is nil.
|
16
|
+
# 2. mssql_class could be nil under certain conditions:
|
17
|
+
# 1. especially on ruby 2.5 (and surprisingly not jruby 9.2) and 3.0+.
|
18
|
+
# 2. when not working with mssql itself.
|
19
|
+
if mssql_class
|
20
|
+
LOADED_VISITOR = Arel::Visitors.const_get(mssql_class)
|
21
|
+
|
22
|
+
LOADED_VISITOR::DATE_MAPPING = {
|
23
|
+
'd' => 'day', 'm' => 'month', 'y' => 'year',
|
24
|
+
'wd' => 'weekday', 'w' => 'week',
|
25
|
+
'h' => 'hour', 'mn' => 'minute', 's' => 'second'
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
LOADED_VISITOR::DATE_FORMAT_DIRECTIVES = {
|
29
|
+
'%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => 'month', '%^B' => '', '%b' => '', '%^b' => '', # year, month
|
30
|
+
'%V' => 'iso_week', '%G' => '', # ISO week number and year of week
|
31
|
+
'%d' => 'DD', '%e' => '' , '%j' => '' , '%w' => 'dw', %'a' => '', '%A' => 'weekday', # day, weekday
|
32
|
+
'%H' => 'hh', '%k' => '' , '%I' => '' , '%l' => '' , '%P' => '', '%p' => '', # hours
|
33
|
+
'%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
|
34
|
+
}.freeze
|
35
|
+
|
36
|
+
LOADED_VISITOR::DATE_FORMAT_FORMAT = {
|
37
|
+
'YY' => '0#', 'MM' => '0#', 'DD' => '0#',
|
38
|
+
'hh' => '0#', 'mi' => '0#', 'ss' => '0#',
|
39
|
+
'iso_week' => '0#'
|
40
|
+
}
|
41
|
+
|
42
|
+
LOADED_VISITOR::DATE_NAME = [
|
43
|
+
'%B', '%A'
|
44
|
+
]
|
45
|
+
|
46
|
+
LOADED_VISITOR::DATE_FORMAT_REGEX =
|
47
|
+
Regexp.new(
|
48
|
+
LOADED_VISITOR::DATE_FORMAT_DIRECTIVES
|
49
|
+
.keys
|
50
|
+
.map{|k| Regexp.escape(k)}
|
51
|
+
.join('|')
|
52
|
+
).freeze
|
53
|
+
|
54
|
+
# TODO; all others... http://www.sql-server-helper.com/tips/date-formats.aspx
|
55
|
+
LOADED_VISITOR::DATE_CONVERT_FORMATS = {
|
56
|
+
'YYYY-MM-DD' => 120,
|
57
|
+
'YY-MM-DD' => 120,
|
58
|
+
'MM/DD/YYYY' => 101,
|
59
|
+
'MM-DD-YYYY' => 110,
|
60
|
+
'YYYY/MM/DD' => 111,
|
61
|
+
'DD-MM-YYYY' => 105,
|
62
|
+
'DD-MM-YY' => 5,
|
63
|
+
'DD.MM.YYYY' => 104,
|
64
|
+
'YYYY-MM-DDTHH:MM:SS:MMM' => 126
|
65
|
+
}.freeze
|
66
|
+
end
|
51
67
|
|
52
68
|
# Quoting in JRuby + AR < 5 requires special handling for MSSQL.
|
53
69
|
#
|
@@ -57,9 +73,10 @@ module ArelExtensions
|
|
57
73
|
# It didn't handle numbers correctly: `quote(1, nil)` translated into
|
58
74
|
# `N'1'` which we don't want.
|
59
75
|
#
|
60
|
-
# The following is adapted from
|
76
|
+
# The following is adapted from
|
77
|
+
# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
|
61
78
|
#
|
62
|
-
if RUBY_PLATFORM == 'java'
|
79
|
+
if RUBY_PLATFORM == 'java'
|
63
80
|
def quote_string(s)
|
64
81
|
s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
65
82
|
end
|
@@ -70,14 +87,15 @@ module ArelExtensions
|
|
70
87
|
|
71
88
|
def quoted_date(value)
|
72
89
|
if value.acts_like?(:time)
|
73
|
-
if ActiveRecord::Base.default_timezone == :utc
|
90
|
+
if (ActiveRecord.respond_to?(:default_timezone) && ActiveRecord.default_timezone == :utc) || ActiveRecord::Base.default_timezone == :utc
|
74
91
|
value = value.getutc if value.respond_to?(:getutc) && !value.utc?
|
75
92
|
else
|
76
93
|
value = value.getlocal if value.respond_to?(:getlocal)
|
77
94
|
end
|
78
95
|
end
|
79
|
-
|
80
|
-
|
96
|
+
# new versions of AR use `to_fs`, but we want max compatibility, and we're
|
97
|
+
# not going to write it over and over, so it's fine like that.
|
98
|
+
result = value.to_formatted_s(:db)
|
81
99
|
if value.respond_to?(:usec) && value.usec > 0
|
82
100
|
result << '.' << sprintf('%06d', value.usec)
|
83
101
|
else
|
@@ -104,17 +122,19 @@ module ArelExtensions
|
|
104
122
|
value
|
105
123
|
when String, Symbol, ActiveSupport::Multibyte::Chars
|
106
124
|
"'#{quote_string(value.to_s)}'"
|
107
|
-
when true
|
125
|
+
when true
|
108
126
|
quoted_true
|
109
|
-
when false
|
127
|
+
when false
|
110
128
|
quoted_false
|
111
|
-
when nil
|
129
|
+
when nil
|
112
130
|
'NULL'
|
113
131
|
# BigDecimals need to be put in a non-normalized form and quoted.
|
114
132
|
when BigDecimal
|
115
133
|
value.to_s('F')
|
116
134
|
when Numeric, ActiveSupport::Duration
|
117
135
|
value.to_s
|
136
|
+
when Arel::VERSION.to_i > 6 && ActiveRecord::Type::Time::Value
|
137
|
+
"'#{quoted_time(value)}'"
|
118
138
|
when Date, Time
|
119
139
|
"'#{quoted_date(value)}'"
|
120
140
|
when Class
|
@@ -125,6 +145,15 @@ module ArelExtensions
|
|
125
145
|
end
|
126
146
|
end
|
127
147
|
|
148
|
+
alias_method(:old_primary_Key_From_Table, :primary_Key_From_Table) rescue nil
|
149
|
+
def primary_Key_From_Table t
|
150
|
+
return unless t
|
151
|
+
|
152
|
+
column_name = @connection.schema_cache.primary_keys(t.name) ||
|
153
|
+
@connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
|
154
|
+
column_name ? t[column_name] : nil
|
155
|
+
end
|
156
|
+
|
128
157
|
# Math Functions
|
129
158
|
def visit_ArelExtensions_Nodes_Ceil o, collector
|
130
159
|
collector << 'CEILING('
|
@@ -543,14 +572,21 @@ module ArelExtensions
|
|
543
572
|
collector = visit o.left, collector
|
544
573
|
end
|
545
574
|
collector << ' AS '
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
575
|
+
# Sometimes these values are already quoted, if they are, don't double quote it
|
576
|
+
lft, rgt =
|
577
|
+
if o.right.is_a?(Arel::Nodes::SqlLiteral)
|
578
|
+
if Arel::VERSION.to_i >= 6 && o.right[0] != '[' && o.right[-1] != ']'
|
579
|
+
# This is a lie, it's not about arel version, but SQL Server's (>= 2000).
|
580
|
+
['[', ']']
|
581
|
+
elsif o.right[0] != '"' && o.right[-1] != '"'
|
582
|
+
['"', '"']
|
583
|
+
else
|
584
|
+
[]
|
585
|
+
end
|
586
|
+
end
|
587
|
+
collector << lft if lft
|
551
588
|
collector = visit o.right, collector
|
552
|
-
collector <<
|
553
|
-
|
589
|
+
collector << rgt if rgt
|
554
590
|
collector
|
555
591
|
end
|
556
592
|
|
@@ -158,10 +158,10 @@ module ArelExtensions
|
|
158
158
|
collector = visit o.expressions.first, collector
|
159
159
|
collector <<
|
160
160
|
if o.ai
|
161
|
-
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' :
|
161
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : "#{charset}_unicode_ci"}"
|
162
162
|
# doesn't work in latin1
|
163
163
|
elsif o.ci
|
164
|
-
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' :
|
164
|
+
" COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : "#{charset}_unicode_ci"}"
|
165
165
|
else
|
166
166
|
" COLLATE #{charset}_bin"
|
167
167
|
end
|
@@ -190,7 +190,7 @@ module ArelExtensions
|
|
190
190
|
collector << ' AT TIME ZONE '
|
191
191
|
collector = visit Arel.quoted(dst_tz), collector
|
192
192
|
when String
|
193
|
-
collector <<
|
193
|
+
collector << ") AT TIME ZONE 'UTC' AT TIME ZONE "
|
194
194
|
collector = visit Arel.quoted(o.time_zone), collector
|
195
195
|
end
|
196
196
|
collector << COMMA
|
@@ -392,7 +392,7 @@ module ArelExtensions
|
|
392
392
|
when :number, :decimal, :float
|
393
393
|
'numeric'
|
394
394
|
when :datetime
|
395
|
-
'timestamp
|
395
|
+
'timestamp without time zone'
|
396
396
|
when :date
|
397
397
|
'date'
|
398
398
|
when :binary
|
@@ -1,6 +1,21 @@
|
|
1
|
+
# MSSQL visitors for java and rails ≥ 7 are painful to work with:
|
2
|
+
# requiring the exact path to the visitor is needed even if the
|
3
|
+
# AR adapter was loaded. It's also needed exactly here because:
|
4
|
+
# 1. putting it inside the visitor or anywhere else will not
|
5
|
+
# guarantee its actual loading.
|
6
|
+
# 2. it needs to load before arel_extensions/visitors.
|
7
|
+
if RUBY_PLATFORM == 'java' && Gem::Specification.find { |g| g.name == 'jdbc-mssql' }
|
8
|
+
begin
|
9
|
+
require 'arel/visitors/sqlserver'
|
10
|
+
rescue LoadError
|
11
|
+
warn 'arel/visitors/sqlserver not found: MSSQL might not work correctly.'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
1
15
|
require 'arel_extensions/visitors/convert_format'
|
2
16
|
require 'arel_extensions/visitors/to_sql'
|
3
17
|
require 'arel_extensions/visitors/mysql'
|
18
|
+
require 'arel_extensions/visitors/mssql'
|
4
19
|
require 'arel_extensions/visitors/postgresql'
|
5
20
|
require 'arel_extensions/visitors/sqlite'
|
6
21
|
|
@@ -9,10 +24,6 @@ if defined?(Arel::Visitors::Oracle)
|
|
9
24
|
require 'arel_extensions/visitors/oracle12'
|
10
25
|
end
|
11
26
|
|
12
|
-
if defined?(Arel::Visitors::SQLServer) || defined?(Arel::Visitors::MSSQL)
|
13
|
-
require 'arel_extensions/visitors/mssql'
|
14
|
-
end
|
15
|
-
|
16
27
|
if defined?(Arel::Visitors::SQLServer)
|
17
28
|
class Arel::Visitors::SQLServer
|
18
29
|
include ArelExtensions::Visitors::MSSQL
|
@@ -27,26 +38,20 @@ if defined?(Arel::Visitors::DepthFirst)
|
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
41
|
+
# Especially required here, not inside the next if, for Arel < 6.
|
42
|
+
if RUBY_PLATFORM != 'java'
|
43
|
+
begin
|
44
|
+
require 'arel_sqlserver'
|
45
|
+
rescue LoadError
|
46
|
+
warn 'gem arel_sqlserver not found: SQLServer Visitor might not work correctly.'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
30
50
|
if defined?(Arel::Visitors::MSSQL)
|
31
51
|
class Arel::Visitors::MSSQL
|
32
52
|
include ArelExtensions::Visitors::MSSQL
|
33
53
|
|
34
|
-
alias_method(:
|
35
|
-
def visit_Arel_Nodes_As o, collector
|
36
|
-
if o.left.is_a?(Arel::Nodes::Binary)
|
37
|
-
collector << '('
|
38
|
-
collector = visit o.left, collector
|
39
|
-
collector << ')'
|
40
|
-
else
|
41
|
-
collector = visit o.left, collector
|
42
|
-
end
|
43
|
-
collector << ' AS ['
|
44
|
-
collector = visit o.right, collector
|
45
|
-
collector << ']'
|
46
|
-
collector
|
47
|
-
end
|
48
|
-
|
49
|
-
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
54
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement)
|
50
55
|
def visit_Arel_Nodes_SelectStatement o, collector
|
51
56
|
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
52
57
|
o = o.dup
|
@@ -55,51 +60,41 @@ if defined?(Arel::Visitors::MSSQL)
|
|
55
60
|
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
56
61
|
end
|
57
62
|
end
|
63
|
+
end
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
if Arel::Visitors::VISITORS['sqlserver'] && Arel::Visitors::VISITORS['sqlserver'] != Arel::Visitors::MSSQL
|
63
|
-
Arel::Visitors::VISITORS['sqlserver'].class_eval do
|
64
|
-
include ArelExtensions::Visitors::MSSQL
|
65
|
-
|
66
|
-
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
67
|
-
def visit_Arel_Nodes_SelectStatement o, collector
|
68
|
-
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
69
|
-
o = o.dup
|
70
|
-
o.orders = []
|
71
|
-
end
|
72
|
-
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
73
|
-
end
|
74
|
-
|
75
|
-
alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
|
76
|
-
def visit_Arel_Nodes_As o, collector
|
77
|
-
if o.left.is_a?(Arel::Nodes::Binary)
|
78
|
-
collector << '('
|
79
|
-
collector = visit o.left, collector
|
80
|
-
collector << ')'
|
81
|
-
else
|
82
|
-
collector = visit o.left, collector
|
83
|
-
end
|
84
|
-
collector << ' AS ['
|
85
|
-
collector = visit o.right, collector
|
86
|
-
collector << ']'
|
87
|
-
collector
|
88
|
-
end
|
65
|
+
if defined?(Arel::Visitors::SQLServer)
|
66
|
+
class Arel::Visitors::SQLServer
|
67
|
+
include ArelExtensions::Visitors::MSSQL
|
89
68
|
|
90
|
-
|
91
|
-
|
92
|
-
|
69
|
+
# There's a bug when working with jruby 9.4 that prevents us from
|
70
|
+
# refactoring this and putting it in the main module, or even in a separate
|
71
|
+
# module then including it.
|
72
|
+
#
|
73
|
+
# Reason: the line in this file that does:
|
74
|
+
#
|
75
|
+
# require 'arel_extensions/visitors/mssql'
|
76
|
+
#
|
77
|
+
# The error could be seen by:
|
78
|
+
#
|
79
|
+
# 1. placing the visit_ inside the visitor, or placing it in a module
|
80
|
+
# then including it here.
|
81
|
+
# 2. replacing the `rescue nil` from aliasing trick, and printing the
|
82
|
+
# error.
|
83
|
+
#
|
84
|
+
# It complains that the visit_ does not exist in the module, as if it's
|
85
|
+
# evaluating the module eagerly, instead of lazily like in other versions
|
86
|
+
# of ruby.
|
87
|
+
#
|
88
|
+
# It might be something different, but this is the first thing we should
|
89
|
+
# investigate.
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
91
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
92
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
93
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
94
|
+
o = o.dup
|
95
|
+
o.orders = []
|
99
96
|
end
|
97
|
+
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
100
98
|
end
|
101
|
-
rescue LoadError
|
102
|
-
rescue => e
|
103
|
-
e
|
104
99
|
end
|
105
100
|
end
|
data/lib/arel_extensions.rb
CHANGED
@@ -121,6 +121,26 @@ module Arel
|
|
121
121
|
)
|
122
122
|
end
|
123
123
|
|
124
|
+
def self.json_true
|
125
|
+
res = Arel.grouping(Arel.quoted('true'))
|
126
|
+
res.instance_eval {
|
127
|
+
def return_type
|
128
|
+
:boolean
|
129
|
+
end
|
130
|
+
}
|
131
|
+
res
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.json_false
|
135
|
+
res = Arel.grouping(Arel.quoted('false'))
|
136
|
+
res.instance_eval {
|
137
|
+
def return_type
|
138
|
+
:boolean
|
139
|
+
end
|
140
|
+
}
|
141
|
+
res
|
142
|
+
end
|
143
|
+
|
124
144
|
# The NULL literal.
|
125
145
|
def self.null
|
126
146
|
Arel.quoted(nil)
|
data/test/arelx_test_helper.rb
CHANGED
@@ -12,7 +12,8 @@ end
|
|
12
12
|
|
13
13
|
YELLOW = '33'
|
14
14
|
|
15
|
-
# Load gems specific to databases
|
15
|
+
# Load gems specific to databases.
|
16
|
+
#
|
16
17
|
# NOTE:
|
17
18
|
# It's strongly advised to test each database on its own. Loading multiple
|
18
19
|
# backend gems leads to undefined behavior according to tests; the backend
|
@@ -22,26 +23,32 @@ YELLOW = '33'
|
|
22
23
|
# The issue also seems to be related to arel version: at some point, arel
|
23
24
|
# dropped its wide support for DBs and kept Postgres, MySQL and SQLite.
|
24
25
|
# Here, we're just trying to load the correct ones.
|
26
|
+
#
|
27
|
+
# NOTE:
|
28
|
+
# As of jruby 9.4 (and maybe 9.3, but I couldn't test it given the state of
|
29
|
+
# the alt-adapter), we need to load jdbc/mssql manually.
|
25
30
|
db_and_gem =
|
26
|
-
if
|
31
|
+
if RUBY_PLATFORM == 'java'
|
27
32
|
{
|
28
|
-
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
29
|
-
'mssql' => 'activerecord-jdbcsqlserver-adapter'
|
33
|
+
'oracle' => ['activerecord-oracle_enhanced-adapter'],
|
34
|
+
'mssql' => ['jdbc/mssql', 'activerecord-jdbcsqlserver-adapter'],
|
30
35
|
}
|
31
36
|
else
|
32
37
|
{
|
33
|
-
'oracle' => 'activerecord-oracle_enhanced-adapter',
|
34
|
-
'mssql' => 'activerecord-sqlserver-adapter'
|
38
|
+
'oracle' => ['activerecord-oracle_enhanced-adapter'],
|
39
|
+
'mssql' => ['activerecord-sqlserver-adapter'],
|
35
40
|
}
|
36
41
|
end
|
37
42
|
|
38
|
-
def load_lib(
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
def load_lib(gems)
|
44
|
+
if gems && (RUBY_PLATFORM == 'java' || Arel::VERSION.to_i > 9)
|
45
|
+
gems.each do |gem|
|
46
|
+
begin
|
47
|
+
require gem
|
48
|
+
rescue Exception => e
|
49
|
+
warn "Warning: failed to load gem #{gem}. Are you sure it's installed?"
|
50
|
+
warn e.message
|
51
|
+
end
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
data/test/real_db_test.rb
CHANGED
@@ -40,6 +40,7 @@ def setup_db
|
|
40
40
|
t.column :created_at, :date
|
41
41
|
t.column :updated_at, :date
|
42
42
|
t.column :score, :decimal
|
43
|
+
t.column :updated_at, :datetime
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
@@ -53,11 +54,12 @@ end
|
|
53
54
|
class ListTest < Minitest::Test
|
54
55
|
def setup
|
55
56
|
d = Date.new(2016, 05, 23)
|
57
|
+
dt = Time.new(2016, 05, 23, 12, 34, 56)
|
56
58
|
setup_db
|
57
59
|
User.create age: 5, name: 'Lucas', created_at: d, score: 20.16
|
58
60
|
User.create age: 15, name: 'Sophie', created_at: d, score: 20.16
|
59
61
|
User.create age: 20, name: 'Camille', created_at: d, score: 20.16
|
60
|
-
User.create age: 21, name: 'Arthur', created_at: d, score: 65.62
|
62
|
+
User.create age: 21, name: 'Arthur', created_at: d, score: 65.62, updated_at: dt
|
61
63
|
u = User.create age: 23, name: 'Myung', created_at: d, score: 20.16
|
62
64
|
@myung = User.where(id: u.id)
|
63
65
|
User.create age: 25, name: 'Laure', created_at: d, score: 20.16
|
@@ -91,7 +93,7 @@ class ListTest < Minitest::Test
|
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
94
|
-
def
|
96
|
+
def test_comparator
|
95
97
|
assert_equal 2, User.where(User.arel_table[:age] < 6).count
|
96
98
|
assert_equal 2, User.where(User.arel_table[:age] <= 10).count
|
97
99
|
assert_equal 3, User.where(User.arel_table[:age] > 20).count
|
@@ -99,6 +101,18 @@ class ListTest < Minitest::Test
|
|
99
101
|
assert_equal 1, User.where(User.arel_table[:age] > 5).where(User.arel_table[:age] < 20).count
|
100
102
|
end
|
101
103
|
|
104
|
+
def test_date_date_comparator
|
105
|
+
d = Date.new(2016, 05, 24) #after created_at in db
|
106
|
+
assert_equal 8, User.where(User.arel_table[:age] < d).count
|
107
|
+
assert_equal 0, User.where(User.arel_table[:age] > d).count
|
108
|
+
assert_equal 0, User.where(User.arel_table[:age] == d).count
|
109
|
+
d = Date.new(2016, 05, 23)
|
110
|
+
assert_equal 8, User.where(User.arel_table[:age] == d).count
|
111
|
+
dt = Time.new(2016, 05, 23, 12, 35, 00) #after updated_at in db
|
112
|
+
assert_equal 1, User.where(User.arel_table[:update_at] < dt).count
|
113
|
+
assert_equal 0, User.where(User.arel_table[:update_at] > dt).count
|
114
|
+
end
|
115
|
+
|
102
116
|
def test_date_duration
|
103
117
|
# Year
|
104
118
|
assert_equal 2016, User.where(User.arel_table[:name].eq('Lucas')).select((User.arel_table[:created_at].year).as('res')).first.res.to_i
|
@@ -501,7 +501,7 @@ module ArelExtensions
|
|
501
501
|
#
|
502
502
|
# MySQL is happy to consider that times by default are in UTC.
|
503
503
|
assert_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', {tz['utc'] => tz['paris']}))
|
504
|
-
refute_equal '2014/03/03 13:42:00', t(@lucas, @updated_at.send(method, '%Y/%m/%d %H:%M:%S', tz['paris'])) if
|
504
|
+
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'])
|
505
505
|
|
506
506
|
# Winter/Summer time
|
507
507
|
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']}))
|
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: 1.3.
|
4
|
+
version: 1.3.10
|
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:
|
13
|
+
date: 2024-07-31 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -67,6 +67,8 @@ extra_rdoc_files:
|
|
67
67
|
- functions.html
|
68
68
|
files:
|
69
69
|
- ".codeclimate.yml"
|
70
|
+
- ".github/workflows/publish.yml"
|
71
|
+
- ".github/workflows/release.yml"
|
70
72
|
- ".github/workflows/ruby.yml"
|
71
73
|
- ".gitignore"
|
72
74
|
- ".rubocop.yml"
|
@@ -79,6 +81,8 @@ files:
|
|
79
81
|
- TODO
|
80
82
|
- appveyor.yml
|
81
83
|
- arel_extensions.gemspec
|
84
|
+
- bin/build
|
85
|
+
- bin/publish
|
82
86
|
- dev/compose.yaml
|
83
87
|
- functions.html
|
84
88
|
- gemfiles/rails3.gemfile
|
@@ -210,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
210
214
|
- !ruby/object:Gem::Version
|
211
215
|
version: '0'
|
212
216
|
requirements: []
|
213
|
-
rubygems_version: 3.
|
217
|
+
rubygems_version: 3.4.19
|
214
218
|
signing_key:
|
215
219
|
specification_version: 4
|
216
220
|
summary: Extending Arel
|