arel_extensions 1.7.0 → 2.0.0.rc3
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 +2 -1
- data/.gitignore +6 -8
- data/.rubocop.yml +4 -194
- data/.travis/oracle/download.js +152 -0
- data/.travis/oracle/download.sh +30 -0
- data/.travis/oracle/download_ojdbc.js +116 -0
- data/.travis/oracle/install.sh +34 -0
- data/.travis/setup_accounts.sh +9 -0
- data/.travis/sqlite3/extension-functions.sh +6 -0
- data/.travis.yml +223 -0
- data/Gemfile +28 -2
- data/README.md +89 -265
- data/Rakefile +30 -50
- data/TODO +1 -0
- data/appveyor.yml +22 -60
- data/arel_extensions.gemspec +17 -14
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +20 -0
- data/gemfiles/rails4.gemfile +29 -0
- data/gemfiles/rails5_0.gemfile +29 -0
- data/gemfiles/rails5_1_4.gemfile +17 -19
- data/gemfiles/rails5_2.gemfile +17 -26
- data/init/mssql.sql +4 -4
- data/init/mysql.sql +38 -38
- data/init/oracle.sql +0 -0
- data/init/postgresql.sql +25 -24
- data/init/sqlite.sql +0 -0
- data/lib/arel_extensions/attributes.rb +3 -9
- data/lib/arel_extensions/boolean_functions.rb +16 -57
- data/lib/arel_extensions/common_sql_functions.rb +20 -21
- data/lib/arel_extensions/comparators.rb +28 -31
- data/lib/arel_extensions/date_duration.rb +13 -19
- data/lib/arel_extensions/insert_manager.rb +15 -22
- data/lib/arel_extensions/math.rb +70 -68
- data/lib/arel_extensions/math_functions.rb +52 -57
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +5 -6
- data/lib/arel_extensions/nodes/case.rb +27 -31
- data/lib/arel_extensions/nodes/cast.rb +12 -12
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/coalesce.rb +5 -4
- data/lib/arel_extensions/nodes/collate.rb +10 -9
- data/lib/arel_extensions/nodes/concat.rb +22 -13
- data/lib/arel_extensions/nodes/date_diff.rb +70 -77
- data/lib/arel_extensions/nodes/duration.rb +5 -2
- data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
- data/lib/arel_extensions/nodes/floor.rb +1 -1
- data/lib/arel_extensions/nodes/format.rb +8 -35
- data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
- data/lib/arel_extensions/nodes/function.rb +39 -50
- data/lib/arel_extensions/nodes/is_null.rb +0 -2
- data/lib/arel_extensions/nodes/json.rb +47 -72
- data/lib/arel_extensions/nodes/length.rb +0 -5
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
- data/lib/arel_extensions/nodes/locate.rb +3 -2
- data/lib/arel_extensions/nodes/log10.rb +2 -1
- data/lib/arel_extensions/nodes/matches.rb +8 -6
- data/lib/arel_extensions/nodes/md5.rb +1 -0
- data/lib/arel_extensions/nodes/power.rb +5 -5
- data/lib/arel_extensions/nodes/rand.rb +3 -2
- data/lib/arel_extensions/nodes/repeat.rb +6 -4
- data/lib/arel_extensions/nodes/replace.rb +8 -16
- data/lib/arel_extensions/nodes/round.rb +7 -6
- data/lib/arel_extensions/nodes/soundex.rb +15 -15
- data/lib/arel_extensions/nodes/std.rb +21 -18
- data/lib/arel_extensions/nodes/substring.rb +16 -58
- data/lib/arel_extensions/nodes/then.rb +2 -2
- data/lib/arel_extensions/nodes/trim.rb +7 -5
- data/lib/arel_extensions/nodes/union.rb +9 -6
- data/lib/arel_extensions/nodes/union_all.rb +8 -5
- data/lib/arel_extensions/nodes/wday.rb +6 -2
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +6 -18
- data/lib/arel_extensions/predications.rb +49 -54
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +7 -5
- data/lib/arel_extensions/string_functions.rb +55 -110
- data/lib/arel_extensions/tasks.rb +6 -6
- data/lib/arel_extensions/version.rb +1 -3
- data/lib/arel_extensions/visitors/ibm_db.rb +36 -29
- data/lib/arel_extensions/visitors/mssql.rb +248 -493
- data/lib/arel_extensions/visitors/mysql.rb +244 -420
- data/lib/arel_extensions/visitors/oracle.rb +258 -311
- data/lib/arel_extensions/visitors/oracle12.rb +34 -20
- data/lib/arel_extensions/visitors/postgresql.rb +239 -350
- data/lib/arel_extensions/visitors/sqlite.rb +169 -191
- data/lib/arel_extensions/visitors/to_sql.rb +299 -371
- data/lib/arel_extensions/visitors.rb +62 -83
- data/lib/arel_extensions.rb +32 -243
- data/test/database.yml +10 -20
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +120 -123
- data/test/support/fake_record.rb +3 -11
- data/test/test_comparators.rb +17 -14
- data/test/visitors/test_bulk_insert_oracle.rb +12 -12
- data/test/visitors/test_bulk_insert_sqlite.rb +14 -13
- data/test/visitors/test_bulk_insert_to_sql.rb +13 -11
- data/test/visitors/test_oracle.rb +55 -55
- data/test/visitors/test_to_sql.rb +226 -419
- data/test/with_ar/all_agnostic_test.rb +375 -912
- data/test/with_ar/insert_agnostic_test.rb +22 -28
- data/test/with_ar/test_bulk_sqlite.rb +17 -18
- data/test/with_ar/test_math_sqlite.rb +27 -27
- data/test/with_ar/test_string_mysql.rb +34 -32
- data/test/with_ar/test_string_sqlite.rb +35 -31
- metadata +64 -50
- data/.github/workflows/publish.yml +0 -30
- data/.github/workflows/release.yml +0 -30
- data/.github/workflows/ruby.yml +0 -452
- data/CONTRIBUTING.md +0 -102
- data/Makefile +0 -48
- data/NEWS.md +0 -131
- data/bin/build +0 -15
- data/bin/publish +0 -8
- data/dev/arelx.dockerfile +0 -41
- data/dev/compose.yaml +0 -69
- data/dev/postgres.dockerfile +0 -5
- data/dev/rbenv +0 -189
- data/gemfiles/rails5.gemfile +0 -36
- data/gemfiles/rails6.gemfile +0 -40
- data/gemfiles/rails6_1.gemfile +0 -48
- data/gemfiles/rails7.gemfile +0 -48
- data/gemfiles/rails7_1.gemfile +0 -48
- data/gemfiles/rails7_2.gemfile +0 -47
- data/gemfiles/rails8.gemfile +0 -40
- data/gemfiles/rails8_1.gemfile +0 -41
- data/gemspecs/arel_extensions-v1.gemspec +0 -25
- data/gemspecs/arel_extensions-v2.gemspec +0 -25
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/aliases.rb +0 -14
- data/lib/arel_extensions/constants.rb +0 -13
- data/lib/arel_extensions/helpers.rb +0 -61
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/byte_size.rb +0 -11
- data/lib/arel_extensions/nodes/char_length.rb +0 -11
- data/lib/arel_extensions/nodes/formatted_date.rb +0 -42
- data/lib/arel_extensions/nodes/rollup.rb +0 -36
- data/lib/arel_extensions/nodes/select.rb +0 -10
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/lib/arel_extensions/warning.rb +0 -42
- data/test/arelx_test_helper.rb +0 -94
- data/test/config_loader.rb +0 -9
- data/version_v1.rb +0 -5
- data/version_v2.rb +0 -5
|
@@ -1,102 +1,81 @@
|
|
|
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
|
-
&& ArelExtensions::AREL_VERSION < ArelExtensions::V10 \
|
|
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
|
-
|
|
26
|
-
require 'arel_extensions/visitors/convert_format'
|
|
27
1
|
require 'arel_extensions/visitors/to_sql'
|
|
28
2
|
require 'arel_extensions/visitors/mysql'
|
|
29
|
-
require 'arel_extensions/visitors/
|
|
3
|
+
require 'arel_extensions/visitors/oracle'
|
|
4
|
+
require 'arel_extensions/visitors/oracle12'
|
|
30
5
|
require 'arel_extensions/visitors/postgresql'
|
|
31
6
|
require 'arel_extensions/visitors/sqlite'
|
|
7
|
+
require 'arel_extensions/visitors/mssql'
|
|
32
8
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
require 'arel_extensions/visitors/oracle12'
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
if defined?(Arel::Visitors::SQLServer)
|
|
39
|
-
class Arel::Visitors::SQLServer
|
|
40
|
-
include ArelExtensions::Visitors::MSSQL
|
|
41
|
-
end
|
|
42
|
-
end
|
|
9
|
+
Arel::Visitors::MSSQL.class_eval do
|
|
10
|
+
include ArelExtensions::Visitors::MSSQL
|
|
43
11
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
12
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
|
13
|
+
def visit_Arel_Nodes_As o, collector
|
|
14
|
+
if o.left.is_a?(Arel::Nodes::Binary)
|
|
15
|
+
collector << '('
|
|
16
|
+
collector = visit o.left, collector
|
|
17
|
+
collector << ')'
|
|
18
|
+
else
|
|
19
|
+
collector = visit o.left, collector
|
|
48
20
|
end
|
|
21
|
+
collector << " AS ["
|
|
22
|
+
collector = visit o.right, collector
|
|
23
|
+
collector << "]"
|
|
24
|
+
collector
|
|
49
25
|
end
|
|
50
|
-
end
|
|
51
26
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def visit_Arel_Nodes_SelectStatement(o, collector)
|
|
58
|
-
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
|
59
|
-
o = o.dup
|
|
60
|
-
o.orders = []
|
|
61
|
-
end
|
|
62
|
-
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
|
27
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
|
28
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
|
29
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
|
30
|
+
o = o.dup
|
|
31
|
+
o.orders = []
|
|
63
32
|
end
|
|
33
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
|
64
34
|
end
|
|
65
35
|
end
|
|
66
36
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
37
|
+
begin
|
|
38
|
+
require 'arel_sqlserver'
|
|
39
|
+
if Arel::VERSION.to_i == 6
|
|
40
|
+
if Arel::Visitors::VISITORS['sqlserver'] && Arel::Visitors::VISITORS['sqlserver'] != Arel::Visitors::MSSQL
|
|
41
|
+
Arel::Visitors::VISITORS['sqlserver'].class_eval do
|
|
42
|
+
include ArelExtensions::Visitors::MSSQL
|
|
70
43
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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.
|
|
44
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
|
45
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
|
46
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
|
47
|
+
o = o.dup
|
|
48
|
+
o.orders = []
|
|
49
|
+
end
|
|
50
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
|
51
|
+
end
|
|
92
52
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
53
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
|
54
|
+
def visit_Arel_Nodes_As o, collector
|
|
55
|
+
if o.left.is_a?(Arel::Nodes::Binary)
|
|
56
|
+
collector << '('
|
|
57
|
+
collector = visit o.left, collector
|
|
58
|
+
collector << ')'
|
|
59
|
+
else
|
|
60
|
+
collector = visit o.left, collector
|
|
61
|
+
end
|
|
62
|
+
collector << " AS ["
|
|
63
|
+
collector = visit o.right, collector
|
|
64
|
+
collector << "]"
|
|
65
|
+
collector
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
alias_method :old_primary_Key_From_Table, :primary_Key_From_Table
|
|
69
|
+
def primary_Key_From_Table t
|
|
70
|
+
return unless t
|
|
71
|
+
column_name = @connection.schema_cache.primary_keys(t.name) ||
|
|
72
|
+
@connection.schema_cache.columns_hash(t.name).first.try(:second).try(:name)
|
|
73
|
+
column_name ? t[column_name] : nil
|
|
74
|
+
end
|
|
98
75
|
end
|
|
99
|
-
old_visit_Arel_Nodes_SelectStatement(o, collector)
|
|
100
76
|
end
|
|
101
77
|
end
|
|
78
|
+
rescue LoadError
|
|
79
|
+
rescue => e
|
|
80
|
+
e
|
|
102
81
|
end
|
data/lib/arel_extensions.rb
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
require 'arel'
|
|
4
|
-
require 'arel_extensions/constants'
|
|
5
|
-
require 'base64'
|
|
6
2
|
|
|
7
3
|
require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
|
8
4
|
|
|
@@ -11,54 +7,41 @@ require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
|
|
11
7
|
# Count|NamedFunction < Function < Arel::Nodes::Node
|
|
12
8
|
|
|
13
9
|
# pure Arel internals improvements
|
|
14
|
-
|
|
10
|
+
Arel::Nodes::Binary.class_eval do
|
|
15
11
|
include Arel::AliasPredication
|
|
16
12
|
include Arel::Expressions
|
|
17
13
|
end
|
|
18
14
|
|
|
19
|
-
|
|
15
|
+
Arel::Nodes::Casted.class_eval do
|
|
20
16
|
include Arel::AliasPredication
|
|
21
|
-
|
|
22
|
-
# They forget to define hash.
|
|
23
|
-
if ArelExtensions::AREL_VERSION < ArelExtensions::V10
|
|
24
|
-
def hash
|
|
25
|
-
[self.class, val, attribute].hash
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
17
|
end
|
|
29
18
|
|
|
30
|
-
|
|
19
|
+
Arel::Nodes::Unary.class_eval do
|
|
31
20
|
include Arel::Math
|
|
32
21
|
include Arel::AliasPredication
|
|
33
22
|
include Arel::Expressions
|
|
34
23
|
end
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
Arel::Nodes::Grouping.class_eval do
|
|
26
|
+
include Arel::Math
|
|
27
|
+
include Arel::AliasPredication
|
|
37
28
|
include Arel::OrderPredications
|
|
29
|
+
include Arel::Expressions
|
|
38
30
|
end
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
def eql?(other)
|
|
42
|
-
hash.eql? other.hash
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
class Arel::Nodes::Function
|
|
32
|
+
Arel::Nodes::Function.class_eval do
|
|
47
33
|
include Arel::Math
|
|
48
34
|
include Arel::Expressions
|
|
49
35
|
end
|
|
50
36
|
|
|
51
|
-
if
|
|
52
|
-
|
|
37
|
+
if Arel::VERSION >= "7.1.0"
|
|
38
|
+
Arel::Nodes::Case.class_eval do
|
|
53
39
|
include Arel::Math
|
|
54
40
|
include Arel::Expressions
|
|
55
41
|
end
|
|
56
42
|
end
|
|
57
43
|
|
|
58
|
-
require 'arel_extensions/warning'
|
|
59
|
-
require 'arel_extensions/helpers'
|
|
60
44
|
require 'arel_extensions/version'
|
|
61
|
-
require 'arel_extensions/aliases'
|
|
62
45
|
require 'arel_extensions/attributes'
|
|
63
46
|
require 'arel_extensions/visitors'
|
|
64
47
|
require 'arel_extensions/nodes'
|
|
@@ -82,117 +65,42 @@ require 'arel_extensions/nodes/case'
|
|
|
82
65
|
require 'arel_extensions/nodes/soundex'
|
|
83
66
|
require 'arel_extensions/nodes/cast'
|
|
84
67
|
require 'arel_extensions/nodes/json'
|
|
85
|
-
require 'arel_extensions/nodes/rollup'
|
|
86
|
-
require 'arel_extensions/nodes/select'
|
|
87
68
|
|
|
88
|
-
# It seems like the code in lib/arel_extensions/visitors.rb that is supposed
|
|
89
|
-
# to inject ArelExtension is not enough. Different versions of the sqlserver
|
|
90
|
-
# adapter behave differently. It doesn't always proc, so we added this for
|
|
91
|
-
# coverage.
|
|
92
|
-
if defined?(Arel::Visitors::SQLServer)
|
|
93
|
-
Arel::Visitors.const_set(:MSSQL, Arel::Visitors::SQLServer)
|
|
94
|
-
require 'arel_extensions/visitors/mssql'
|
|
95
|
-
class Arel::Visitors::SQLServer
|
|
96
|
-
include ArelExtensions::Visitors::MSSQL
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
69
|
|
|
100
|
-
module Arel
|
|
101
|
-
def self.column_of(table_name, column_name)
|
|
102
|
-
ArelExtensions.column_of(table_name, column_name)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def self.duration(s, expr)
|
|
106
|
-
ArelExtensions::Nodes::Duration.new("#{s}i", expr)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# The FALSE pseudo literal.
|
|
110
|
-
def self.false
|
|
111
|
-
Arel::Nodes::Equality.new(1, 0)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def self.grouping(*v)
|
|
115
|
-
Arel::Nodes::Grouping.new(*v)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def self.json(*expr)
|
|
119
|
-
ArelExtensions::Nodes::Json.new(
|
|
120
|
-
if expr.length == 1
|
|
121
|
-
expr.first
|
|
122
|
-
else
|
|
123
|
-
expr
|
|
124
|
-
end
|
|
125
|
-
)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def self.json_true
|
|
129
|
-
res = Arel.grouping(Arel.quoted('true'))
|
|
130
|
-
res.instance_eval {
|
|
131
|
-
def return_type
|
|
132
|
-
:boolean
|
|
133
|
-
end
|
|
134
|
-
}
|
|
135
|
-
res
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def self.json_false
|
|
139
|
-
res = Arel.grouping(Arel.quoted('false'))
|
|
140
|
-
res.instance_eval {
|
|
141
|
-
def return_type
|
|
142
|
-
:boolean
|
|
143
|
-
end
|
|
144
|
-
}
|
|
145
|
-
res
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
# The NULL literal.
|
|
149
|
-
def self.null
|
|
150
|
-
Arel.quoted(nil)
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def self.quoted(*args)
|
|
154
|
-
Arel::Nodes.build_quoted(*args)
|
|
155
|
-
end
|
|
156
70
|
|
|
71
|
+
module Arel
|
|
157
72
|
def self.rand
|
|
158
73
|
ArelExtensions::Nodes::Rand.new
|
|
159
74
|
end
|
|
160
75
|
|
|
161
|
-
def self.
|
|
162
|
-
Arel::Nodes::RollUp.new(args)
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def self.shorten(s)
|
|
76
|
+
def self.shorten s
|
|
166
77
|
Base64.urlsafe_encode64(Digest::MD5.new.digest(s)).tr('=', '').tr('-', '_')
|
|
167
78
|
end
|
|
168
79
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
80
|
+
def self.json *expr
|
|
81
|
+
if expr.length == 1
|
|
82
|
+
ArelExtensions::Nodes::Json.new(expr.first)
|
|
83
|
+
else
|
|
84
|
+
ArelExtensions::Nodes::Json.new(expr)
|
|
85
|
+
end
|
|
172
86
|
end
|
|
173
87
|
|
|
174
|
-
def self.
|
|
175
|
-
|
|
176
|
-
Arel.grouping(v.map { |e| tmp.convert_to_node(e) })
|
|
88
|
+
def self.when condition
|
|
89
|
+
ArelExtensions::Nodes::Case.new.when(condition)
|
|
177
90
|
end
|
|
178
91
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# ```
|
|
182
|
-
# Arel.when(at[field].is_null).then(0).else(1)
|
|
183
|
-
# ```
|
|
184
|
-
def self.when(condition)
|
|
185
|
-
ArelExtensions::Nodes::Case.new.when(condition)
|
|
92
|
+
def self.duration s, expr
|
|
93
|
+
ArelExtensions::Nodes::Duration.new(s.to_s+'i',expr)
|
|
186
94
|
end
|
|
95
|
+
|
|
187
96
|
end
|
|
188
97
|
|
|
189
|
-
|
|
98
|
+
Arel::Attributes::Attribute.class_eval do
|
|
190
99
|
include Arel::Math
|
|
191
100
|
include ArelExtensions::Attributes
|
|
192
101
|
end
|
|
193
102
|
|
|
194
|
-
|
|
195
|
-
include ArelExtensions::Aliases
|
|
103
|
+
Arel::Nodes::Function.class_eval do
|
|
196
104
|
include ArelExtensions::Math
|
|
197
105
|
include ArelExtensions::Comparators
|
|
198
106
|
include ArelExtensions::DateDuration
|
|
@@ -201,163 +109,44 @@ class Arel::Nodes::Function
|
|
|
201
109
|
include ArelExtensions::BooleanFunctions
|
|
202
110
|
include ArelExtensions::NullFunctions
|
|
203
111
|
include ArelExtensions::Predications
|
|
204
|
-
|
|
205
|
-
if ArelExtensions::ACTIVE_RECORD_VERSION >= ArelExtensions::V8_1
|
|
206
|
-
attr_accessor :alias
|
|
207
|
-
alias old_initialize initialize
|
|
208
|
-
|
|
209
|
-
def initialize(expr, aliaz = nil)
|
|
210
|
-
old_initialize(expr)
|
|
211
|
-
self.alias = aliaz
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
alias old_as as rescue nil
|
|
216
|
-
def as(other)
|
|
217
|
-
res = Arel::Nodes::As.new(clone, Arel.sql(other))
|
|
218
|
-
self.alias = Arel.sql(other)
|
|
219
|
-
res
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
class Arel::Nodes::Grouping
|
|
224
|
-
include ArelExtensions::Math
|
|
225
|
-
include ArelExtensions::Comparators
|
|
226
|
-
include ArelExtensions::DateDuration
|
|
227
|
-
include ArelExtensions::MathFunctions
|
|
228
|
-
include ArelExtensions::NullFunctions
|
|
229
|
-
include ArelExtensions::StringFunctions
|
|
230
|
-
include ArelExtensions::Predications
|
|
231
112
|
end
|
|
232
113
|
|
|
233
|
-
|
|
114
|
+
Arel::Nodes::Unary.class_eval do
|
|
234
115
|
include ArelExtensions::Math
|
|
235
116
|
include ArelExtensions::Attributes
|
|
236
117
|
include ArelExtensions::MathFunctions
|
|
237
118
|
include ArelExtensions::Comparators
|
|
238
119
|
include ArelExtensions::Predications
|
|
239
|
-
|
|
240
|
-
def eql?(other)
|
|
241
|
-
hash == other.hash
|
|
242
|
-
end
|
|
243
120
|
end
|
|
244
121
|
|
|
245
|
-
|
|
122
|
+
Arel::Nodes::Binary.class_eval do
|
|
246
123
|
include ArelExtensions::Math
|
|
247
124
|
include ArelExtensions::Attributes
|
|
248
125
|
include ArelExtensions::MathFunctions
|
|
249
126
|
include ArelExtensions::Comparators
|
|
250
127
|
include ArelExtensions::BooleanFunctions
|
|
251
128
|
include ArelExtensions::Predications
|
|
252
|
-
|
|
253
|
-
def eql?(other)
|
|
254
|
-
hash == other.hash
|
|
255
|
-
end
|
|
256
129
|
end
|
|
257
130
|
|
|
258
|
-
|
|
131
|
+
Arel::Nodes::Equality.class_eval do
|
|
259
132
|
include ArelExtensions::Comparators
|
|
260
133
|
include ArelExtensions::DateDuration
|
|
261
134
|
include ArelExtensions::MathFunctions
|
|
262
135
|
include ArelExtensions::StringFunctions
|
|
263
136
|
end
|
|
264
137
|
|
|
265
|
-
|
|
138
|
+
|
|
139
|
+
Arel::InsertManager.class_eval do
|
|
266
140
|
include ArelExtensions::InsertManager
|
|
267
141
|
end
|
|
268
142
|
|
|
269
|
-
|
|
143
|
+
Arel::SelectManager.class_eval do
|
|
270
144
|
include ArelExtensions::SetFunctions
|
|
271
145
|
include ArelExtensions::Nodes
|
|
272
|
-
|
|
273
|
-
remove_method(:as) if method_defined?(:as)
|
|
274
|
-
def as(table_name)
|
|
275
|
-
Arel::Nodes::TableAlias.new(self, table_name)
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
# Install an alias, if present.
|
|
279
|
-
def xas(table_name)
|
|
280
|
-
if table_name.present?
|
|
281
|
-
as table_name
|
|
282
|
-
else
|
|
283
|
-
self
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
146
|
end
|
|
287
147
|
|
|
288
|
-
|
|
148
|
+
Arel::Nodes::As.class_eval do
|
|
289
149
|
include ArelExtensions::Nodes
|
|
290
150
|
end
|
|
291
151
|
|
|
292
|
-
class Arel::Table
|
|
293
|
-
alias old_alias alias rescue nil
|
|
294
|
-
|
|
295
|
-
# activerecord 7.1 removed the alias. We might need to remove our dependency
|
|
296
|
-
# on the alias if it proves problematic.
|
|
297
|
-
if !respond_to?(:table_name)
|
|
298
|
-
alias table_name name
|
|
299
|
-
end
|
|
300
152
|
|
|
301
|
-
def alias(name = "#{self.name}_2")
|
|
302
|
-
if name.present?
|
|
303
|
-
Arel::Nodes::TableAlias.new(self, name)
|
|
304
|
-
else
|
|
305
|
-
self
|
|
306
|
-
end
|
|
307
|
-
end
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
class Arel::Nodes::TableAlias
|
|
311
|
-
def method_missing(*args)
|
|
312
|
-
met = args.shift.to_sym
|
|
313
|
-
if relation.respond_to?(met)
|
|
314
|
-
relation.send(met, args)
|
|
315
|
-
else
|
|
316
|
-
super(met, *args)
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
321
|
-
relation.respond_to?(method_name) || super
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
class Arel::Attributes::Attribute
|
|
326
|
-
def to_sql(engine = Arel::Table.engine)
|
|
327
|
-
collector = Arel::Collectors::SQLString.new
|
|
328
|
-
collector = engine.connection.visitor.accept self, collector
|
|
329
|
-
collector.value
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
def rollup
|
|
333
|
-
Arel::Nodes::RollUp.new([self])
|
|
334
|
-
end
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
class Arel::Nodes::Node
|
|
338
|
-
def rollup
|
|
339
|
-
Arel::Nodes::RollUp.new([self])
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
require 'active_record'
|
|
344
|
-
if ArelExtensions::ACTIVE_RECORD_VERSION >= ArelExtensions::V7_2
|
|
345
|
-
class ActiveRecord::Relation::WhereClause
|
|
346
|
-
def except_predicates(columns)
|
|
347
|
-
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
|
348
|
-
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
349
|
-
|
|
350
|
-
predicates.reject do |node|
|
|
351
|
-
if !non_attrs.empty? && node.equality? && node.left.is_a?(Arel::Predications)
|
|
352
|
-
non_attrs.include?(node.left)
|
|
353
|
-
end || Arel.fetch_attribute(node) do |attr|
|
|
354
|
-
attrs.find { |v| v.eql? attr } || columns.include?(attr.name.to_s) # 👈 replces
|
|
355
|
-
# attrs.include?(attr) || columns.include?(attr.name.to_s) # 👈 this
|
|
356
|
-
#
|
|
357
|
-
# And that's because our attributes override `==`, so `attrs.include?(attr)` always
|
|
358
|
-
# passes because it returns an equality node.
|
|
359
|
-
end
|
|
360
|
-
end
|
|
361
|
-
end
|
|
362
|
-
end
|
|
363
|
-
end
|
data/test/database.yml
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# Updated to use ENV vars mapped in compose.yml
|
|
2
1
|
sqlite:
|
|
3
2
|
adapter: sqlite3
|
|
4
3
|
database: ":memory:"
|
|
@@ -9,31 +8,22 @@ jdbc-sqlite:
|
|
|
9
8
|
timeout: 500
|
|
10
9
|
mysql:
|
|
11
10
|
adapter: mysql2
|
|
12
|
-
database:
|
|
13
|
-
username:
|
|
14
|
-
|
|
15
|
-
port: 3306
|
|
16
|
-
encoding: utf8mb4
|
|
11
|
+
database: arext_test
|
|
12
|
+
username: travis
|
|
13
|
+
encoding: utf8
|
|
17
14
|
jdbc-mysql:
|
|
18
15
|
adapter: jdbcmysql
|
|
19
|
-
database:
|
|
20
|
-
username:
|
|
21
|
-
encoding:
|
|
22
|
-
host: <%= ENV.fetch('MYSQL_HOST', '127.0.0.1') %>
|
|
16
|
+
database: arext_test
|
|
17
|
+
username: travis
|
|
18
|
+
encoding: utf8
|
|
23
19
|
postgresql:
|
|
24
20
|
adapter: postgresql
|
|
25
|
-
database:
|
|
21
|
+
database: arext_test
|
|
26
22
|
username: postgres
|
|
27
|
-
password: secret
|
|
28
|
-
host: <%= ENV.fetch('POSTGRES_HOST', '127.0.0.1') %>
|
|
29
|
-
port: 5432
|
|
30
23
|
jdbc-postgresql:
|
|
31
24
|
adapter: jdbcpostgresql
|
|
32
|
-
database:
|
|
25
|
+
database: arext_test
|
|
33
26
|
username: postgres
|
|
34
|
-
password: secret
|
|
35
|
-
host: <%= ENV.fetch('POSTGRES_HOST', '127.0.0.1') %>
|
|
36
|
-
port: 5432
|
|
37
27
|
oracle:
|
|
38
28
|
adapter: oracle_enhanced
|
|
39
29
|
database: xe
|
|
@@ -47,10 +37,10 @@ jdbc-oracle:
|
|
|
47
37
|
ibm_db:
|
|
48
38
|
adapter: ibm_db
|
|
49
39
|
username: travis
|
|
50
|
-
database:
|
|
40
|
+
database: arext_test
|
|
51
41
|
mssql:
|
|
52
42
|
adapter: sqlserver
|
|
53
|
-
host:
|
|
43
|
+
host: localhost
|
|
54
44
|
database: master
|
|
55
45
|
username: sa
|
|
56
46
|
password: Password12!
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'minitest/autorun'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'arel'
|
|
5
|
+
require 'active_record'
|
|
6
|
+
|
|
7
|
+
require 'arel_extensions'
|
|
8
|
+
|
|
9
|
+
require 'support/fake_record'
|
|
10
|
+
Arel::Table.engine = FakeRecord::Base.new
|
|
11
|
+
|
|
12
|
+
$arel_silence_type_casting_deprecation = true
|
|
13
|
+
|
|
14
|
+
class Object
|
|
15
|
+
def must_be_like other
|
|
16
|
+
gsub(/\s+/, ' ').strip.must_equal other.gsub(/\s+/, ' ').strip
|
|
17
|
+
end
|
|
18
|
+
end
|