arel_extensions 2.3.3 → 2.5.0
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/.github/workflows/ruby.yml +92 -43
- data/.gitignore +2 -1
- data/.rubocop.yml +131 -5
- data/Makefile +48 -0
- data/NEWS.md +22 -0
- data/README.md +32 -5
- data/Rakefile +5 -3
- data/arel_extensions.gemspec +3 -5
- data/dev/arelx.dockerfile +13 -16
- data/dev/compose.yaml +26 -28
- data/gemfiles/rails5.gemfile +15 -8
- data/gemfiles/rails5_1_4.gemfile +11 -9
- data/gemfiles/rails5_2.gemfile +16 -9
- data/gemfiles/rails6.gemfile +13 -7
- data/gemfiles/rails6_1.gemfile +13 -7
- data/gemfiles/rails7.gemfile +15 -9
- data/gemfiles/rails7_1.gemfile +15 -8
- data/gemfiles/rails7_2.gemfile +12 -6
- data/gemfiles/rails8.gemfile +40 -0
- data/gemfiles/rails8_1.gemfile +41 -0
- data/gemspecs/arel_extensions-v1.gemspec +3 -5
- data/gemspecs/arel_extensions-v2.gemspec +3 -5
- data/lib/arel_extensions/aliases.rb +3 -3
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/boolean_functions.rb +9 -7
- data/lib/arel_extensions/common_sql_functions.rb +5 -3
- data/lib/arel_extensions/comparators.rb +6 -4
- data/lib/arel_extensions/constants.rb +13 -0
- data/lib/arel_extensions/date_duration.rb +2 -0
- data/lib/arel_extensions/helpers.rb +18 -19
- data/lib/arel_extensions/insert_manager.rb +5 -1
- data/lib/arel_extensions/math.rb +40 -44
- data/lib/arel_extensions/math_functions.rb +29 -31
- data/lib/arel_extensions/nodes/aggregate_function.rb +4 -4
- data/lib/arel_extensions/nodes/blank.rb +6 -4
- data/lib/arel_extensions/nodes/byte_size.rb +11 -0
- data/lib/arel_extensions/nodes/case.rb +16 -13
- data/lib/arel_extensions/nodes/cast.rb +3 -5
- data/lib/arel_extensions/nodes/char_length.rb +11 -0
- data/lib/arel_extensions/nodes/coalesce.rb +1 -1
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/concat.rb +6 -6
- data/lib/arel_extensions/nodes/date_diff.rb +40 -49
- data/lib/arel_extensions/nodes/duration.rb +2 -2
- data/lib/arel_extensions/nodes/format.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_date.rb +2 -2
- data/lib/arel_extensions/nodes/formatted_number.rb +2 -2
- data/lib/arel_extensions/nodes/function.rb +7 -7
- data/lib/arel_extensions/nodes/is_null.rb +2 -0
- data/lib/arel_extensions/nodes/json.rb +27 -15
- data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
- data/lib/arel_extensions/nodes/locate.rb +1 -1
- data/lib/arel_extensions/nodes/matches.rb +2 -2
- data/lib/arel_extensions/nodes/power.rb +2 -2
- data/lib/arel_extensions/nodes/rand.rb +2 -2
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/replace.rb +3 -3
- data/lib/arel_extensions/nodes/rollup.rb +4 -4
- data/lib/arel_extensions/nodes/round.rb +3 -3
- data/lib/arel_extensions/nodes/select.rb +1 -1
- data/lib/arel_extensions/nodes/std.rb +4 -4
- data/lib/arel_extensions/nodes/substring.rb +52 -2
- 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 +3 -3
- data/lib/arel_extensions/nodes/union_all.rb +3 -3
- data/lib/arel_extensions/nodes/wday.rb +2 -2
- data/lib/arel_extensions/null_functions.rb +5 -7
- data/lib/arel_extensions/predications.rb +23 -19
- data/lib/arel_extensions/string_functions.rb +37 -28
- data/lib/arel_extensions/version.rb +3 -1
- data/lib/arel_extensions/visitors/convert_format.rb +2 -2
- data/lib/arel_extensions/visitors/ibm_db.rb +5 -5
- data/lib/arel_extensions/visitors/mssql.rb +111 -97
- data/lib/arel_extensions/visitors/mysql.rb +101 -67
- data/lib/arel_extensions/visitors/oracle.rb +113 -103
- data/lib/arel_extensions/visitors/oracle12.rb +5 -6
- data/lib/arel_extensions/visitors/postgresql.rb +119 -92
- data/lib/arel_extensions/visitors/sqlite.rb +72 -64
- data/lib/arel_extensions/visitors/to_sql.rb +85 -75
- data/lib/arel_extensions/visitors.rb +7 -7
- data/lib/arel_extensions/warning.rb +5 -5
- data/lib/arel_extensions.rb +47 -31
- data/test/arelx_test_helper.rb +8 -6
- data/test/config_loader.rb +9 -0
- data/test/database.yml +8 -6
- data/test/real_db_test.rb +33 -33
- data/test/support/fake_record.rb +3 -1
- data/test/visitors/test_bulk_insert_oracle.rb +2 -2
- data/test/visitors/test_bulk_insert_sqlite.rb +2 -2
- data/test/visitors/test_to_sql.rb +2 -2
- data/test/with_ar/all_agnostic_test.rb +214 -32
- data/test/with_ar/insert_agnostic_test.rb +2 -2
- data/test/with_ar/test_bulk_sqlite.rb +2 -2
- data/test/with_ar/test_math_sqlite.rb +2 -2
- data/test/with_ar/test_string_mysql.rb +2 -2
- data/test/with_ar/test_string_sqlite.rb +2 -2
- data/version_v1.rb +3 -1
- data/version_v2.rb +3 -1
- metadata +9 -33
- data/bin/compose +0 -6
- data/gemfiles/rails3.gemfile +0 -20
- data/gemfiles/rails4_2.gemfile +0 -38
|
@@ -3,13 +3,63 @@ module ArelExtensions
|
|
|
3
3
|
class Substring < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
|
|
6
|
+
def initialize(expr)
|
|
7
|
+
start = expr[1]
|
|
8
|
+
if start.is_a?(Range) && expr[2]
|
|
9
|
+
raise ArgumentError, 'cannot pass a length together with a Range start; the Range already determines the extracted length'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
tab = [convert_to_node(expr[0]), start.is_a?(Range) ? start : convert_to_node(start)]
|
|
8
13
|
if expr[2]
|
|
9
14
|
tab << convert_to_node(expr[2])
|
|
10
15
|
end
|
|
11
16
|
super(tab)
|
|
12
17
|
end
|
|
18
|
+
|
|
19
|
+
def range?
|
|
20
|
+
expressions[1].is_a?(Range)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Builds the vendor-agnostic Arel node tree reproducing Ruby's
|
|
24
|
+
# `String#[Range]` semantics: endless/beginless ranges, negative
|
|
25
|
+
# "from the end" indices, `exclude_end?`, and Ruby's `nil`-vs-`""`
|
|
26
|
+
# distinction (out of range vs valid-but-empty).
|
|
27
|
+
#
|
|
28
|
+
# Only meaningful when `#range?` is true; visitors need to check
|
|
29
|
+
# that first, then `visit` the node this returns.
|
|
30
|
+
def range_substring_node
|
|
31
|
+
col = expressions[0]
|
|
32
|
+
range = expressions[1]
|
|
33
|
+
b = range.begin
|
|
34
|
+
e = range.end
|
|
35
|
+
n = col.char_length
|
|
36
|
+
|
|
37
|
+
b_idx =
|
|
38
|
+
if b.nil?
|
|
39
|
+
0
|
|
40
|
+
elsif b.negative?
|
|
41
|
+
n + b
|
|
42
|
+
else
|
|
43
|
+
b
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
e_idx =
|
|
47
|
+
if e.nil?
|
|
48
|
+
n
|
|
49
|
+
else
|
|
50
|
+
raw = e.negative? ? n + e : e
|
|
51
|
+
range.exclude_end? ? raw : raw + 1
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
e_idx_clamped = Arel.when(n < e_idx).then(n).else(e_idx)
|
|
55
|
+
|
|
56
|
+
cases = Arel.when(col.is_null).then(Arel.quoted(nil))
|
|
57
|
+
cases = cases.when(n < b_idx).then(Arel.quoted(nil))
|
|
58
|
+
cases = cases.when(b_idx < 0).then(Arel.quoted(nil)) if b.is_a?(Integer) && b.negative?
|
|
59
|
+
cases
|
|
60
|
+
.when(e_idx_clamped <= b_idx).then(Arel.quoted(''))
|
|
61
|
+
.else(Substring.new([col, b_idx + 1, e_idx_clamped - b_idx]))
|
|
62
|
+
end
|
|
13
63
|
end
|
|
14
64
|
end
|
|
15
65
|
end
|
|
@@ -3,7 +3,7 @@ module ArelExtensions
|
|
|
3
3
|
class Trim < Function
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
6
|
+
def initialize(expr)
|
|
7
7
|
tab = expr.map { |arg|
|
|
8
8
|
convert_to_node(arg)
|
|
9
9
|
}
|
|
@@ -11,7 +11,7 @@ module ArelExtensions
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def +(other)
|
|
14
|
-
ArelExtensions::Nodes::Concat.new(
|
|
14
|
+
ArelExtensions::Nodes::Concat.new(expressions + [other])
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class Union < Arel::Nodes::Union
|
|
4
|
-
def initialize
|
|
5
|
-
super
|
|
4
|
+
def initialize(left, right)
|
|
5
|
+
super
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def +(other)
|
|
@@ -13,7 +13,7 @@ module ArelExtensions
|
|
|
13
13
|
ArelExtensions::Nodes::UnionAll.new(self, other)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def as
|
|
16
|
+
def as(other)
|
|
17
17
|
Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Nodes
|
|
3
3
|
class UnionAll < Arel::Nodes::UnionAll
|
|
4
|
-
def initialize
|
|
5
|
-
super
|
|
4
|
+
def initialize(left, right)
|
|
5
|
+
super
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def union_all(other)
|
|
9
9
|
ArelExtensions::Nodes::UnionAll.new(self, other)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def as
|
|
12
|
+
def as(other)
|
|
13
13
|
Arel::Nodes::TableAlias.new Arel.grouping(self), Arel::Nodes::SqlLiteral.new(other.to_s)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -3,10 +3,9 @@ require 'arel_extensions/nodes/is_null'
|
|
|
3
3
|
|
|
4
4
|
module ArelExtensions
|
|
5
5
|
module NullFunctions
|
|
6
|
-
|
|
7
6
|
# if_present returns nil if the the value is nil or blank
|
|
8
7
|
def if_present
|
|
9
|
-
Arel.when(
|
|
8
|
+
Arel.when(cast(:string).present).then(self)
|
|
10
9
|
end
|
|
11
10
|
|
|
12
11
|
# ISNULL function lets you return an alternative value when an expression is NULL.
|
|
@@ -21,19 +20,18 @@ module ArelExtensions
|
|
|
21
20
|
|
|
22
21
|
# returns the first non-null expr in the expression list. You must specify at least two expressions.
|
|
23
22
|
# If all occurrences of expr evaluate to null, then the function returns null.
|
|
24
|
-
def coalesce
|
|
23
|
+
def coalesce(*args)
|
|
25
24
|
args.unshift(self)
|
|
26
25
|
ArelExtensions::Nodes::Coalesce.new args
|
|
27
26
|
end
|
|
28
27
|
|
|
29
|
-
def coalesce_blank
|
|
30
|
-
res = Arel.when(
|
|
28
|
+
def coalesce_blank(*args)
|
|
29
|
+
res = Arel.when(cast(:string).present).then(self)
|
|
31
30
|
args[0...-1].each do |a|
|
|
32
31
|
val = a.is_a?(Arel::Nodes::Node) ? a : Arel.quoted(a)
|
|
33
32
|
res = res.when(val.present).then(a)
|
|
34
33
|
end
|
|
35
|
-
res
|
|
36
|
-
res
|
|
34
|
+
res.else(args[-1])
|
|
37
35
|
end
|
|
38
36
|
end
|
|
39
37
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Predications
|
|
3
|
-
def when
|
|
3
|
+
def when(right, expression = nil)
|
|
4
4
|
ArelExtensions::Nodes::Case.new(self).when(right, expression)
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
def matches(other, escape = nil, case_sensitive = nil)
|
|
8
|
-
if
|
|
8
|
+
if AREL_VERSION < V7
|
|
9
9
|
Arel::Nodes::Matches.new(self, Arel.quoted(other), escape)
|
|
10
10
|
else
|
|
11
11
|
Arel::Nodes::Matches.new(self, Arel.quoted(other), escape, case_sensitive)
|
|
@@ -16,7 +16,7 @@ module ArelExtensions
|
|
|
16
16
|
ArelExtensions::Nodes::IMatches.new(self, other, escape)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
def cast
|
|
19
|
+
def cast(right)
|
|
20
20
|
ArelExtensions::Nodes::Cast.new([self, right])
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -24,23 +24,24 @@ module ArelExtensions
|
|
|
24
24
|
other = other.first if other.length <= 1
|
|
25
25
|
case other
|
|
26
26
|
when Range
|
|
27
|
-
|
|
27
|
+
between(other)
|
|
28
28
|
when Arel::Nodes::Grouping, ArelExtensions::Nodes::Union, ArelExtensions::Nodes::UnionAll
|
|
29
29
|
Arel::Nodes::In.new(self, quoted_node(other))
|
|
30
30
|
when Enumerable
|
|
31
|
-
nils, values = other.partition{ |v| v.nil? }
|
|
32
|
-
ranges, values = values.partition{ |v| v.is_a?(Range) || v.is_a?(Arel::SelectManager)}
|
|
31
|
+
nils, values = other.partition { |v| v.nil? }
|
|
32
|
+
ranges, values = values.partition { |v| v.is_a?(Range) || v.is_a?(Arel::SelectManager) }
|
|
33
33
|
# In order of (imagined) decreasing efficiency: nil, values, and then more complex.
|
|
34
34
|
clauses =
|
|
35
35
|
nils.uniq.map { |r| self.in(r) } \
|
|
36
36
|
+ (case values.uniq.size
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
when 0 then []
|
|
38
|
+
when 1 then [values[0].is_a?(Arel::Nodes::Grouping) ? self.in(values[0]) : eq(values[0])]
|
|
39
|
+
else [Arel::Nodes::In.new(self, quoted_array(values))]
|
|
40
|
+
end) \
|
|
40
41
|
+ ranges.uniq.map { |r| self.in(r) }
|
|
41
42
|
clauses.empty? ? Arel.false : clauses.reduce(&:or)
|
|
42
43
|
when nil
|
|
43
|
-
|
|
44
|
+
is_null
|
|
44
45
|
when Arel::SelectManager
|
|
45
46
|
Arel::Nodes::In.new(self, other.ast)
|
|
46
47
|
else
|
|
@@ -52,23 +53,24 @@ module ArelExtensions
|
|
|
52
53
|
other = other.first if other.length <= 1
|
|
53
54
|
case other
|
|
54
55
|
when Range
|
|
55
|
-
Arel::Nodes::Not.new(
|
|
56
|
+
Arel::Nodes::Not.new(between(other))
|
|
56
57
|
when Arel::Nodes::Grouping, ArelExtensions::Nodes::Union, ArelExtensions::Nodes::UnionAll
|
|
57
58
|
Arel::Nodes::NotIn.new(self, quoted_node(other))
|
|
58
59
|
when Enumerable
|
|
59
|
-
nils, values = other.partition{ |v| v.nil? }
|
|
60
|
-
ranges, values = values.partition{ |v| v.is_a?(Range) || v.is_a?(Arel::SelectManager)}
|
|
60
|
+
nils, values = other.partition { |v| v.nil? }
|
|
61
|
+
ranges, values = values.partition { |v| v.is_a?(Range) || v.is_a?(Arel::SelectManager) }
|
|
61
62
|
# In order of (imagined) decreasing efficiency: nil, values, and then more complex.
|
|
62
63
|
clauses =
|
|
63
|
-
nils.uniq.map { |r|
|
|
64
|
+
nils.uniq.map { |r| not_in(r) } \
|
|
64
65
|
+ (case values.uniq.size
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
when 0 then []
|
|
67
|
+
when 1 then [values[0].is_a?(Arel::Nodes::Grouping) ? not_in(values[0]) : not_eq(values[0])]
|
|
68
|
+
else [Arel::Nodes::NotIn.new(self, quoted_array(values))]
|
|
69
|
+
end) \
|
|
70
|
+
+ ranges.uniq.map { |r| not_in(r) }
|
|
69
71
|
Arel::Nodes::And.new clauses
|
|
70
72
|
when nil
|
|
71
|
-
|
|
73
|
+
is_not_null
|
|
72
74
|
when Arel::SelectManager
|
|
73
75
|
Arel::Nodes::NotIn.new(self, other.ast)
|
|
74
76
|
else
|
|
@@ -86,6 +88,8 @@ module ArelExtensions
|
|
|
86
88
|
Arel.quoted(object.strftime('%H:%M:%S'), self)
|
|
87
89
|
when String
|
|
88
90
|
Arel.quoted(object)
|
|
91
|
+
when TrueClass, FalseClass
|
|
92
|
+
Arel.quoted(object)
|
|
89
93
|
when Date
|
|
90
94
|
Arel.quoted(object.to_s, self)
|
|
91
95
|
when NilClass
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'arel_extensions/nodes/byte_size'
|
|
2
|
+
require 'arel_extensions/nodes/char_length'
|
|
1
3
|
require 'arel_extensions/nodes/concat' # if Arel::VERSION.to_i < 7
|
|
2
4
|
require 'arel_extensions/nodes/length'
|
|
3
5
|
require 'arel_extensions/nodes/locate'
|
|
@@ -16,37 +18,44 @@ require 'arel_extensions/nodes/collate'
|
|
|
16
18
|
require 'arel_extensions/nodes/levenshtein_distance'
|
|
17
19
|
require 'arel_extensions/nodes/md5'
|
|
18
20
|
|
|
19
|
-
|
|
20
21
|
module ArelExtensions
|
|
21
22
|
module StringFunctions
|
|
23
|
+
include ArelExtensions::Warning
|
|
24
|
+
|
|
22
25
|
# *FindInSet function .......
|
|
23
26
|
def &(other)
|
|
24
27
|
ArelExtensions::Nodes::FindInSet.new [
|
|
25
28
|
Arel.quoted(other.is_a?(Integer) ? other.to_s : other),
|
|
26
|
-
self
|
|
29
|
+
self
|
|
27
30
|
]
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
# LENGTH function returns the length (bytewise) of the value in a text field.
|
|
31
34
|
def length
|
|
35
|
+
deprecated "Use `byte_size` or `char_length` instead. `length` relies on the vendor's `LEN/LENGTH` implementation and it's not portable"
|
|
32
36
|
ArelExtensions::Nodes::Length.new self, true
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
def byte_length
|
|
40
|
+
deprecated "Use `byte_size` instead. `byte_length` relies on the vendor's `LEN/LENGTH` implementation and it's not portable"
|
|
36
41
|
ArelExtensions::Nodes::Length.new self, true
|
|
37
42
|
end
|
|
38
43
|
|
|
44
|
+
def byte_size
|
|
45
|
+
ArelExtensions::Nodes::ByteSize.new self
|
|
46
|
+
end
|
|
47
|
+
|
|
39
48
|
def char_length
|
|
40
|
-
ArelExtensions::Nodes::
|
|
49
|
+
ArelExtensions::Nodes::CharLength.new self
|
|
41
50
|
end
|
|
42
51
|
|
|
43
52
|
# LOCATE function returns the first starting position of a string in another string.
|
|
44
53
|
# If string1 or string2 is NULL then it returns NULL. If string1 not found in string2 then it returns 0.
|
|
45
|
-
def locate
|
|
54
|
+
def locate(val)
|
|
46
55
|
ArelExtensions::Nodes::Locate.new [self, val]
|
|
47
56
|
end
|
|
48
57
|
|
|
49
|
-
def substring
|
|
58
|
+
def substring(start, len = nil)
|
|
50
59
|
ArelExtensions::Nodes::Substring.new [self, start, len]
|
|
51
60
|
end
|
|
52
61
|
|
|
@@ -61,9 +70,9 @@ module ArelExtensions
|
|
|
61
70
|
# It's ignored in all other cases.
|
|
62
71
|
def [](start, end_ = nil)
|
|
63
72
|
if start.is_a?(String) || start.is_a?(Symbol)
|
|
64
|
-
|
|
73
|
+
send(start)
|
|
65
74
|
elsif start.is_a?(Range)
|
|
66
|
-
ArelExtensions::Nodes::Substring.new [self, start
|
|
75
|
+
ArelExtensions::Nodes::Substring.new [self, start]
|
|
67
76
|
elsif start.is_a?(Integer) && !end_
|
|
68
77
|
ArelExtensions::Nodes::Substring.new [self, start + 1, 1]
|
|
69
78
|
elsif start.is_a?(Integer)
|
|
@@ -79,11 +88,11 @@ module ArelExtensions
|
|
|
79
88
|
ArelExtensions::Nodes::Soundex.new [self]
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
def imatches
|
|
91
|
+
def imatches(others, escape = nil)
|
|
83
92
|
ArelExtensions::Nodes::IMatches.new self, others, escape
|
|
84
93
|
end
|
|
85
94
|
|
|
86
|
-
def imatches_any
|
|
95
|
+
def imatches_any(others, escape = nil)
|
|
87
96
|
grouping_any :imatches, others, escape
|
|
88
97
|
end
|
|
89
98
|
|
|
@@ -100,31 +109,31 @@ module ArelExtensions
|
|
|
100
109
|
# res
|
|
101
110
|
# end
|
|
102
111
|
|
|
103
|
-
def imatches_all
|
|
112
|
+
def imatches_all(others, escape = nil)
|
|
104
113
|
grouping_all :imatches, others, escape, escape
|
|
105
114
|
end
|
|
106
115
|
|
|
107
|
-
def idoes_not_match
|
|
116
|
+
def idoes_not_match(others, escape = nil)
|
|
108
117
|
ArelExtensions::Nodes::IDoesNotMatch.new self, others, escape
|
|
109
118
|
end
|
|
110
119
|
|
|
111
|
-
def idoes_not_match_any
|
|
120
|
+
def idoes_not_match_any(others, escape = nil)
|
|
112
121
|
grouping_any :idoes_not_match, others, escape
|
|
113
122
|
end
|
|
114
123
|
|
|
115
|
-
def idoes_not_match_all
|
|
124
|
+
def idoes_not_match_all(others, escape = nil)
|
|
116
125
|
grouping_all :idoes_not_match, others, escape
|
|
117
126
|
end
|
|
118
127
|
|
|
119
|
-
def ai_matches
|
|
128
|
+
def ai_matches(other) # accent insensitive & case sensitive
|
|
120
129
|
ArelExtensions::Nodes::AiMatches.new(self, other)
|
|
121
130
|
end
|
|
122
131
|
|
|
123
|
-
def ai_imatches
|
|
132
|
+
def ai_imatches(other) # accent insensitive & case insensitive
|
|
124
133
|
ArelExtensions::Nodes::AiIMatches.new(self, other)
|
|
125
134
|
end
|
|
126
135
|
|
|
127
|
-
def smatches
|
|
136
|
+
def smatches(other) # accent sensitive & case sensitive
|
|
128
137
|
ArelExtensions::Nodes::SMatches.new(self, other)
|
|
129
138
|
end
|
|
130
139
|
|
|
@@ -136,12 +145,12 @@ module ArelExtensions
|
|
|
136
145
|
ArelExtensions::Nodes::Collate.new(self, nil, false, true)
|
|
137
146
|
end
|
|
138
147
|
|
|
139
|
-
def collate
|
|
148
|
+
def collate(ai = false, ci = false, option = nil)
|
|
140
149
|
ArelExtensions::Nodes::Collate.new(self, option, ai, ci)
|
|
141
150
|
end
|
|
142
151
|
|
|
143
152
|
# REPLACE function replaces a sequence of characters in a string with another set of characters, not case-sensitive.
|
|
144
|
-
def replace
|
|
153
|
+
def replace(pattern, substitute)
|
|
145
154
|
if pattern.is_a? Regexp
|
|
146
155
|
ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
|
|
147
156
|
else
|
|
@@ -149,11 +158,11 @@ module ArelExtensions
|
|
|
149
158
|
end
|
|
150
159
|
end
|
|
151
160
|
|
|
152
|
-
def regexp_replace
|
|
161
|
+
def regexp_replace(pattern, substitute)
|
|
153
162
|
ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
|
|
154
163
|
end
|
|
155
164
|
|
|
156
|
-
def concat
|
|
165
|
+
def concat(other)
|
|
157
166
|
ArelExtensions::Nodes::Concat.new [self, other]
|
|
158
167
|
end
|
|
159
168
|
|
|
@@ -162,26 +171,26 @@ module ArelExtensions
|
|
|
162
171
|
if orders.present?
|
|
163
172
|
deprecated 'Use the kwarg `order` instead.', what: 'orders'
|
|
164
173
|
end
|
|
165
|
-
order_tabs = [orders].flatten.map{ |o|
|
|
174
|
+
order_tabs = [orders].flatten.map { |o|
|
|
166
175
|
if o.is_a?(Arel::Nodes::Ascending) || o.is_a?(Arel::Nodes::Descending)
|
|
167
176
|
o
|
|
168
177
|
elsif o.respond_to?(:asc)
|
|
169
178
|
o.asc
|
|
170
179
|
end
|
|
171
180
|
}.compact
|
|
172
|
-
ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order:
|
|
181
|
+
ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order: order || order_tabs)
|
|
173
182
|
end
|
|
174
183
|
|
|
175
184
|
# Function returns a string after removing left, right or the both prefixes or suffixes int argument
|
|
176
|
-
def trim
|
|
185
|
+
def trim(other = ' ')
|
|
177
186
|
ArelExtensions::Nodes::Trim.new [self, other]
|
|
178
187
|
end
|
|
179
188
|
|
|
180
|
-
def ltrim
|
|
189
|
+
def ltrim(other = ' ')
|
|
181
190
|
ArelExtensions::Nodes::Ltrim.new [self, other]
|
|
182
191
|
end
|
|
183
192
|
|
|
184
|
-
def rtrim
|
|
193
|
+
def rtrim(other = ' ')
|
|
185
194
|
ArelExtensions::Nodes::Rtrim.new [self, other]
|
|
186
195
|
end
|
|
187
196
|
|
|
@@ -202,15 +211,15 @@ module ArelExtensions
|
|
|
202
211
|
end
|
|
203
212
|
alias present not_blank
|
|
204
213
|
|
|
205
|
-
def repeat
|
|
214
|
+
def repeat(other = 1)
|
|
206
215
|
ArelExtensions::Nodes::Repeat.new [self, other]
|
|
207
216
|
end
|
|
208
217
|
|
|
209
|
-
def levenshtein_distance
|
|
218
|
+
def levenshtein_distance(other)
|
|
210
219
|
ArelExtensions::Nodes::LevenshteinDistance.new [self, other]
|
|
211
220
|
end
|
|
212
221
|
|
|
213
|
-
def edit_distance
|
|
222
|
+
def edit_distance(other)
|
|
214
223
|
ArelExtensions::Nodes::LevenshteinDistance.new [self, other]
|
|
215
224
|
end
|
|
216
225
|
|
|
@@ -2,13 +2,13 @@ module ArelExtensions
|
|
|
2
2
|
module Visitors
|
|
3
3
|
# Convert date format in strftime syntax to whatever the RDBMs
|
|
4
4
|
# wants, based on the table of conversion +mapping+.
|
|
5
|
-
def self.strftime_to_format
|
|
5
|
+
def self.strftime_to_format(format, mapping)
|
|
6
6
|
@mapping_regexps ||= {}
|
|
7
7
|
@mapping_regexps[mapping] ||=
|
|
8
8
|
Regexp.new(
|
|
9
9
|
mapping
|
|
10
10
|
.keys
|
|
11
|
-
.map{|k| Regexp.escape(k)}
|
|
11
|
+
.map { |k| Regexp.escape(k) }
|
|
12
12
|
.join('|')
|
|
13
13
|
)
|
|
14
14
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Visitors
|
|
3
3
|
class Arel::Visitors::IBM_DB
|
|
4
|
-
def visit_ArelExtensions_Nodes_Ceil
|
|
4
|
+
def visit_ArelExtensions_Nodes_Ceil(o, collector)
|
|
5
5
|
collector << 'CEILING('
|
|
6
6
|
collector = visit o.expr, collector
|
|
7
7
|
collector << ')'
|
|
8
8
|
collector
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
def visit_ArelExtensions_Nodes_Trim
|
|
11
|
+
def visit_ArelExtensions_Nodes_Trim(o, collector)
|
|
12
12
|
collector << 'LTRIM(RTRIM('
|
|
13
13
|
o.expressions.each_with_index { |arg, i|
|
|
14
14
|
collector << COMMA if i != 0
|
|
@@ -18,7 +18,7 @@ module ArelExtensions
|
|
|
18
18
|
collector
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def visit_ArelExtensions_Nodes_DateDiff
|
|
21
|
+
def visit_ArelExtensions_Nodes_DateDiff(o, collector)
|
|
22
22
|
collector << 'DAY('
|
|
23
23
|
collector = visit o.left, collector
|
|
24
24
|
collector << ','
|
|
@@ -31,7 +31,7 @@ module ArelExtensions
|
|
|
31
31
|
collector
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
def visit_ArelExtensions_Nodes_Duration
|
|
34
|
+
def visit_ArelExtensions_Nodes_Duration(o, collector)
|
|
35
35
|
# visit left for period
|
|
36
36
|
if o.left == 'd'
|
|
37
37
|
collector << 'DAY('
|
|
@@ -52,7 +52,7 @@ module ArelExtensions
|
|
|
52
52
|
collector
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
def visit_ArelExtensions_Nodes_IsNull
|
|
55
|
+
def visit_ArelExtensions_Nodes_IsNull(o, collector)
|
|
56
56
|
collector << 'COALESCE('
|
|
57
57
|
collector = visit o.left, collector
|
|
58
58
|
collector << ','
|