arel_extensions 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis/oracle/download.js +116 -0
- data/.travis/oracle/download.sh +16 -0
- data/.travis/oracle/install.sh +32 -0
- data/.travis.yml +72 -69
- data/Rakefile +29 -4
- data/arel_extensions.gemspec +1 -1
- data/functions.html +21 -12
- data/gemfiles/rails4.gemfile +11 -3
- data/gemfiles/rails5.gemfile +8 -4
- data/lib/arel_extensions/math.rb +2 -2
- data/lib/arel_extensions/math_functions.rb +1 -1
- data/lib/arel_extensions/nodes/concat.rb +16 -0
- data/lib/arel_extensions/nodes/date_diff.rb +37 -25
- data/lib/arel_extensions/nodes/function.rb +30 -0
- data/lib/arel_extensions/nodes/is_null.rb +6 -0
- data/lib/arel_extensions/nodes/replace.rb +8 -26
- data/lib/arel_extensions/nodes/round.rb +6 -6
- data/lib/arel_extensions/nodes.rb +1 -1
- data/lib/arel_extensions/null_functions.rb +2 -2
- data/lib/arel_extensions/string_functions.rb +5 -1
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mysql.rb +89 -113
- data/lib/arel_extensions/visitors/oracle.rb +28 -65
- data/lib/arel_extensions/visitors/postgresql.rb +82 -121
- data/lib/arel_extensions/visitors/sqlite.rb +60 -55
- data/lib/arel_extensions/visitors/to_sql.rb +30 -5
- data/test/database.yml +15 -3
- data/test/real_db_test.rb +0 -1
- data/test/visitors/test_bulk_insert_sqlite.rb +2 -1
- data/test/visitors/test_oracle.rb +2 -2
- data/test/visitors/test_to_sql.rb +3 -4
- data/test/with_ar/all_agnostic_test.rb +294 -0
- data/test/with_ar/insert_agnostic_test.rb +52 -0
- data/test/with_ar/test_bulk_sqlite.rb +3 -2
- metadata +10 -5
- data/lib/arel_extensions/nodes/isnull.rb +0 -30
- data/test/with_ar/test_string_postgresql.rb +0 -81
@@ -41,6 +41,36 @@ module ArelExtensions
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
def convert_to_date_node(object)
|
45
|
+
case object
|
46
|
+
when Arel::Attributes::Attribute, Arel::Nodes::Node
|
47
|
+
object
|
48
|
+
when DateTime, Time
|
49
|
+
Arel::Nodes.build_quoted(Date.new(object.year, object.month, object.day), self)
|
50
|
+
when String
|
51
|
+
Arel::Nodes.build_quoted(Date.parse(object), self)
|
52
|
+
when Date
|
53
|
+
Arel::Nodes.build_quoted(object, self)
|
54
|
+
else
|
55
|
+
raise(ArgumentError, "#{object.class} can not be converted to Date")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def convert_to_number(object)
|
60
|
+
case object
|
61
|
+
when Arel::Attributes::Attribute, Arel::Nodes::Node
|
62
|
+
object
|
63
|
+
when Fixnum, Integer
|
64
|
+
object.to_i.abs
|
65
|
+
when DateTime, Date, Time, String, ActiveSupport::Duration
|
66
|
+
object.to_i.abs
|
67
|
+
when NilClass
|
68
|
+
0
|
69
|
+
else
|
70
|
+
raise(ArgumentError, "#{object.class} can not be converted to NUMBER arg")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
44
74
|
end
|
45
75
|
end
|
46
76
|
end
|
@@ -1,34 +1,16 @@
|
|
1
1
|
module ArelExtensions
|
2
2
|
module Nodes
|
3
|
-
class Replace <
|
3
|
+
class Replace < Function
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
tab
|
10
|
-
tab << right
|
11
|
-
super(tab, aliaz)
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
def expr
|
16
|
-
@expressions.first
|
5
|
+
def initialize expr
|
6
|
+
tab = expr.map { |arg|
|
7
|
+
convert_to_node(arg)
|
8
|
+
}
|
9
|
+
return super(tab)
|
17
10
|
end
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
@expressions[1]
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
def right
|
26
|
-
@expressions[2]
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def as other
|
31
|
-
Arel::Nodes::As.new self, Arel::Nodes::SqlLiteral.new(other)
|
12
|
+
def +(other)
|
13
|
+
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
32
14
|
end
|
33
15
|
|
34
16
|
end
|
@@ -2,14 +2,14 @@ module ArelExtensions
|
|
2
2
|
module Nodes
|
3
3
|
class Round < Function
|
4
4
|
|
5
|
-
def
|
6
|
-
|
5
|
+
def initialize expr
|
6
|
+
if expr && expr.length == 1
|
7
|
+
super [convert_to_node(expr.first)]
|
8
|
+
else
|
9
|
+
super [convert_to_node(expr.first), convert_to_number(expr[1])]
|
10
|
+
end
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
def right
|
11
|
-
@expressions[1]
|
12
|
-
end
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -2,8 +2,8 @@ module ArelExtensions
|
|
2
2
|
module NullFunctions
|
3
3
|
|
4
4
|
#ISNULL function lets you return an alternative value when an expression is NULL.
|
5
|
-
def
|
6
|
-
ArelExtensions::Nodes::
|
5
|
+
def is_null
|
6
|
+
ArelExtensions::Nodes::IsNull.new [self]
|
7
7
|
end
|
8
8
|
# returns the first non-null expr in the expression list. You must specify at least two expressions.
|
9
9
|
#If all occurrences of expr evaluate to null, then the function returns null.
|
@@ -48,7 +48,11 @@ module ArelExtensions
|
|
48
48
|
|
49
49
|
#REPLACE function replaces a sequence of characters in a string with another set of characters, not case-sensitive.
|
50
50
|
def replace left, right
|
51
|
-
ArelExtensions::Nodes::Replace.new self, left, right
|
51
|
+
ArelExtensions::Nodes::Replace.new [self, left, right]
|
52
|
+
end
|
53
|
+
|
54
|
+
def group_concat sep = nil
|
55
|
+
ArelExtensions::Nodes::GroupConcat.new [self, sep]
|
52
56
|
end
|
53
57
|
|
54
58
|
#Function returns a string after removing left, right or the both prefixes or suffixes int argument
|
@@ -2,39 +2,31 @@ module ArelExtensions
|
|
2
2
|
module Visitors
|
3
3
|
Arel::Visitors::MySQL.class_eval do
|
4
4
|
|
5
|
-
|
6
|
-
def
|
7
|
-
collector << "DATEDIFF("
|
5
|
+
#String functions
|
6
|
+
def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
|
8
7
|
collector = visit o.left, collector
|
9
|
-
collector <<
|
8
|
+
collector << ' LIKE '
|
10
9
|
collector = visit o.right, collector
|
11
|
-
|
12
|
-
|
10
|
+
if o.escape
|
11
|
+
collector << ' ESCAPE '
|
12
|
+
visit o.escape, collector
|
13
|
+
else
|
14
|
+
collector
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
elsif (o.left == "w")
|
23
|
-
collector << "WEEK("
|
24
|
-
elsif (o.left == "y")
|
25
|
-
collector << "YEAR("
|
26
|
-
end
|
27
|
-
#visit right
|
28
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
29
|
-
collector = visit o.right, collector
|
18
|
+
def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
|
19
|
+
collector = visit o.left.lower, collector
|
20
|
+
collector << ' NOT LIKE '
|
21
|
+
collector = visit o.right.lower(o.right), collector
|
22
|
+
if o.escape
|
23
|
+
collector << ' ESCAPE '
|
24
|
+
visit o.escape, collector
|
30
25
|
else
|
31
|
-
collector
|
26
|
+
collector
|
32
27
|
end
|
33
|
-
collector << ")"
|
34
|
-
collector
|
35
28
|
end
|
36
29
|
|
37
|
-
#****************************************************************#
|
38
30
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
39
31
|
collector << "CONCAT("
|
40
32
|
o.expressions.each_with_index { |arg, i|
|
@@ -45,123 +37,107 @@ module ArelExtensions
|
|
45
37
|
collector
|
46
38
|
end
|
47
39
|
|
48
|
-
|
49
|
-
|
50
|
-
collector
|
51
|
-
if
|
52
|
-
collector
|
53
|
-
|
54
|
-
collector << "#{o.left}"
|
40
|
+
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
41
|
+
collector << "GROUP_CONCAT("
|
42
|
+
collector = visit o.left, collector
|
43
|
+
if o.right
|
44
|
+
collector << ' SEPARATOR '
|
45
|
+
collector = visit o.right, collector
|
55
46
|
end
|
56
|
-
o.other.each { |a|
|
57
|
-
collector << ","
|
58
|
-
if(a.is_a?(Arel::Attributes::Attribute))
|
59
|
-
collector = visit a, collector
|
60
|
-
else
|
61
|
-
collector << "#{a}"
|
62
|
-
end
|
63
|
-
}
|
64
|
-
collector << ")"
|
65
|
-
collector
|
66
|
-
end
|
67
|
-
|
68
|
-
def visit_ArelExtensions_Nodes_Isnull o, collector
|
69
|
-
collector << "IFNULL("
|
70
|
-
collector = visit o.left, collector
|
71
|
-
collector << ","
|
72
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
73
|
-
collector = visit o.right, collector
|
74
|
-
else
|
75
|
-
collector << "'#{o.right}'"
|
76
|
-
end
|
77
|
-
collector << ")"
|
78
|
-
collector
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
def visit_ArelExtensions_Nodes_Replace o, collector
|
83
|
-
collector << "REPLACE("
|
84
|
-
collector = visit o.expr,collector
|
85
|
-
collector << ","
|
86
|
-
if(o.left.is_a?(Arel::Attributes::Attribute))
|
87
|
-
collector = visit o.left, collector
|
88
|
-
else
|
89
|
-
collector << "'#{o.left}'"
|
90
|
-
end
|
91
|
-
collector << ","
|
92
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
93
|
-
collector = visit o.right, collector
|
94
|
-
else
|
95
|
-
collector << "'#{o.right}'"
|
96
|
-
end
|
97
|
-
collector << ")"
|
98
|
-
collector
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
def visit_ArelExtensions_Nodes_Soundex o, collector
|
103
|
-
collector << "SOUNDEX("
|
104
|
-
if((o.expr).is_a?(Arel::Attributes::Attribute))
|
105
|
-
collector = visit o.expr, collector
|
106
|
-
else
|
107
|
-
collector << "'#{o.expr}'"
|
108
|
-
end
|
109
47
|
collector << ")"
|
110
48
|
collector
|
111
49
|
end
|
112
50
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
collector << 'TRIM(BOTH '
|
117
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
118
|
-
collector = visit o.right, collector
|
119
|
-
else
|
120
|
-
collector << "'#{o.right}'"
|
121
|
-
end
|
51
|
+
def visit_ArelExtensions_Nodes_Trim o, collector
|
52
|
+
collector << 'TRIM(' # BOTH
|
53
|
+
collector = visit o.right, collector
|
122
54
|
collector << " FROM "
|
123
55
|
collector = visit o.left, collector
|
124
|
-
|
125
56
|
collector << ")"
|
126
57
|
collector
|
127
58
|
end
|
128
59
|
|
129
60
|
def visit_ArelExtensions_Nodes_Ltrim o , collector
|
130
61
|
collector << 'TRIM(LEADING '
|
131
|
-
|
132
|
-
collector = visit o.right, collector
|
133
|
-
else
|
134
|
-
collector << "'#{o.right}'"
|
135
|
-
end
|
62
|
+
collector = visit o.right, collector
|
136
63
|
collector << " FROM "
|
137
64
|
collector = visit o.left, collector
|
138
|
-
|
139
65
|
collector << ")"
|
140
66
|
collector
|
141
67
|
end
|
142
68
|
|
143
|
-
|
144
69
|
def visit_ArelExtensions_Nodes_Rtrim o , collector
|
145
|
-
|
146
|
-
|
147
|
-
collector = visit o.right, collector
|
148
|
-
else
|
149
|
-
collector << "'#{o.right}'"
|
150
|
-
end
|
70
|
+
collector << 'TRIM(TRAILING '
|
71
|
+
collector = visit o.right, collector
|
151
72
|
collector << " FROM "
|
152
73
|
collector = visit o.left, collector
|
74
|
+
collector << ")"
|
75
|
+
collector
|
76
|
+
end
|
77
|
+
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
78
|
+
collector << "DATEDIFF("
|
79
|
+
collector = visit o.left, collector
|
80
|
+
collector << Arel::Visitors::MySQL::COMMA
|
81
|
+
collector = visit o.right, collector
|
82
|
+
collector << ")"
|
83
|
+
collector
|
84
|
+
end
|
153
85
|
|
86
|
+
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
87
|
+
collector << "DATE_ADD("
|
88
|
+
collector = visit o.left, collector
|
89
|
+
collector << Arel::Visitors::MySQL::COMMA
|
90
|
+
collector = visit o.mysql_value(o.right), collector
|
154
91
|
collector << ")"
|
155
92
|
collector
|
156
93
|
end
|
157
94
|
|
95
|
+
|
96
|
+
def visit_ArelExtensions_Nodes_Duration o, collector
|
97
|
+
#visit left for period
|
98
|
+
if o.left == "d"
|
99
|
+
collector << "DAY("
|
100
|
+
elsif(o.left == "m")
|
101
|
+
collector << "MONTH("
|
102
|
+
elsif (o.left == "w")
|
103
|
+
collector << "WEEK("
|
104
|
+
elsif (o.left == "y")
|
105
|
+
collector << "YEAR("
|
106
|
+
end
|
107
|
+
#visit right
|
108
|
+
collector = visit o.right, collector
|
109
|
+
collector << ")"
|
110
|
+
collector
|
111
|
+
end
|
112
|
+
|
113
|
+
#****************************************************************#
|
114
|
+
|
115
|
+
def visit_ArelExtensions_Nodes_IsNull o, collector
|
116
|
+
collector << "ISNULL("
|
117
|
+
collector = visit o.left, collector
|
118
|
+
if o.right
|
119
|
+
collector << Arel::Visitors::MySQL::COMMA
|
120
|
+
collector = visit o.right, collector
|
121
|
+
end
|
122
|
+
collector << ")"
|
123
|
+
collector
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
def visit_ArelExtensions_Nodes_Replace o, collector
|
128
|
+
collector << "REPLACE("
|
129
|
+
o.expressions.each_with_index { |arg, i|
|
130
|
+
collector << Arel::Visitors::MySQL::COMMA unless i == 0
|
131
|
+
collector = visit arg, collector
|
132
|
+
}
|
133
|
+
collector << ")"
|
134
|
+
collector
|
135
|
+
end
|
136
|
+
|
137
|
+
|
158
138
|
def visit_ArelExtensions_Nodes_Wday o, collector
|
159
139
|
collector << "(WEEKDAY("
|
160
|
-
|
161
|
-
collector = visit o.date, collector
|
162
|
-
else
|
163
|
-
collector << "'#{o.date}'"
|
164
|
-
end
|
140
|
+
collector = visit o.date, collector
|
165
141
|
collector << ") + 1) % 7"
|
166
142
|
collector
|
167
143
|
end
|
@@ -26,47 +26,27 @@ module ArelExtensions
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
collector << "DATEADD("
|
40
|
-
collector = visit o.left, collector
|
41
|
-
collector << ", + interval '#{o.right}' DAY)"
|
42
|
-
else
|
43
|
-
collector << "CONCAT("
|
44
|
-
collector = visit o.left, collector
|
45
|
-
collector << ","
|
46
|
-
collector << "#{o.right})"
|
47
|
-
end
|
48
|
-
collector
|
49
|
-
end
|
50
|
-
|
29
|
+
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
30
|
+
collector << "LISTAGG("
|
31
|
+
collector = visit o.left, collector
|
32
|
+
if o.right
|
33
|
+
collector << Arel::Visitors::Oracle::COMMA
|
34
|
+
collector = visit o.right, collector
|
35
|
+
end
|
36
|
+
collector << ")"
|
37
|
+
collector
|
38
|
+
end
|
51
39
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
if(a.is_a?(Arel::Attributes::Attribute))
|
62
|
-
collector = visit a, collector
|
63
|
-
else
|
64
|
-
collector << "#{a}"
|
40
|
+
def visit_ArelExtensions_Nodes_Coalesce o, collector
|
41
|
+
collector << "COALESCE("
|
42
|
+
collector = visit o.left, collector
|
43
|
+
o.other.each { |a|
|
44
|
+
collector << Arel::Visitors::Oracle::COMMA
|
45
|
+
collector = visit a, collector
|
46
|
+
}
|
47
|
+
collector << ")"
|
48
|
+
collector
|
65
49
|
end
|
66
|
-
}
|
67
|
-
collector << ")"
|
68
|
-
collector
|
69
|
-
end
|
70
50
|
|
71
51
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
72
52
|
collector << '('
|
@@ -90,11 +70,7 @@ module ArelExtensions
|
|
90
70
|
collector << "YEAR("
|
91
71
|
end
|
92
72
|
#visit right
|
93
|
-
|
94
|
-
collector = visit o.right, collector
|
95
|
-
else
|
96
|
-
collector << "'#{o.right}'"
|
97
|
-
end
|
73
|
+
collector = visit o.right, collector
|
98
74
|
collector << ")"
|
99
75
|
collector
|
100
76
|
end
|
@@ -108,25 +84,20 @@ module ArelExtensions
|
|
108
84
|
end
|
109
85
|
|
110
86
|
|
111
|
-
def
|
87
|
+
def visit_ArelExtensions_Nodes_IsNull o, collector
|
112
88
|
collector << "NVL("
|
113
89
|
collector = visit o.left, collector
|
114
|
-
collector <<
|
115
|
-
|
116
|
-
collector = visit o.right, collector
|
117
|
-
else
|
118
|
-
collector << "'#{o.right}'"
|
119
|
-
end
|
90
|
+
collector << Arel::Visitors::Oracle::COMMA
|
91
|
+
collector = visit Arel::Nodes.build_quoted(true), collector
|
120
92
|
collector << ")"
|
121
93
|
collector
|
122
94
|
end
|
123
95
|
|
124
|
-
|
125
96
|
def visit_ArelExtensions_Nodes_Rand o, collector
|
126
97
|
collector << "dbms_random.value("
|
127
98
|
if(o.left != nil && o.right != nil)
|
128
99
|
collector << "'#{o.left}'"
|
129
|
-
collector <<
|
100
|
+
collector << Arel::Visitors::Oracle::COMMA
|
130
101
|
collector << "'#{o.right}'"
|
131
102
|
end
|
132
103
|
collector << ")"
|
@@ -136,18 +107,10 @@ module ArelExtensions
|
|
136
107
|
def visit_ArelExtensions_Nodes_Replace o, collector
|
137
108
|
collector << "REPLACE("
|
138
109
|
collector = visit o.expr,collector
|
139
|
-
collector <<
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
collector << "'#{o.left}'"
|
144
|
-
end
|
145
|
-
collector << ","
|
146
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
147
|
-
collector = visit o.right, collector
|
148
|
-
else
|
149
|
-
collector << "'#{o.right}'"
|
150
|
-
end
|
110
|
+
collector << Arel::Visitors::Oracle::COMMA
|
111
|
+
collector = visit o.left, collector
|
112
|
+
collector << Arel::Visitors::Oracle::COMMA
|
113
|
+
collector = visit o.right, collector
|
151
114
|
collector << ")"
|
152
115
|
collector
|
153
116
|
end
|