arel_extensions 1.6.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 -7
- data/.rubocop.yml +3 -67
- 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 +91 -258
- data/Rakefile +30 -48
- data/TODO +1 -0
- data/appveyor.yml +22 -60
- data/arel_extensions.gemspec +14 -13
- 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 +14 -14
- data/gemfiles/rails5_2.gemfile +14 -16
- 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 -7
- data/lib/arel_extensions/boolean_functions.rb +14 -53
- data/lib/arel_extensions/common_sql_functions.rb +17 -16
- data/lib/arel_extensions/comparators.rb +28 -29
- data/lib/arel_extensions/date_duration.rb +13 -17
- data/lib/arel_extensions/insert_manager.rb +15 -18
- data/lib/arel_extensions/math.rb +53 -55
- data/lib/arel_extensions/math_functions.rb +39 -46
- data/lib/arel_extensions/nodes/abs.rb +1 -0
- data/lib/arel_extensions/nodes/blank.rb +2 -1
- data/lib/arel_extensions/nodes/case.rb +19 -20
- data/lib/arel_extensions/nodes/cast.rb +8 -10
- data/lib/arel_extensions/nodes/ceil.rb +1 -1
- data/lib/arel_extensions/nodes/coalesce.rb +4 -3
- data/lib/arel_extensions/nodes/collate.rb +10 -9
- data/lib/arel_extensions/nodes/concat.rb +18 -9
- data/lib/arel_extensions/nodes/date_diff.rb +26 -42
- data/lib/arel_extensions/nodes/duration.rb +3 -0
- 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 +37 -46
- data/lib/arel_extensions/nodes/is_null.rb +0 -0
- data/lib/arel_extensions/nodes/json.rb +39 -52
- data/lib/arel_extensions/nodes/length.rb +0 -5
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +1 -1
- data/lib/arel_extensions/nodes/locate.rb +2 -1
- 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 +1 -0
- data/lib/arel_extensions/nodes/repeat.rb +5 -3
- data/lib/arel_extensions/nodes/replace.rb +8 -16
- data/lib/arel_extensions/nodes/round.rb +6 -5
- 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 -8
- data/lib/arel_extensions/nodes/then.rb +1 -1
- data/lib/arel_extensions/nodes/trim.rb +6 -4
- data/lib/arel_extensions/nodes/union.rb +8 -5
- data/lib/arel_extensions/nodes/union_all.rb +7 -4
- data/lib/arel_extensions/nodes/wday.rb +4 -0
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +5 -19
- data/lib/arel_extensions/predications.rb +44 -45
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +7 -5
- data/lib/arel_extensions/string_functions.rb +35 -91
- data/lib/arel_extensions/tasks.rb +6 -6
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +31 -24
- data/lib/arel_extensions/visitors/mssql.rb +194 -440
- data/lib/arel_extensions/visitors/mysql.rb +212 -368
- data/lib/arel_extensions/visitors/oracle.rb +179 -236
- data/lib/arel_extensions/visitors/oracle12.rb +31 -18
- data/lib/arel_extensions/visitors/postgresql.rb +173 -271
- data/lib/arel_extensions/visitors/sqlite.rb +127 -157
- data/lib/arel_extensions/visitors/to_sql.rb +238 -300
- data/lib/arel_extensions/visitors.rb +62 -83
- data/lib/arel_extensions.rb +31 -235
- data/test/database.yml +10 -20
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +118 -121
- 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 +370 -773
- 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 +38 -52
- 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 -18
- data/NEWS.md +0 -116
- 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 -29
- data/gemfiles/rails6.gemfile +0 -34
- data/gemfiles/rails6_1.gemfile +0 -42
- data/gemfiles/rails7.gemfile +0 -42
- data/gemfiles/rails7_1.gemfile +0 -41
- data/gemfiles/rails7_2.gemfile +0 -41
- data/gemfiles/rails8.gemfile +0 -40
- data/gemfiles/rails8_1.gemfile +0 -41
- data/gemspecs/arel_extensions-v1.gemspec +0 -27
- data/gemspecs/arel_extensions-v2.gemspec +0 -27
- 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 -3
- data/version_v2.rb +0 -3
|
@@ -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,6 +1,4 @@
|
|
|
1
1
|
require 'arel'
|
|
2
|
-
require 'arel_extensions/constants'
|
|
3
|
-
require 'base64'
|
|
4
2
|
|
|
5
3
|
require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
|
6
4
|
|
|
@@ -9,54 +7,41 @@ require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
|
|
9
7
|
# Count|NamedFunction < Function < Arel::Nodes::Node
|
|
10
8
|
|
|
11
9
|
# pure Arel internals improvements
|
|
12
|
-
|
|
10
|
+
Arel::Nodes::Binary.class_eval do
|
|
13
11
|
include Arel::AliasPredication
|
|
14
12
|
include Arel::Expressions
|
|
15
13
|
end
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
Arel::Nodes::Casted.class_eval do
|
|
18
16
|
include Arel::AliasPredication
|
|
19
|
-
|
|
20
|
-
# They forget to define hash.
|
|
21
|
-
if ArelExtensions::AREL_VERSION < ArelExtensions::V10
|
|
22
|
-
def hash
|
|
23
|
-
[self.class, self.val, self.attribute].hash
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
17
|
end
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
Arel::Nodes::Unary.class_eval do
|
|
29
20
|
include Arel::Math
|
|
30
21
|
include Arel::AliasPredication
|
|
31
22
|
include Arel::Expressions
|
|
32
23
|
end
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
Arel::Nodes::Grouping.class_eval do
|
|
26
|
+
include Arel::Math
|
|
27
|
+
include Arel::AliasPredication
|
|
35
28
|
include Arel::OrderPredications
|
|
29
|
+
include Arel::Expressions
|
|
36
30
|
end
|
|
37
31
|
|
|
38
|
-
|
|
39
|
-
def eql? other
|
|
40
|
-
self.hash.eql? other.hash
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
class Arel::Nodes::Function
|
|
32
|
+
Arel::Nodes::Function.class_eval do
|
|
45
33
|
include Arel::Math
|
|
46
34
|
include Arel::Expressions
|
|
47
35
|
end
|
|
48
36
|
|
|
49
|
-
if
|
|
50
|
-
|
|
37
|
+
if Arel::VERSION >= "7.1.0"
|
|
38
|
+
Arel::Nodes::Case.class_eval do
|
|
51
39
|
include Arel::Math
|
|
52
40
|
include Arel::Expressions
|
|
53
41
|
end
|
|
54
42
|
end
|
|
55
43
|
|
|
56
|
-
require 'arel_extensions/warning'
|
|
57
|
-
require 'arel_extensions/helpers'
|
|
58
44
|
require 'arel_extensions/version'
|
|
59
|
-
require 'arel_extensions/aliases'
|
|
60
45
|
require 'arel_extensions/attributes'
|
|
61
46
|
require 'arel_extensions/visitors'
|
|
62
47
|
require 'arel_extensions/nodes'
|
|
@@ -80,117 +65,42 @@ require 'arel_extensions/nodes/case'
|
|
|
80
65
|
require 'arel_extensions/nodes/soundex'
|
|
81
66
|
require 'arel_extensions/nodes/cast'
|
|
82
67
|
require 'arel_extensions/nodes/json'
|
|
83
|
-
require 'arel_extensions/nodes/rollup'
|
|
84
|
-
require 'arel_extensions/nodes/select'
|
|
85
|
-
|
|
86
|
-
# It seems like the code in lib/arel_extensions/visitors.rb that is supposed
|
|
87
|
-
# to inject ArelExtension is not enough. Different versions of the sqlserver
|
|
88
|
-
# adapter behave differently. It doesn't always proc, so we added this for
|
|
89
|
-
# coverage.
|
|
90
|
-
if defined?(Arel::Visitors::SQLServer)
|
|
91
|
-
Arel::Visitors.const_set('MSSQL', Arel::Visitors::SQLServer)
|
|
92
|
-
require 'arel_extensions/visitors/mssql'
|
|
93
|
-
class Arel::Visitors::SQLServer
|
|
94
|
-
include ArelExtensions::Visitors::MSSQL
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
module Arel
|
|
99
|
-
def self.column_of table_name, column_name
|
|
100
|
-
ArelExtensions.column_of(table_name, column_name)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def self.duration s, expr
|
|
104
|
-
ArelExtensions::Nodes::Duration.new("#{s}i", expr)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
# The FALSE pseudo literal.
|
|
108
|
-
def self.false
|
|
109
|
-
Arel::Nodes::Equality.new(1, 0)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def self.grouping *v
|
|
113
|
-
Arel::Nodes::Grouping.new(*v)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def self.json *expr
|
|
117
|
-
ArelExtensions::Nodes::Json.new(
|
|
118
|
-
if expr.length == 1
|
|
119
|
-
expr.first
|
|
120
|
-
else
|
|
121
|
-
expr
|
|
122
|
-
end
|
|
123
|
-
)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def self.json_true
|
|
127
|
-
res = Arel.grouping(Arel.quoted('true'))
|
|
128
|
-
res.instance_eval {
|
|
129
|
-
def return_type
|
|
130
|
-
:boolean
|
|
131
|
-
end
|
|
132
|
-
}
|
|
133
|
-
res
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def self.json_false
|
|
137
|
-
res = Arel.grouping(Arel.quoted('false'))
|
|
138
|
-
res.instance_eval {
|
|
139
|
-
def return_type
|
|
140
|
-
:boolean
|
|
141
|
-
end
|
|
142
|
-
}
|
|
143
|
-
res
|
|
144
|
-
end
|
|
145
68
|
|
|
146
|
-
# The NULL literal.
|
|
147
|
-
def self.null
|
|
148
|
-
Arel.quoted(nil)
|
|
149
|
-
end
|
|
150
69
|
|
|
151
|
-
def self.quoted *args
|
|
152
|
-
Arel::Nodes.build_quoted(*args)
|
|
153
|
-
end
|
|
154
70
|
|
|
71
|
+
module Arel
|
|
155
72
|
def self.rand
|
|
156
73
|
ArelExtensions::Nodes::Rand.new
|
|
157
74
|
end
|
|
158
75
|
|
|
159
|
-
def self.rollup(*args)
|
|
160
|
-
Arel::Nodes::RollUp.new(args)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
76
|
def self.shorten s
|
|
164
77
|
Base64.urlsafe_encode64(Digest::MD5.new.digest(s)).tr('=', '').tr('-', '_')
|
|
165
78
|
end
|
|
166
79
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
tmp = Arel.grouping(nil)
|
|
174
|
-
Arel.grouping v.map{|e| tmp.convert_to_node(e)}
|
|
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
|
|
175
86
|
end
|
|
176
87
|
|
|
177
|
-
# For instance
|
|
178
|
-
#
|
|
179
|
-
# ```
|
|
180
|
-
# Arel.when(at[field].is_null).then(0).else(1)
|
|
181
|
-
# ```
|
|
182
88
|
def self.when condition
|
|
183
89
|
ArelExtensions::Nodes::Case.new.when(condition)
|
|
184
90
|
end
|
|
91
|
+
|
|
92
|
+
def self.duration s, expr
|
|
93
|
+
ArelExtensions::Nodes::Duration.new(s.to_s+'i',expr)
|
|
94
|
+
end
|
|
95
|
+
|
|
185
96
|
end
|
|
186
97
|
|
|
187
|
-
|
|
98
|
+
Arel::Attributes::Attribute.class_eval do
|
|
188
99
|
include Arel::Math
|
|
189
100
|
include ArelExtensions::Attributes
|
|
190
101
|
end
|
|
191
102
|
|
|
192
|
-
|
|
193
|
-
include ArelExtensions::Aliases
|
|
103
|
+
Arel::Nodes::Function.class_eval do
|
|
194
104
|
include ArelExtensions::Math
|
|
195
105
|
include ArelExtensions::Comparators
|
|
196
106
|
include ArelExtensions::DateDuration
|
|
@@ -199,158 +109,44 @@ class Arel::Nodes::Function
|
|
|
199
109
|
include ArelExtensions::BooleanFunctions
|
|
200
110
|
include ArelExtensions::NullFunctions
|
|
201
111
|
include ArelExtensions::Predications
|
|
202
|
-
|
|
203
|
-
if ArelExtensions::ACTIVE_RECORD_VERSION >= ArelExtensions::V8_1
|
|
204
|
-
attr_accessor :alias
|
|
205
|
-
alias_method :old_initialize, :initialize
|
|
206
|
-
|
|
207
|
-
def initialize(expr, aliaz = nil)
|
|
208
|
-
old_initialize(expr)
|
|
209
|
-
self.alias = aliaz
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
alias_method(:old_as, :as) rescue nil
|
|
214
|
-
def as other
|
|
215
|
-
res = Arel::Nodes::As.new(self.clone, Arel.sql(other))
|
|
216
|
-
self.alias = Arel.sql(other)
|
|
217
|
-
res
|
|
218
|
-
end
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
class Arel::Nodes::Grouping
|
|
222
|
-
include ArelExtensions::Math
|
|
223
|
-
include ArelExtensions::Comparators
|
|
224
|
-
include ArelExtensions::DateDuration
|
|
225
|
-
include ArelExtensions::MathFunctions
|
|
226
|
-
include ArelExtensions::NullFunctions
|
|
227
|
-
include ArelExtensions::StringFunctions
|
|
228
|
-
include ArelExtensions::Predications
|
|
229
112
|
end
|
|
230
113
|
|
|
231
|
-
|
|
114
|
+
Arel::Nodes::Unary.class_eval do
|
|
232
115
|
include ArelExtensions::Math
|
|
233
116
|
include ArelExtensions::Attributes
|
|
234
117
|
include ArelExtensions::MathFunctions
|
|
235
118
|
include ArelExtensions::Comparators
|
|
236
119
|
include ArelExtensions::Predications
|
|
237
|
-
def eql? other
|
|
238
|
-
hash == other.hash
|
|
239
|
-
end
|
|
240
120
|
end
|
|
241
121
|
|
|
242
|
-
|
|
122
|
+
Arel::Nodes::Binary.class_eval do
|
|
243
123
|
include ArelExtensions::Math
|
|
244
124
|
include ArelExtensions::Attributes
|
|
245
125
|
include ArelExtensions::MathFunctions
|
|
246
126
|
include ArelExtensions::Comparators
|
|
247
127
|
include ArelExtensions::BooleanFunctions
|
|
248
128
|
include ArelExtensions::Predications
|
|
249
|
-
def eql? other
|
|
250
|
-
hash == other.hash
|
|
251
|
-
end
|
|
252
129
|
end
|
|
253
130
|
|
|
254
|
-
|
|
131
|
+
Arel::Nodes::Equality.class_eval do
|
|
255
132
|
include ArelExtensions::Comparators
|
|
256
133
|
include ArelExtensions::DateDuration
|
|
257
134
|
include ArelExtensions::MathFunctions
|
|
258
135
|
include ArelExtensions::StringFunctions
|
|
259
136
|
end
|
|
260
137
|
|
|
261
|
-
|
|
138
|
+
|
|
139
|
+
Arel::InsertManager.class_eval do
|
|
262
140
|
include ArelExtensions::InsertManager
|
|
263
141
|
end
|
|
264
142
|
|
|
265
|
-
|
|
143
|
+
Arel::SelectManager.class_eval do
|
|
266
144
|
include ArelExtensions::SetFunctions
|
|
267
145
|
include ArelExtensions::Nodes
|
|
268
|
-
|
|
269
|
-
remove_method(:as) if method_defined?(:as)
|
|
270
|
-
def as table_name
|
|
271
|
-
Arel::Nodes::TableAlias.new(self, table_name)
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
# Install an alias, if present.
|
|
275
|
-
def xas table_name
|
|
276
|
-
if table_name.present?
|
|
277
|
-
as table_name
|
|
278
|
-
else
|
|
279
|
-
self
|
|
280
|
-
end
|
|
281
|
-
end
|
|
282
146
|
end
|
|
283
147
|
|
|
284
|
-
|
|
148
|
+
Arel::Nodes::As.class_eval do
|
|
285
149
|
include ArelExtensions::Nodes
|
|
286
150
|
end
|
|
287
151
|
|
|
288
|
-
class Arel::Table
|
|
289
|
-
alias_method(:old_alias, :alias) rescue nil
|
|
290
|
-
|
|
291
|
-
# activerecord 7.1 removed the alias. We might need to remove our dependency
|
|
292
|
-
# on the alias if it proves problematic.
|
|
293
|
-
if !self.respond_to?(:table_name)
|
|
294
|
-
alias :table_name :name
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
def alias(name = "#{self.name}_2")
|
|
298
|
-
if name.present?
|
|
299
|
-
Arel::Nodes::TableAlias.new(self, name)
|
|
300
|
-
else
|
|
301
|
-
self
|
|
302
|
-
end
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
class Arel::Nodes::TableAlias
|
|
307
|
-
def method_missing(*args)
|
|
308
|
-
met = args.shift.to_sym
|
|
309
|
-
if self.relation.respond_to?(met)
|
|
310
|
-
self.relation.send(met, args)
|
|
311
|
-
else
|
|
312
|
-
super(met, *args)
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
end
|
|
316
|
-
|
|
317
152
|
|
|
318
|
-
class Arel::Attributes::Attribute
|
|
319
|
-
def to_sql(engine = Arel::Table.engine)
|
|
320
|
-
collector = Arel::Collectors::SQLString.new
|
|
321
|
-
collector = engine.connection.visitor.accept self, collector
|
|
322
|
-
collector.value
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
def rollup
|
|
326
|
-
Arel::Nodes::RollUp.new([self])
|
|
327
|
-
end
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
class Arel::Nodes::Node
|
|
331
|
-
def rollup
|
|
332
|
-
Arel::Nodes::RollUp.new([self])
|
|
333
|
-
end
|
|
334
|
-
end
|
|
335
|
-
|
|
336
|
-
require 'active_record'
|
|
337
|
-
if ArelExtensions::ACTIVE_RECORD_VERSION >= ArelExtensions::V7_2
|
|
338
|
-
class ActiveRecord::Relation::WhereClause
|
|
339
|
-
def except_predicates(columns)
|
|
340
|
-
attrs = columns.extract! { |node| node.is_a?(Arel::Attribute) }
|
|
341
|
-
non_attrs = columns.extract! { |node| node.is_a?(Arel::Predications) }
|
|
342
|
-
|
|
343
|
-
predicates.reject do |node|
|
|
344
|
-
if !non_attrs.empty? && node.equality? && node.left.is_a?(Arel::Predications)
|
|
345
|
-
non_attrs.include?(node.left)
|
|
346
|
-
end || Arel.fetch_attribute(node) do |attr|
|
|
347
|
-
attrs.find { |v| v.eql? attr } || columns.include?(attr.name.to_s) # 👈 replces
|
|
348
|
-
# attrs.include?(attr) || columns.include?(attr.name.to_s) # 👈 this
|
|
349
|
-
#
|
|
350
|
-
# And that's because our attributes override `==`, so `attrs.include?(attr)` always
|
|
351
|
-
# passes because it returns an equality node.
|
|
352
|
-
end
|
|
353
|
-
end
|
|
354
|
-
end
|
|
355
|
-
end
|
|
356
|
-
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
|