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
@@ -1,6 +1,32 @@
|
|
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' \
|
8
|
+
&& RUBY_ENGINE == 'jruby' \
|
9
|
+
&& (version = JRUBY_VERSION.split('.').map(&:to_i)) && version[0] == 9 && version[1] >= 4 \
|
10
|
+
&& Gem::Specification.find { |g| g.name == 'jdbc-mssql' }
|
11
|
+
begin
|
12
|
+
require 'arel/visitors/sqlserver'
|
13
|
+
rescue LoadError
|
14
|
+
warn 'arel/visitors/sqlserver not found: MSSQL might not work correctly.'
|
15
|
+
end
|
16
|
+
elsif RUBY_PLATFORM != 'java' \
|
17
|
+
&& Arel::VERSION.to_i < 10 \
|
18
|
+
&& Gem::Specification.find { |g| g.name == 'activerecord-sqlserver-adapter' }
|
19
|
+
begin
|
20
|
+
require 'arel_sqlserver'
|
21
|
+
rescue LoadError
|
22
|
+
warn 'arel_sqlserver not found: SQLServer Visitor might not work correctly.'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
1
26
|
require 'arel_extensions/visitors/convert_format'
|
2
27
|
require 'arel_extensions/visitors/to_sql'
|
3
28
|
require 'arel_extensions/visitors/mysql'
|
29
|
+
require 'arel_extensions/visitors/mssql'
|
4
30
|
require 'arel_extensions/visitors/postgresql'
|
5
31
|
require 'arel_extensions/visitors/sqlite'
|
6
32
|
|
@@ -9,81 +35,68 @@ if defined?(Arel::Visitors::Oracle)
|
|
9
35
|
require 'arel_extensions/visitors/oracle12'
|
10
36
|
end
|
11
37
|
|
12
|
-
if defined?(Arel::Visitors::
|
13
|
-
|
14
|
-
|
15
|
-
class Arel::Visitors::MSSQL
|
38
|
+
if defined?(Arel::Visitors::SQLServer)
|
39
|
+
class Arel::Visitors::SQLServer
|
16
40
|
include ArelExtensions::Visitors::MSSQL
|
41
|
+
end
|
42
|
+
end
|
17
43
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
collector = visit o.left, collector
|
23
|
-
collector << ')'
|
24
|
-
else
|
25
|
-
collector = visit o.left, collector
|
26
|
-
end
|
27
|
-
collector << " AS ["
|
28
|
-
collector = visit o.right, collector
|
29
|
-
collector << "]"
|
30
|
-
collector
|
44
|
+
if defined?(Arel::Visitors::DepthFirst)
|
45
|
+
class Arel::Visitors::DepthFirst
|
46
|
+
def visit_Arel_SelectManager o
|
47
|
+
visit o.ast
|
31
48
|
end
|
49
|
+
end
|
50
|
+
end
|
32
51
|
|
33
|
-
|
52
|
+
if defined?(Arel::Visitors::MSSQL)
|
53
|
+
class Arel::Visitors::MSSQL
|
54
|
+
include ArelExtensions::Visitors::MSSQL
|
55
|
+
|
56
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement)
|
34
57
|
def visit_Arel_Nodes_SelectStatement o, collector
|
35
58
|
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
36
59
|
o = o.dup
|
37
60
|
o.orders = []
|
38
61
|
end
|
39
|
-
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
62
|
+
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
40
63
|
end
|
41
64
|
end
|
65
|
+
end
|
42
66
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if Arel::Visitors::VISITORS['sqlserver'] && Arel::Visitors::VISITORS['sqlserver'] != Arel::Visitors::MSSQL
|
47
|
-
Arel::Visitors::VISITORS['sqlserver'].class_eval do
|
48
|
-
include ArelExtensions::Visitors::MSSQL
|
49
|
-
|
50
|
-
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
51
|
-
def visit_Arel_Nodes_SelectStatement o, collector
|
52
|
-
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
53
|
-
o = o.dup
|
54
|
-
o.orders = []
|
55
|
-
end
|
56
|
-
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
57
|
-
end
|
58
|
-
|
59
|
-
alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
|
60
|
-
def visit_Arel_Nodes_As o, collector
|
61
|
-
if o.left.is_a?(Arel::Nodes::Binary)
|
62
|
-
collector << '('
|
63
|
-
collector = visit o.left, collector
|
64
|
-
collector << ')'
|
65
|
-
else
|
66
|
-
collector = visit o.left, collector
|
67
|
-
end
|
68
|
-
collector << " AS ["
|
69
|
-
collector = visit o.right, collector
|
70
|
-
collector << "]"
|
71
|
-
collector
|
72
|
-
end
|
67
|
+
if defined?(Arel::Visitors::SQLServer)
|
68
|
+
class Arel::Visitors::SQLServer
|
69
|
+
include ArelExtensions::Visitors::MSSQL
|
73
70
|
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
# There's a bug when working with jruby 9.4 that prevents us from
|
72
|
+
# refactoring this and putting it in the main module, or even in a separate
|
73
|
+
# module then including it.
|
74
|
+
#
|
75
|
+
# Reason: the line in this file that does:
|
76
|
+
#
|
77
|
+
# require 'arel_extensions/visitors/mssql'
|
78
|
+
#
|
79
|
+
# The error could be seen by:
|
80
|
+
#
|
81
|
+
# 1. placing the visit_ inside the visitor, or placing it in a module
|
82
|
+
# then including it here.
|
83
|
+
# 2. replacing the `rescue nil` from aliasing trick, and printing the
|
84
|
+
# error.
|
85
|
+
#
|
86
|
+
# It complains that the visit_ does not exist in the module, as if it's
|
87
|
+
# evaluating the module eagerly, instead of lazily like in other versions
|
88
|
+
# of ruby.
|
89
|
+
#
|
90
|
+
# It might be something different, but this is the first thing we should
|
91
|
+
# investigate.
|
77
92
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
alias_method(:old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement) rescue nil
|
94
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
95
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
96
|
+
o = o.dup
|
97
|
+
o.orders = []
|
83
98
|
end
|
99
|
+
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
84
100
|
end
|
85
|
-
rescue LoadError
|
86
|
-
rescue => e
|
87
|
-
e
|
88
101
|
end
|
89
102
|
end
|
data/lib/arel_extensions.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'arel'
|
2
|
+
require 'base64'
|
2
3
|
|
3
4
|
require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
4
5
|
|
@@ -16,7 +17,7 @@ class Arel::Nodes::Casted
|
|
16
17
|
include Arel::AliasPredication
|
17
18
|
|
18
19
|
# They forget to define hash.
|
19
|
-
if Gem::Version.new(Arel::VERSION) < Gem::Version.new(
|
20
|
+
if Gem::Version.new(Arel::VERSION) < Gem::Version.new('10.0.0')
|
20
21
|
def hash
|
21
22
|
[self.class, self.val, self.attribute].hash
|
22
23
|
end
|
@@ -34,9 +35,9 @@ class Arel::Nodes::Grouping
|
|
34
35
|
end
|
35
36
|
|
36
37
|
class Arel::Nodes::Ordering
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def eql? other
|
39
|
+
self.hash.eql? other.hash
|
40
|
+
end
|
40
41
|
end
|
41
42
|
|
42
43
|
class Arel::Nodes::Function
|
@@ -44,14 +45,16 @@ class Arel::Nodes::Function
|
|
44
45
|
include Arel::Expressions
|
45
46
|
end
|
46
47
|
|
47
|
-
if Gem::Version.new(Arel::VERSION) >= Gem::Version.new(
|
48
|
+
if Gem::Version.new(Arel::VERSION) >= Gem::Version.new('7.1.0')
|
48
49
|
class Arel::Nodes::Case
|
49
50
|
include Arel::Math
|
50
51
|
include Arel::Expressions
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
55
|
+
require 'arel_extensions/helpers'
|
54
56
|
require 'arel_extensions/version'
|
57
|
+
require 'arel_extensions/aliases'
|
55
58
|
require 'arel_extensions/attributes'
|
56
59
|
require 'arel_extensions/visitors'
|
57
60
|
require 'arel_extensions/nodes'
|
@@ -75,45 +78,107 @@ require 'arel_extensions/nodes/case'
|
|
75
78
|
require 'arel_extensions/nodes/soundex'
|
76
79
|
require 'arel_extensions/nodes/cast'
|
77
80
|
require 'arel_extensions/nodes/json'
|
81
|
+
require 'arel_extensions/nodes/rollup'
|
82
|
+
require 'arel_extensions/nodes/select'
|
83
|
+
|
84
|
+
# It seems like the code in lib/arel_extensions/visitors.rb that is supposed
|
85
|
+
# to inject ArelExtension is not enough. Different versions of the sqlserver
|
86
|
+
# adapter behave differently. It doesn't always proc, so we added this for
|
87
|
+
# coverage.
|
88
|
+
if defined?(Arel::Visitors::SQLServer)
|
89
|
+
Arel::Visitors.const_set('MSSQL', Arel::Visitors::SQLServer)
|
90
|
+
require 'arel_extensions/visitors/mssql'
|
91
|
+
class Arel::Visitors::SQLServer
|
92
|
+
include ArelExtensions::Visitors::MSSQL
|
93
|
+
end
|
94
|
+
end
|
78
95
|
|
96
|
+
module Arel
|
97
|
+
def self.column_of table_name, column_name
|
98
|
+
ArelExtensions.column_of(table_name, column_name)
|
99
|
+
end
|
79
100
|
|
101
|
+
def self.duration s, expr
|
102
|
+
ArelExtensions::Nodes::Duration.new("#{s}i", expr)
|
103
|
+
end
|
80
104
|
|
81
|
-
|
82
|
-
def self.
|
83
|
-
|
105
|
+
# The FALSE pseudo literal.
|
106
|
+
def self.false
|
107
|
+
Arel::Nodes::Equality.new(1, 0)
|
84
108
|
end
|
85
109
|
|
86
|
-
def self.
|
87
|
-
|
110
|
+
def self.grouping *v
|
111
|
+
Arel::Nodes::Grouping.new(*v)
|
88
112
|
end
|
89
113
|
|
90
114
|
def self.json *expr
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
115
|
+
ArelExtensions::Nodes::Json.new(
|
116
|
+
if expr.length == 1
|
117
|
+
expr.first
|
118
|
+
else
|
119
|
+
expr
|
120
|
+
end
|
121
|
+
)
|
96
122
|
end
|
97
123
|
|
98
|
-
def self.
|
99
|
-
|
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
|
100
132
|
end
|
101
133
|
|
102
|
-
def self.
|
103
|
-
|
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
|
104
142
|
end
|
105
143
|
|
106
|
-
|
107
|
-
|
144
|
+
# The NULL literal.
|
145
|
+
def self.null
|
146
|
+
Arel.quoted(nil)
|
108
147
|
end
|
109
148
|
|
110
|
-
def self.
|
111
|
-
Arel::Nodes
|
149
|
+
def self.quoted *args
|
150
|
+
Arel::Nodes.build_quoted(*args)
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.rand
|
154
|
+
ArelExtensions::Nodes::Rand.new
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.rollup(*args)
|
158
|
+
Arel::Nodes::RollUp.new(args)
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.shorten s
|
162
|
+
Base64.urlsafe_encode64(Digest::MD5.new.digest(s)).tr('=', '').tr('-', '_')
|
163
|
+
end
|
164
|
+
|
165
|
+
# The TRUE pseudo literal.
|
166
|
+
def self.true
|
167
|
+
Arel::Nodes::Equality.new(1, 1)
|
112
168
|
end
|
113
169
|
|
114
170
|
def self.tuple *v
|
115
|
-
tmp = Arel
|
116
|
-
Arel
|
171
|
+
tmp = Arel.grouping(nil)
|
172
|
+
Arel.grouping v.map{|e| tmp.convert_to_node(e)}
|
173
|
+
end
|
174
|
+
|
175
|
+
# For instance
|
176
|
+
#
|
177
|
+
# ```
|
178
|
+
# Arel.when(at[field].is_null).then(0).else(1)
|
179
|
+
# ```
|
180
|
+
def self.when condition
|
181
|
+
ArelExtensions::Nodes::Case.new.when(condition)
|
117
182
|
end
|
118
183
|
end
|
119
184
|
|
@@ -123,6 +188,7 @@ class Arel::Attributes::Attribute
|
|
123
188
|
end
|
124
189
|
|
125
190
|
class Arel::Nodes::Function
|
191
|
+
include ArelExtensions::Aliases
|
126
192
|
include ArelExtensions::Math
|
127
193
|
include ArelExtensions::Comparators
|
128
194
|
include ArelExtensions::DateDuration
|
@@ -135,7 +201,7 @@ class Arel::Nodes::Function
|
|
135
201
|
alias_method(:old_as, :as) rescue nil
|
136
202
|
def as other
|
137
203
|
res = Arel::Nodes::As.new(self.clone, Arel.sql(other))
|
138
|
-
if Gem::Version.new(Arel::VERSION) >= Gem::Version.new(
|
204
|
+
if Gem::Version.new(Arel::VERSION) >= Gem::Version.new('9.0.0')
|
139
205
|
self.alias = Arel.sql(other)
|
140
206
|
end
|
141
207
|
res
|
@@ -143,13 +209,13 @@ class Arel::Nodes::Function
|
|
143
209
|
end
|
144
210
|
|
145
211
|
class Arel::Nodes::Grouping
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
212
|
+
include ArelExtensions::Math
|
213
|
+
include ArelExtensions::Comparators
|
214
|
+
include ArelExtensions::DateDuration
|
215
|
+
include ArelExtensions::MathFunctions
|
216
|
+
include ArelExtensions::NullFunctions
|
217
|
+
include ArelExtensions::StringFunctions
|
218
|
+
include ArelExtensions::Predications
|
153
219
|
end
|
154
220
|
|
155
221
|
class Arel::Nodes::Unary
|
@@ -158,6 +224,9 @@ class Arel::Nodes::Unary
|
|
158
224
|
include ArelExtensions::MathFunctions
|
159
225
|
include ArelExtensions::Comparators
|
160
226
|
include ArelExtensions::Predications
|
227
|
+
def eql? other
|
228
|
+
hash == other.hash
|
229
|
+
end
|
161
230
|
end
|
162
231
|
|
163
232
|
class Arel::Nodes::Binary
|
@@ -167,6 +236,9 @@ class Arel::Nodes::Binary
|
|
167
236
|
include ArelExtensions::Comparators
|
168
237
|
include ArelExtensions::BooleanFunctions
|
169
238
|
include ArelExtensions::Predications
|
239
|
+
def eql? other
|
240
|
+
hash == other.hash
|
241
|
+
end
|
170
242
|
end
|
171
243
|
|
172
244
|
class Arel::Nodes::Equality
|
@@ -183,6 +255,19 @@ end
|
|
183
255
|
class Arel::SelectManager
|
184
256
|
include ArelExtensions::SetFunctions
|
185
257
|
include ArelExtensions::Nodes
|
258
|
+
|
259
|
+
def as table_name
|
260
|
+
Arel::Nodes::TableAlias.new(self, table_name)
|
261
|
+
end
|
262
|
+
|
263
|
+
# Install an alias, if present.
|
264
|
+
def xas table_name
|
265
|
+
if table_name.present?
|
266
|
+
as table_name
|
267
|
+
else
|
268
|
+
self
|
269
|
+
end
|
270
|
+
end
|
186
271
|
end
|
187
272
|
|
188
273
|
class Arel::Nodes::As
|
@@ -191,8 +276,19 @@ end
|
|
191
276
|
|
192
277
|
class Arel::Table
|
193
278
|
alias_method(:old_alias, :alias) rescue nil
|
279
|
+
|
280
|
+
# activerecord 7.1 removed the alias. We might need to remove our dependency
|
281
|
+
# on the alias if it proves problematic.
|
282
|
+
if !self.respond_to?(:table_name)
|
283
|
+
alias :table_name :name
|
284
|
+
end
|
285
|
+
|
194
286
|
def alias(name = "#{self.name}_2")
|
195
|
-
name.
|
287
|
+
if name.present?
|
288
|
+
Arel::Nodes::TableAlias.new(self, name)
|
289
|
+
else
|
290
|
+
self
|
291
|
+
end
|
196
292
|
end
|
197
293
|
end
|
198
294
|
|
@@ -200,9 +296,50 @@ class Arel::Nodes::TableAlias
|
|
200
296
|
def method_missing(*args)
|
201
297
|
met = args.shift.to_sym
|
202
298
|
if self.relation.respond_to?(met)
|
203
|
-
self.relation.send(met,args)
|
299
|
+
self.relation.send(met, args)
|
204
300
|
else
|
205
|
-
super(met
|
301
|
+
super(met, *args)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
class Arel::Attributes::Attribute
|
308
|
+
def to_sql(engine = Arel::Table.engine)
|
309
|
+
collector = Arel::Collectors::SQLString.new
|
310
|
+
collector = engine.connection.visitor.accept self, collector
|
311
|
+
collector.value
|
312
|
+
end
|
313
|
+
|
314
|
+
def rollup
|
315
|
+
Arel::Nodes::RollUp.new([self])
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class Arel::Nodes::Node
|
320
|
+
def rollup
|
321
|
+
Arel::Nodes::RollUp.new([self])
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
require 'active_record'
|
326
|
+
if ActiveRecord.version >= Gem::Version.create('7.2')
|
327
|
+
class ActiveRecord::Relation::WhereClause
|
328
|
+
def except_predicates(columns)
|
329
|
+
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
330
|
+
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
331
|
+
|
332
|
+
predicates.reject do |node|
|
333
|
+
if !non_attrs.empty? && node.equality? && node.left.is_a?(Arel::Predications)
|
334
|
+
non_attrs.include?(node.left)
|
335
|
+
end || Arel.fetch_attribute(node) do |attr|
|
336
|
+
attrs.find { |v| v.eql? attr } || columns.include?(attr.name.to_s) # 👈 replces
|
337
|
+
# attrs.include?(attr) || columns.include?(attr.name.to_s) # 👈 this
|
338
|
+
#
|
339
|
+
# And that's because our attributes override `==`, so `attrs.include?(attr)` always
|
340
|
+
# passes because it returns an equality node.
|
341
|
+
end
|
342
|
+
end
|
206
343
|
end
|
207
344
|
end
|
208
345
|
end
|
data/test/arelx_test_helper.rb
CHANGED
@@ -6,8 +6,56 @@ require 'active_record'
|
|
6
6
|
|
7
7
|
require 'support/fake_record'
|
8
8
|
|
9
|
+
def colored(color, msg)
|
10
|
+
/^xterm|-256color$/.match?(ENV['TERM']) ? "\x1b[#{color}m#{msg}\x1b[89m\x1b[0m" : "#{msg}"
|
11
|
+
end
|
12
|
+
|
13
|
+
YELLOW = '33'
|
14
|
+
|
15
|
+
# Load gems specific to databases.
|
16
|
+
#
|
17
|
+
# NOTE:
|
18
|
+
# It's strongly advised to test each database on its own. Loading multiple
|
19
|
+
# backend gems leads to undefined behavior according to tests; the backend
|
20
|
+
# might not recognize the correct DB visitor and will fallback to `ToSQL`
|
21
|
+
# and screw all tests.
|
22
|
+
#
|
23
|
+
# The issue also seems to be related to arel version: at some point, arel
|
24
|
+
# dropped its wide support for DBs and kept Postgres, MySQL and SQLite.
|
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.
|
30
|
+
db_and_gem =
|
31
|
+
if RUBY_PLATFORM == 'java'
|
32
|
+
{
|
33
|
+
'oracle' => ['activerecord-oracle_enhanced-adapter'],
|
34
|
+
'mssql' => ['jdbc/mssql', 'activerecord-jdbcsqlserver-adapter'],
|
35
|
+
}
|
36
|
+
else
|
37
|
+
{
|
38
|
+
'oracle' => ['activerecord-oracle_enhanced-adapter'],
|
39
|
+
'mssql' => ['activerecord-sqlserver-adapter'],
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
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
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
load_lib(db_and_gem[ENV['DB']])
|
57
|
+
|
9
58
|
require 'arel_extensions'
|
10
|
-
Arel::Table.engine = FakeRecord::Base.new
|
11
59
|
|
12
60
|
$arel_silence_type_casting_deprecation = true
|
13
61
|
|
data/test/database.yml
CHANGED
@@ -8,24 +8,30 @@ jdbc-sqlite:
|
|
8
8
|
timeout: 500
|
9
9
|
mysql:
|
10
10
|
adapter: mysql2
|
11
|
-
database:
|
12
|
-
username:
|
11
|
+
database: arelx_test
|
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
|
-
database:
|
19
|
-
username:
|
18
|
+
database: arelx_test
|
19
|
+
username: root
|
20
20
|
encoding: utf8
|
21
21
|
postgresql:
|
22
22
|
adapter: postgresql
|
23
|
-
database:
|
23
|
+
database: arelx_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
|
-
database:
|
30
|
+
database: arelx_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
|
@@ -39,7 +45,7 @@ jdbc-oracle:
|
|
39
45
|
ibm_db:
|
40
46
|
adapter: ibm_db
|
41
47
|
username: travis
|
42
|
-
database:
|
48
|
+
database: arelx_test
|
43
49
|
mssql:
|
44
50
|
adapter: sqlserver
|
45
51
|
host: localhost
|