arel_extensions 2.4.0 → 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/.gitignore +2 -1
- data/.rubocop.yml +131 -5
- data/Makefile +31 -1
- data/NEWS.md +15 -0
- data/README.md +11 -2
- data/Rakefile +5 -3
- data/arel_extensions.gemspec +3 -5
- 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 +7 -7
- data/gemfiles/rails8_1.gemfile +4 -4
- 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/date_duration.rb +2 -0
- data/lib/arel_extensions/helpers.rb +17 -17
- data/lib/arel_extensions/insert_manager.rb +5 -1
- data/lib/arel_extensions/math.rb +40 -44
- data/lib/arel_extensions/math_functions.rb +28 -30
- data/lib/arel_extensions/nodes/aggregate_function.rb +4 -4
- data/lib/arel_extensions/nodes/blank.rb +6 -4
- data/lib/arel_extensions/nodes/case.rb +15 -12
- data/lib/arel_extensions/nodes/cast.rb +3 -5
- 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 +6 -4
- 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/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 +22 -18
- data/lib/arel_extensions/string_functions.rb +26 -27
- 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 +91 -92
- data/lib/arel_extensions/visitors/mysql.rb +89 -69
- data/lib/arel_extensions/visitors/oracle.rb +100 -104
- data/lib/arel_extensions/visitors/oracle12.rb +5 -6
- data/lib/arel_extensions/visitors/postgresql.rb +107 -94
- data/lib/arel_extensions/visitors/sqlite.rb +57 -65
- data/lib/arel_extensions/visitors/to_sql.rb +84 -74
- data/lib/arel_extensions/visitors.rb +6 -6
- data/lib/arel_extensions/warning.rb +5 -5
- data/lib/arel_extensions.rb +34 -27
- data/test/real_db_test.rb +31 -31
- data/test/visitors/test_to_sql.rb +2 -2
- data/test/with_ar/all_agnostic_test.rb +149 -15
- data/version_v1.rb +3 -1
- data/version_v2.rb +3 -1
- metadata +2 -30
|
@@ -5,20 +5,20 @@ module ArelExtensions
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :dict
|
|
7
7
|
|
|
8
|
-
def merge
|
|
9
|
-
args = [self] + expr.map{|e| Json.new(e)}
|
|
8
|
+
def merge(*expr)
|
|
9
|
+
args = [self] + expr.map { |e| Json.new(e) }
|
|
10
10
|
JsonMerge.new(args)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def get
|
|
13
|
+
def get(key)
|
|
14
14
|
JsonGet.new(self, key)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def set
|
|
17
|
+
def set(key, value)
|
|
18
18
|
JsonSet.new(self, key, value)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def group
|
|
21
|
+
def group(as_array = true, orders = nil, distinct: false)
|
|
22
22
|
if distinct
|
|
23
23
|
JsonGroup.new(Arel::Nodes::NamedFunction.new('DISTINCT', [self]), as_array, orders)
|
|
24
24
|
else
|
|
@@ -35,12 +35,12 @@ module ArelExtensions
|
|
|
35
35
|
when JsonNode
|
|
36
36
|
n.dict
|
|
37
37
|
when Array
|
|
38
|
-
n.map{|e|
|
|
39
|
-
|
|
38
|
+
n.map { |e|
|
|
39
|
+
e.is_a?(Array) || e.is_a?(Hash) ? Json.new(e) : convert_to_json_node(e)
|
|
40
40
|
}
|
|
41
41
|
when Hash
|
|
42
|
-
n.reduce({}){|acc, v|
|
|
43
|
-
acc[convert_to_json_node(v[0])] =
|
|
42
|
+
n.reduce({}) { |acc, v|
|
|
43
|
+
acc[convert_to_json_node(v[0])] = v[1].is_a?(Array) || v[1].is_a?(Hash) ? Json.new(v[1]) : convert_to_json_node(v[1])
|
|
44
44
|
acc
|
|
45
45
|
}
|
|
46
46
|
when String, Numeric, TrueClass, FalseClass
|
|
@@ -58,9 +58,21 @@ module ArelExtensions
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
# A boolean literal, either bare (TrueClass/FalseClass) or wrapped in a Quoted node
|
|
62
|
+
# (which is how `convert_to_node` represents one after construction).
|
|
63
|
+
def boolean_literal?(v)
|
|
64
|
+
v.is_a?(TrueClass) \
|
|
65
|
+
|| v.is_a?(FalseClass) \
|
|
66
|
+
|| (v.is_a?(Arel::Nodes::Quoted) && [true, false].include?(v.expr))
|
|
67
|
+
end
|
|
68
|
+
|
|
61
69
|
def type_of_node(v)
|
|
62
70
|
if v.is_a?(Arel::Attributes::Attribute)
|
|
63
|
-
|
|
71
|
+
type_of_attribute(v)
|
|
72
|
+
elsif v.is_a?(Numeric)
|
|
73
|
+
:numeric
|
|
74
|
+
elsif boolean_literal?(v)
|
|
75
|
+
:boolean
|
|
64
76
|
elsif v.respond_to?(:return_type)
|
|
65
77
|
v.return_type
|
|
66
78
|
elsif v.nil?
|
|
@@ -72,12 +84,12 @@ module ArelExtensions
|
|
|
72
84
|
end
|
|
73
85
|
|
|
74
86
|
class Json < JsonNode
|
|
75
|
-
def initialize
|
|
87
|
+
def initialize(*expr)
|
|
76
88
|
@dict =
|
|
77
89
|
if expr.length == 1
|
|
78
90
|
convert_to_json_node(expr.first)
|
|
79
91
|
else
|
|
80
|
-
expr.map{|e| convert_to_json_node(e) }
|
|
92
|
+
expr.map { |e| convert_to_json_node(e) }
|
|
81
93
|
end
|
|
82
94
|
super
|
|
83
95
|
end
|
|
@@ -89,7 +101,7 @@ module ArelExtensions
|
|
|
89
101
|
class JsonGroup < JsonNode
|
|
90
102
|
attr_accessor :as_array, :orders
|
|
91
103
|
|
|
92
|
-
def initialize
|
|
104
|
+
def initialize(json, as_array = true, orders = nil)
|
|
93
105
|
@dict = as_array ? json : json.dict
|
|
94
106
|
@as_array = as_array
|
|
95
107
|
if orders
|
|
@@ -101,7 +113,7 @@ module ArelExtensions
|
|
|
101
113
|
class JsonGet < JsonNode
|
|
102
114
|
attr_accessor :key
|
|
103
115
|
|
|
104
|
-
def initialize
|
|
116
|
+
def initialize(json, key)
|
|
105
117
|
@dict = json
|
|
106
118
|
@key = convert_to_node(key)
|
|
107
119
|
end
|
|
@@ -110,7 +122,7 @@ module ArelExtensions
|
|
|
110
122
|
class JsonSet < JsonNode
|
|
111
123
|
attr_accessor :key, :value
|
|
112
124
|
|
|
113
|
-
def initialize
|
|
125
|
+
def initialize(json, key, value)
|
|
114
126
|
@dict = json
|
|
115
127
|
@key = convert_to_node(key)
|
|
116
128
|
@value = Json.new(value)
|
|
@@ -3,8 +3,8 @@ module ArelExtensions
|
|
|
3
3
|
class LevenshteinDistance < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
super
|
|
6
|
+
def initialize(expr)
|
|
7
|
+
super([convert_to_node(expr.first), Arel.quoted(expr[1])])
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -3,8 +3,8 @@ module ArelExtensions
|
|
|
3
3
|
class Power < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
super
|
|
6
|
+
def initialize(expr)
|
|
7
|
+
super([convert_to_node(expr.first), convert_to_number(expr[1])])
|
|
8
8
|
end
|
|
9
9
|
end
|
|
10
10
|
end
|
|
@@ -3,7 +3,7 @@ module ArelExtensions
|
|
|
3
3
|
class Repeat < 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
|
end
|
|
@@ -4,7 +4,7 @@ module ArelExtensions
|
|
|
4
4
|
RETURN_TYPE = :string
|
|
5
5
|
attr_accessor :left, :pattern, :substitute
|
|
6
6
|
|
|
7
|
-
def initialize
|
|
7
|
+
def initialize(left, pattern, substitute)
|
|
8
8
|
@left = convert_to_node(left)
|
|
9
9
|
@pattern = convert_to_node(pattern)
|
|
10
10
|
@substitute = convert_to_node(substitute)
|
|
@@ -16,9 +16,9 @@ module ArelExtensions
|
|
|
16
16
|
RETURN_TYPE = :string
|
|
17
17
|
attr_accessor :left, :pattern, :substitute
|
|
18
18
|
|
|
19
|
-
def initialize
|
|
19
|
+
def initialize(left, pattern, substitute)
|
|
20
20
|
@left = convert_to_node(left)
|
|
21
|
-
@pattern = (pattern.is_a?(Regexp) ? pattern :
|
|
21
|
+
@pattern = (pattern.is_a?(Regexp) ? pattern : /#{pattern}/)
|
|
22
22
|
@substitute = convert_to_node(substitute)
|
|
23
23
|
super([@left, @pattern, @substitute])
|
|
24
24
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
begin
|
|
5
5
|
Arel::Nodes.const_get('RollUp')
|
|
6
|
-
rescue NameError =>
|
|
6
|
+
rescue NameError => _e
|
|
7
7
|
module Arel
|
|
8
8
|
module Nodes
|
|
9
9
|
class RollUp < Arel::Nodes::Unary
|
|
@@ -18,16 +18,16 @@ rescue NameError => _
|
|
|
18
18
|
# handle grouping aggregation semantics
|
|
19
19
|
def grouping_array_or_grouping_element(o, collector)
|
|
20
20
|
if o.expr.is_a? Array
|
|
21
|
-
collector <<
|
|
21
|
+
collector << '( '
|
|
22
22
|
visit o.expr, collector
|
|
23
|
-
collector <<
|
|
23
|
+
collector << ' )'
|
|
24
24
|
else
|
|
25
25
|
visit o.expr, collector
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def visit_Arel_Nodes_RollUp(o, collector)
|
|
30
|
-
collector <<
|
|
30
|
+
collector << 'ROLLUP'
|
|
31
31
|
grouping_array_or_grouping_element o, collector
|
|
32
32
|
end
|
|
33
33
|
end
|
|
@@ -3,11 +3,11 @@ module ArelExtensions
|
|
|
3
3
|
class Round < Function
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
6
|
+
def initialize(expr)
|
|
7
7
|
if expr && expr.length == 1
|
|
8
|
-
super
|
|
8
|
+
super([convert_to_node(expr.first)])
|
|
9
9
|
else
|
|
10
|
-
super
|
|
10
|
+
super([convert_to_node(expr.first), convert_to_number(expr[1])])
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
|
@@ -4,9 +4,9 @@ module ArelExtensions
|
|
|
4
4
|
RETURN_TYPE = :number
|
|
5
5
|
attr_accessor :unbiased_estimator
|
|
6
6
|
|
|
7
|
-
def initialize
|
|
7
|
+
def initialize(node, **opts)
|
|
8
8
|
@unbiased_estimator = opts[:unbiased] ? true : false
|
|
9
|
-
super
|
|
9
|
+
super
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -14,9 +14,9 @@ module ArelExtensions
|
|
|
14
14
|
RETURN_TYPE = :number
|
|
15
15
|
attr_accessor :unbiased_estimator
|
|
16
16
|
|
|
17
|
-
def initialize
|
|
17
|
+
def initialize(node, **opts)
|
|
18
18
|
@unbiased_estimator = opts[:unbiased] ? true : false
|
|
19
|
-
super
|
|
19
|
+
super
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -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,6 +1,6 @@
|
|
|
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
|
|
|
@@ -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
|