arel_extensions 1.3.5 → 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 +21 -16
- data/README.md +13 -125
- data/Rakefile +30 -41
- data/TODO +1 -0
- data/appveyor.yml +22 -51
- data/arel_extensions.gemspec +14 -14
- data/functions.html +3 -3
- data/gemfiles/rails3.gemfile +10 -10
- data/gemfiles/rails4.gemfile +14 -14
- data/gemfiles/rails5_0.gemfile +14 -14
- 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 +21 -21
- data/init/sqlite.sql +0 -0
- data/lib/arel_extensions/attributes.rb +3 -4
- 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 -27
- data/lib/arel_extensions/date_duration.rb +14 -13
- 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 +16 -16
- 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 -42
- data/lib/arel_extensions/nodes/is_null.rb +0 -0
- data/lib/arel_extensions/nodes/json.rb +39 -48
- 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 +7 -5
- 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 +7 -5
- data/lib/arel_extensions/predications.rb +43 -44
- data/lib/arel_extensions/railtie.rb +5 -5
- data/lib/arel_extensions/set_functions.rb +7 -5
- data/lib/arel_extensions/string_functions.rb +29 -58
- 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 +181 -279
- data/lib/arel_extensions/visitors/mysql.rb +210 -280
- data/lib/arel_extensions/visitors/oracle.rb +180 -201
- data/lib/arel_extensions/visitors/oracle12.rb +31 -18
- data/lib/arel_extensions/visitors/postgresql.rb +173 -252
- data/lib/arel_extensions/visitors/sqlite.rb +126 -140
- data/lib/arel_extensions/visitors/to_sql.rb +237 -272
- data/lib/arel_extensions/visitors.rb +59 -75
- data/lib/arel_extensions.rb +31 -159
- data/test/database.yml +7 -15
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +116 -105
- data/test/support/fake_record.rb +3 -3
- data/test/test_comparators.rb +17 -14
- data/test/visitors/test_bulk_insert_oracle.rb +11 -11
- data/test/visitors/test_bulk_insert_sqlite.rb +13 -12
- 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 +361 -578
- data/test/with_ar/insert_agnostic_test.rb +21 -27
- data/test/with_ar/test_bulk_sqlite.rb +16 -17
- data/test/with_ar/test_math_sqlite.rb +26 -26
- data/test/with_ar/test_string_mysql.rb +33 -31
- data/test/with_ar/test_string_sqlite.rb +34 -30
- metadata +22 -29
- data/.github/workflows/ruby.yml +0 -341
- data/gemfiles/rails6.gemfile +0 -30
- data/gemfiles/rails6_1.gemfile +0 -30
- data/gemfiles/rails7.gemfile +0 -23
- data/gemspecs/arel_extensions-v1.gemspec +0 -28
- data/gemspecs/arel_extensions-v2.gemspec +0 -28
- data/generate_gems.sh +0 -15
- data/lib/arel_extensions/aliases.rb +0 -14
- data/lib/arel_extensions/helpers.rb +0 -51
- data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
- data/lib/arel_extensions/nodes/sum.rb +0 -7
- data/lib/arel_extensions/visitors/convert_format.rb +0 -37
- data/test/arelx_test_helper.rb +0 -71
- data/version_v1.rb +0 -3
- data/version_v2.rb +0 -3
|
@@ -1,42 +1,38 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Visitors
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}.freeze
|
|
8
|
-
|
|
9
|
-
DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
|
|
3
|
+
Arel::Visitors::MySQL.class_eval do
|
|
4
|
+
Arel::Visitors::MySQL::COMMA = ", "
|
|
5
|
+
Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
|
|
6
|
+
Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
|
|
10
7
|
'%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
|
|
11
|
-
'%
|
|
12
|
-
'%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%a' => '%a', '%A' => '%W', # day, weekday
|
|
8
|
+
'%d' => '%d', '%e' => '%e', '%j' => '%j', '%w' => '%w', '%A' => '%W', # day, weekday
|
|
13
9
|
'%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
|
|
14
10
|
'%M' => '%i', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => ''
|
|
15
|
-
}
|
|
11
|
+
}
|
|
16
12
|
|
|
17
13
|
|
|
18
|
-
#
|
|
14
|
+
#Math functions
|
|
19
15
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
collector << "LOG10("
|
|
17
|
+
o.expressions.each_with_index { |arg, i|
|
|
18
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
|
19
|
+
collector = visit arg, collector
|
|
20
|
+
}
|
|
21
|
+
collector << ")"
|
|
22
|
+
collector
|
|
27
23
|
end
|
|
28
24
|
|
|
29
25
|
def visit_ArelExtensions_Nodes_Power o, collector
|
|
30
|
-
collector <<
|
|
26
|
+
collector << "POW("
|
|
31
27
|
o.expressions.each_with_index { |arg, i|
|
|
32
|
-
collector << Arel::Visitors::ToSql::COMMA
|
|
28
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
|
33
29
|
collector = visit arg, collector
|
|
34
30
|
}
|
|
35
|
-
collector <<
|
|
31
|
+
collector << ")"
|
|
36
32
|
collector
|
|
37
33
|
end
|
|
38
34
|
|
|
39
|
-
#
|
|
35
|
+
#String functions
|
|
40
36
|
def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
|
|
41
37
|
collector << 'LOWER('
|
|
42
38
|
collector = visit o.left, collector
|
|
@@ -45,9 +41,10 @@ module ArelExtensions
|
|
|
45
41
|
collector << ')'
|
|
46
42
|
if o.escape
|
|
47
43
|
collector << ' ESCAPE '
|
|
48
|
-
|
|
44
|
+
visit o.escape, collector
|
|
45
|
+
else
|
|
46
|
+
collector
|
|
49
47
|
end
|
|
50
|
-
collector
|
|
51
48
|
end
|
|
52
49
|
|
|
53
50
|
def visit_ArelExtensions_Nodes_AiMatches o, collector
|
|
@@ -56,9 +53,10 @@ module ArelExtensions
|
|
|
56
53
|
collector = visit o.right.ai_collate, collector
|
|
57
54
|
if o.escape
|
|
58
55
|
collector << ' ESCAPE '
|
|
59
|
-
|
|
56
|
+
visit o.escape, collector
|
|
57
|
+
else
|
|
58
|
+
collector
|
|
60
59
|
end
|
|
61
|
-
collector
|
|
62
60
|
end
|
|
63
61
|
|
|
64
62
|
def visit_ArelExtensions_Nodes_AiIMatches o, collector
|
|
@@ -67,20 +65,22 @@ module ArelExtensions
|
|
|
67
65
|
collector = visit o.right.ai_collate, collector
|
|
68
66
|
if o.escape
|
|
69
67
|
collector << ' ESCAPE '
|
|
70
|
-
|
|
68
|
+
visit o.escape, collector
|
|
69
|
+
else
|
|
70
|
+
collector
|
|
71
71
|
end
|
|
72
|
-
collector
|
|
73
72
|
end
|
|
74
73
|
|
|
75
74
|
def visit_ArelExtensions_Nodes_SMatches o, collector
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
collector = visit o.left.collate, collector
|
|
76
|
+
collector << ' LIKE '
|
|
77
|
+
collector = visit o.right.collate, collector
|
|
78
|
+
if o.escape
|
|
79
|
+
collector << ' ESCAPE '
|
|
80
|
+
visit o.escape, collector
|
|
81
|
+
else
|
|
82
|
+
collector
|
|
83
|
+
end
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
|
|
@@ -91,146 +91,125 @@ module ArelExtensions
|
|
|
91
91
|
collector << ')'
|
|
92
92
|
if o.escape
|
|
93
93
|
collector << ' ESCAPE '
|
|
94
|
-
|
|
94
|
+
visit o.escape, collector
|
|
95
|
+
else
|
|
96
|
+
collector
|
|
95
97
|
end
|
|
96
|
-
collector
|
|
97
98
|
end
|
|
98
99
|
|
|
99
100
|
def visit_ArelExtensions_Nodes_Collate o, collector
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
when 'latin1', 'utf8'
|
|
101
|
+
case o.expressions.first
|
|
102
|
+
when Arel::Attributes::Attribute
|
|
103
|
+
charset = case o.option
|
|
104
|
+
when 'latin1','utf8'
|
|
105
105
|
o.option
|
|
106
106
|
else
|
|
107
107
|
Arel::Table.engine.connection.charset || 'utf8'
|
|
108
108
|
end
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
else
|
|
110
|
+
charset = (o.option == 'latin1') ? 'latin1' : 'utf8'
|
|
111
|
+
end
|
|
112
112
|
collector = visit o.expressions.first, collector
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
end
|
|
113
|
+
if o.ai
|
|
114
|
+
collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
|
115
|
+
#doesn't work in latin1
|
|
116
|
+
elsif o.ci
|
|
117
|
+
collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
|
|
118
|
+
else
|
|
119
|
+
collector << " COLLATE #{charset}_bin"
|
|
120
|
+
end
|
|
122
121
|
collector
|
|
123
122
|
end
|
|
124
123
|
|
|
125
124
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
|
126
|
-
collector <<
|
|
125
|
+
collector << "CONCAT("
|
|
127
126
|
o.expressions.each_with_index { |arg, i|
|
|
128
|
-
collector << COMMA
|
|
129
|
-
if arg.is_a?(Numeric) || arg.is_a?(Arel::Attributes::Attribute)
|
|
130
|
-
collector <<
|
|
127
|
+
collector << Arel::Visitors::MySQL::COMMA unless i == 0
|
|
128
|
+
if (arg.is_a?(Numeric)) || (arg.is_a?(Arel::Attributes::Attribute))
|
|
129
|
+
collector << "CAST("
|
|
131
130
|
collector = visit arg, collector
|
|
132
|
-
collector <<
|
|
131
|
+
collector << " AS char)"
|
|
133
132
|
else
|
|
134
133
|
collector = visit arg, collector
|
|
135
134
|
end
|
|
136
135
|
}
|
|
137
|
-
collector <<
|
|
136
|
+
collector << ")"
|
|
138
137
|
collector
|
|
139
138
|
end
|
|
140
139
|
|
|
141
140
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
|
142
|
-
collector <<
|
|
141
|
+
collector << "GROUP_CONCAT("
|
|
143
142
|
collector = visit o.left, collector
|
|
144
|
-
if !o.
|
|
143
|
+
if !o.orders.blank?
|
|
145
144
|
collector << ' ORDER BY '
|
|
146
|
-
o.
|
|
147
|
-
collector << Arel::Visitors::ToSql::COMMA
|
|
145
|
+
o.orders.each_with_index do |order,i|
|
|
146
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
|
148
147
|
collector = visit order, collector
|
|
149
148
|
end
|
|
150
149
|
end
|
|
151
|
-
if o.
|
|
150
|
+
if o.right && o.right != 'NULL'
|
|
152
151
|
collector << ' SEPARATOR '
|
|
153
|
-
collector = visit o.
|
|
152
|
+
collector = visit o.right, collector
|
|
154
153
|
end
|
|
155
|
-
collector <<
|
|
154
|
+
collector << ")"
|
|
156
155
|
collector
|
|
157
156
|
end
|
|
158
157
|
|
|
159
158
|
def visit_ArelExtensions_Nodes_Trim o, collector
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
collector << 'TRIM(' # BOTH
|
|
160
|
+
collector = visit o.right, collector
|
|
161
|
+
collector << " FROM "
|
|
162
|
+
collector = visit o.left, collector
|
|
163
|
+
collector << ")"
|
|
164
|
+
collector
|
|
166
165
|
end
|
|
167
166
|
|
|
168
|
-
def visit_ArelExtensions_Nodes_Ltrim o, collector
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
167
|
+
def visit_ArelExtensions_Nodes_Ltrim o , collector
|
|
168
|
+
collector << 'TRIM(LEADING '
|
|
169
|
+
collector = visit o.right, collector
|
|
170
|
+
collector << " FROM "
|
|
171
|
+
collector = visit o.left, collector
|
|
172
|
+
collector << ")"
|
|
173
|
+
collector
|
|
175
174
|
end
|
|
176
175
|
|
|
177
|
-
def visit_ArelExtensions_Nodes_Rtrim o, collector
|
|
176
|
+
def visit_ArelExtensions_Nodes_Rtrim o , collector
|
|
178
177
|
collector << 'TRIM(TRAILING '
|
|
179
178
|
collector = visit o.right, collector
|
|
180
|
-
collector <<
|
|
179
|
+
collector << " FROM "
|
|
181
180
|
collector = visit o.left, collector
|
|
182
|
-
collector <<
|
|
181
|
+
collector << ")"
|
|
183
182
|
collector
|
|
184
183
|
end
|
|
185
184
|
|
|
186
185
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
|
187
|
-
collector <<
|
|
186
|
+
collector << "REPEAT("
|
|
188
187
|
o.expressions.each_with_index { |arg, i|
|
|
189
|
-
collector << Arel::Visitors::ToSql::COMMA
|
|
188
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
|
190
189
|
collector = visit arg, collector
|
|
191
190
|
}
|
|
192
|
-
collector <<
|
|
191
|
+
collector << ")"
|
|
193
192
|
collector
|
|
194
193
|
end
|
|
195
194
|
|
|
196
|
-
def visit_ArelExtensions_Nodes_RegexpReplace o, collector
|
|
197
|
-
if !regexp_replace_supported?
|
|
198
|
-
warn('Warning: ArelExtensions: REGEXP_REPLACE does not seem to be available in the current version of the DBMS, it might crash')
|
|
199
|
-
end
|
|
200
|
-
super(o, collector)
|
|
201
|
-
end
|
|
202
|
-
|
|
203
195
|
def visit_ArelExtensions_Nodes_Format o, collector
|
|
204
196
|
case o.col_type
|
|
205
|
-
when :date, :datetime
|
|
206
|
-
|
|
207
|
-
collector << 'DATE_FORMAT('
|
|
208
|
-
collector << 'CONVERT_TZ(' if o.time_zone
|
|
197
|
+
when :date, :datetime
|
|
198
|
+
collector << "DATE_FORMAT("
|
|
209
199
|
collector = visit o.left, collector
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
collector << COMMA
|
|
216
|
-
collector = visit Arel.quoted(dst_tz), collector
|
|
217
|
-
collector << ')'
|
|
218
|
-
when String
|
|
219
|
-
collector << COMMA << "'UTC'" << COMMA
|
|
220
|
-
collector = visit Arel.quoted(o.time_zone), collector
|
|
221
|
-
collector << ')'
|
|
222
|
-
end
|
|
223
|
-
collector << COMMA
|
|
224
|
-
collector = visit Arel.quoted(fmt), collector
|
|
225
|
-
collector << ')'
|
|
200
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
201
|
+
f = o.iso_format.dup
|
|
202
|
+
Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
|
|
203
|
+
collector = visit Arel::Nodes.build_quoted(f), collector
|
|
204
|
+
collector << ")"
|
|
226
205
|
when :integer, :float, :decimal
|
|
227
|
-
collector <<
|
|
206
|
+
collector << "FORMAT("
|
|
228
207
|
collector = visit o.left, collector
|
|
229
208
|
collector << Arel::Visitors::ToSql::COMMA
|
|
230
209
|
collector << '2'
|
|
231
210
|
collector << Arel::Visitors::ToSql::COMMA
|
|
232
211
|
collector = visit o.right, collector
|
|
233
|
-
collector <<
|
|
212
|
+
collector << ")"
|
|
234
213
|
else
|
|
235
214
|
collector = visit o.left, collector
|
|
236
215
|
end
|
|
@@ -238,17 +217,16 @@ module ArelExtensions
|
|
|
238
217
|
end
|
|
239
218
|
|
|
240
219
|
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
end
|
|
220
|
+
if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
|
|
221
|
+
collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
|
|
222
|
+
'TIMESTAMPDIFF(SECOND, '
|
|
223
|
+
else
|
|
224
|
+
'DATEDIFF('
|
|
225
|
+
end
|
|
248
226
|
collector = visit o.right, collector
|
|
249
|
-
collector << COMMA
|
|
227
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
250
228
|
collector = visit o.left, collector
|
|
251
|
-
collector <<
|
|
229
|
+
collector << ")"
|
|
252
230
|
else
|
|
253
231
|
collector << '('
|
|
254
232
|
collector = visit o.left, collector
|
|
@@ -268,92 +246,101 @@ module ArelExtensions
|
|
|
268
246
|
end
|
|
269
247
|
|
|
270
248
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
|
271
|
-
collector <<
|
|
249
|
+
collector << "DATE_ADD("
|
|
272
250
|
collector = visit o.left, collector
|
|
273
|
-
collector << COMMA
|
|
251
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
274
252
|
collector = visit o.mysql_value(o.right), collector
|
|
275
|
-
collector <<
|
|
253
|
+
collector << ")"
|
|
276
254
|
collector
|
|
277
255
|
end
|
|
278
256
|
|
|
257
|
+
|
|
279
258
|
def visit_ArelExtensions_Nodes_Duration o, collector
|
|
280
259
|
if o.left == 'wd'
|
|
281
|
-
collector <<
|
|
260
|
+
collector << "(WEEKDAY("
|
|
282
261
|
collector = visit o.right, collector
|
|
283
|
-
collector <<
|
|
262
|
+
collector << ") + 1) % 7"
|
|
284
263
|
else
|
|
285
264
|
if o.with_interval
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
265
|
+
case o.left
|
|
266
|
+
when 'd','m','y'
|
|
267
|
+
interval = 'DAY'
|
|
268
|
+
when 'h','mn','s'
|
|
269
|
+
interval = 'SECOND'
|
|
270
|
+
when /i\z/
|
|
271
|
+
interval = Arel::Visitors::MySQL::DATE_MAPPING[o.left[0..-2]]
|
|
272
|
+
else
|
|
273
|
+
interval = nil
|
|
274
|
+
end
|
|
295
275
|
end
|
|
296
|
-
collector <<
|
|
297
|
-
collector << "#{DATE_MAPPING[o.left]}("
|
|
276
|
+
collector << " INTERVAL " if o.with_interval && interval
|
|
277
|
+
collector << "#{Arel::Visitors::MySQL::DATE_MAPPING[o.left]}("
|
|
298
278
|
collector = visit o.right, collector
|
|
299
|
-
collector <<
|
|
279
|
+
collector << ")"
|
|
300
280
|
collector << " #{interval} " if o.with_interval && interval
|
|
301
281
|
end
|
|
302
282
|
collector
|
|
303
283
|
end
|
|
304
284
|
|
|
285
|
+
|
|
305
286
|
def visit_ArelExtensions_Nodes_IsNull o, collector
|
|
306
|
-
collector <<
|
|
287
|
+
collector << "ISNULL("
|
|
307
288
|
collector = visit o.expr, collector
|
|
308
|
-
collector <<
|
|
289
|
+
collector << ")"
|
|
309
290
|
collector
|
|
310
291
|
end
|
|
311
292
|
|
|
312
293
|
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
|
313
|
-
|
|
294
|
+
collector << "NOT ISNULL("
|
|
314
295
|
collector = visit o.expr, collector
|
|
315
|
-
collector <<
|
|
296
|
+
collector << ")"
|
|
316
297
|
collector
|
|
317
298
|
end
|
|
318
299
|
|
|
319
300
|
def visit_ArelExtensions_Nodes_Wday o, collector
|
|
320
|
-
collector <<
|
|
301
|
+
collector << "(WEEKDAY("
|
|
321
302
|
collector = visit o.date, collector
|
|
322
|
-
collector <<
|
|
303
|
+
collector << ") + 1) % 7"
|
|
323
304
|
collector
|
|
324
305
|
end
|
|
325
306
|
|
|
326
307
|
def visit_ArelExtensions_Nodes_Cast o, collector
|
|
327
|
-
|
|
328
|
-
case o.as_attr
|
|
329
|
-
when :binary then 'binary'
|
|
330
|
-
when :date then 'date'
|
|
331
|
-
when :datetime then 'datetime'
|
|
332
|
-
when :int then 'signed'
|
|
333
|
-
when :number, :decimal then 'decimal(20,6)'
|
|
334
|
-
when :string then 'char'
|
|
335
|
-
when :time then 'time'
|
|
336
|
-
else o.as_attr.to_s
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
collector << 'CAST('
|
|
308
|
+
collector << "CAST("
|
|
340
309
|
collector = visit o.left, collector
|
|
341
|
-
collector <<
|
|
342
|
-
|
|
343
|
-
|
|
310
|
+
collector << " AS "
|
|
311
|
+
case o.as_attr
|
|
312
|
+
when :string
|
|
313
|
+
as_attr = Arel::Nodes::SqlLiteral.new('char')
|
|
314
|
+
when :time
|
|
315
|
+
as_attr = Arel::Nodes::SqlLiteral.new('time')
|
|
316
|
+
when :int
|
|
317
|
+
as_attr = Arel::Nodes::SqlLiteral.new('signed')
|
|
318
|
+
when :number, :decimal
|
|
319
|
+
as_attr = Arel::Nodes::SqlLiteral.new('decimal(20,6)')
|
|
320
|
+
when :datetime
|
|
321
|
+
as_attr = Arel::Nodes::SqlLiteral.new('datetime')
|
|
322
|
+
when :date
|
|
323
|
+
as_attr = Arel::Nodes::SqlLiteral.new('date')
|
|
324
|
+
when :binary
|
|
325
|
+
as_attr = Arel::Nodes::SqlLiteral.new('binary')
|
|
326
|
+
else
|
|
327
|
+
as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
|
|
328
|
+
end
|
|
329
|
+
collector = visit as_attr, collector
|
|
330
|
+
collector << ")"
|
|
344
331
|
collector
|
|
345
332
|
end
|
|
346
333
|
|
|
347
|
-
alias_method
|
|
334
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
|
348
335
|
def visit_Arel_Nodes_SelectStatement o, collector
|
|
349
336
|
if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
|
|
350
337
|
o = o.dup
|
|
351
338
|
o.orders = []
|
|
352
339
|
end
|
|
353
|
-
old_visit_Arel_Nodes_SelectStatement(o,
|
|
340
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
|
354
341
|
end
|
|
355
342
|
|
|
356
|
-
alias_method
|
|
343
|
+
alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
|
|
357
344
|
def visit_Arel_Nodes_As o, collector
|
|
358
345
|
if o.left.is_a?(Arel::Nodes::Binary)
|
|
359
346
|
collector << '('
|
|
@@ -362,56 +349,44 @@ module ArelExtensions
|
|
|
362
349
|
else
|
|
363
350
|
collector = visit o.left, collector
|
|
364
351
|
end
|
|
365
|
-
collector <<
|
|
366
|
-
|
|
367
|
-
# sometimes these values are already quoted, if they are, don't double quote it
|
|
368
|
-
quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '`' && o.right[-1] != '`'
|
|
369
|
-
|
|
370
|
-
collector << '`' if quote
|
|
352
|
+
collector << " AS `"
|
|
371
353
|
collector = visit o.right, collector
|
|
372
|
-
collector <<
|
|
373
|
-
|
|
354
|
+
collector << "`"
|
|
374
355
|
collector
|
|
375
356
|
end
|
|
376
357
|
|
|
377
358
|
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
|
378
359
|
col = o.left.coalesce(0)
|
|
379
|
-
params = o.locale ? [o.precision,
|
|
380
|
-
sign =
|
|
360
|
+
params = o.locale ? [o.precision,Arel::Nodes.build_quoted(o.locale)] : [o.precision]
|
|
361
|
+
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
|
381
362
|
then('-').
|
|
382
363
|
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
|
383
364
|
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
|
384
365
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
Arel::Nodes
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
0
|
|
395
|
-
])
|
|
366
|
+
if o.scientific_notation
|
|
367
|
+
number = ArelExtensions::Nodes::Concat.new([
|
|
368
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
|
369
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
|
|
370
|
+
]+params),
|
|
371
|
+
o.type,
|
|
372
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
|
373
|
+
col.abs.log10.floor,
|
|
374
|
+
0
|
|
396
375
|
])
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
376
|
+
])
|
|
377
|
+
else
|
|
378
|
+
number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
|
|
379
|
+
end
|
|
400
380
|
|
|
401
|
-
repeated_char =
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
Arel
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
)
|
|
411
|
-
.else('')
|
|
412
|
-
end
|
|
413
|
-
before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
|
414
|
-
middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
|
381
|
+
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
|
382
|
+
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
|
383
|
+
then(Arel::Nodes.build_quoted(
|
|
384
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
|
385
|
+
).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
|
|
386
|
+
).
|
|
387
|
+
else('')
|
|
388
|
+
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
|
389
|
+
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
|
415
390
|
after = o.flags.include?('-') ? repeated_char : ''
|
|
416
391
|
full_number = ArelExtensions::Nodes::Concat.new([
|
|
417
392
|
before,
|
|
@@ -420,97 +395,52 @@ module ArelExtensions
|
|
|
420
395
|
number,
|
|
421
396
|
after
|
|
422
397
|
])
|
|
423
|
-
collector = visit ArelExtensions::Nodes::Concat.new([Arel.
|
|
424
|
-
collector
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
def visit_Aggregate_For_AggregateFunction o, collector
|
|
428
|
-
if !window_supported?
|
|
429
|
-
warn('Warning: ArelExtensions: Window Functions are not available in the current version of the DBMS.')
|
|
430
|
-
return collector
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
if !o.order.empty? || !o.group.empty?
|
|
434
|
-
collector << ' OVER ('
|
|
435
|
-
if !o.group.empty?
|
|
436
|
-
collector << ' PARTITION BY ('
|
|
437
|
-
visit o.group, collector
|
|
438
|
-
collector << ')'
|
|
439
|
-
end
|
|
440
|
-
if !o.order.empty?
|
|
441
|
-
collector << ' ORDER BY ('
|
|
442
|
-
visit o.order, collector
|
|
443
|
-
collector << ')'
|
|
444
|
-
end
|
|
445
|
-
collector << ')'
|
|
446
|
-
end
|
|
398
|
+
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
|
447
399
|
collector
|
|
448
400
|
end
|
|
449
401
|
|
|
450
402
|
def visit_ArelExtensions_Nodes_Std o, collector
|
|
451
|
-
collector << (o.unbiased_estimator ?
|
|
403
|
+
collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
|
|
452
404
|
visit o.left, collector
|
|
453
|
-
collector <<
|
|
454
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
|
405
|
+
collector << ")"
|
|
455
406
|
collector
|
|
456
407
|
end
|
|
457
408
|
|
|
458
409
|
def visit_ArelExtensions_Nodes_Variance o, collector
|
|
459
|
-
collector << (o.unbiased_estimator ?
|
|
410
|
+
collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
|
|
460
411
|
visit o.left, collector
|
|
461
|
-
collector <<
|
|
462
|
-
visit_Aggregate_For_AggregateFunction o, collector
|
|
412
|
+
collector << ")"
|
|
463
413
|
collector
|
|
464
414
|
end
|
|
465
415
|
|
|
466
|
-
# JSON if implemented only after 10.2.3
|
|
416
|
+
# JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
|
|
467
417
|
def json_supported?
|
|
468
|
-
|
|
418
|
+
Arel::Table.engine.connection.send(:mariadb?) &&
|
|
419
|
+
Arel::Table.engine.connection.send(:version) >= '10.2.3' ||
|
|
420
|
+
!Arel::Table.engine.connection.send(:mariadb?) &&
|
|
421
|
+
Arel::Table.engine.connection.send(:version) >= '5.7.0'
|
|
469
422
|
end
|
|
470
423
|
|
|
471
|
-
def
|
|
472
|
-
version_supported?('10.2.3', '8.0')
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
def regexp_replace_supported?
|
|
476
|
-
version_supported?('10.0.5', '8.0')
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
def version_supported?(mariadb_v = '10.2.3', mysql_v = '5.7.0')
|
|
480
|
-
conn = Arel::Table.engine.connection
|
|
481
|
-
conn.send(:mariadb?) && \
|
|
482
|
-
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v || \
|
|
483
|
-
conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
|
|
484
|
-
conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
|
|
485
|
-
!conn.send(:mariadb?) && \
|
|
486
|
-
(conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
|
|
487
|
-
conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
|
|
488
|
-
conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
|
|
489
|
-
# ideally we should parse the instance_variable @full_version because @version contains only the supposedly
|
|
490
|
-
# corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
def visit_ArelExtensions_Nodes_Json o, collector
|
|
424
|
+
def visit_ArelExtensions_Nodes_Json o,collector
|
|
494
425
|
return super if !json_supported?
|
|
495
|
-
|
|
496
426
|
case o.dict
|
|
497
427
|
when Array
|
|
498
428
|
collector << 'JSON_ARRAY('
|
|
499
|
-
o.dict.each.with_index do |v,
|
|
429
|
+
o.dict.each.with_index do |v,i|
|
|
500
430
|
if i != 0
|
|
501
|
-
collector << COMMA
|
|
431
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
502
432
|
end
|
|
503
433
|
collector = visit v, collector
|
|
504
434
|
end
|
|
505
435
|
collector << ')'
|
|
506
436
|
when Hash
|
|
507
437
|
collector << 'JSON_OBJECT('
|
|
508
|
-
o.dict.each.with_index do |(k,
|
|
438
|
+
o.dict.each.with_index do |(k,v),i|
|
|
509
439
|
if i != 0
|
|
510
|
-
collector << COMMA
|
|
440
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
511
441
|
end
|
|
512
442
|
collector = visit k, collector
|
|
513
|
-
collector << COMMA
|
|
443
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
514
444
|
collector = visit v, collector
|
|
515
445
|
end
|
|
516
446
|
collector << ')'
|
|
@@ -520,11 +450,11 @@ module ArelExtensions
|
|
|
520
450
|
collector
|
|
521
451
|
end
|
|
522
452
|
|
|
523
|
-
def visit_ArelExtensions_Nodes_JsonMerge o,
|
|
453
|
+
def visit_ArelExtensions_Nodes_JsonMerge o,collector
|
|
524
454
|
collector << 'JSON_MERGE_PATCH('
|
|
525
|
-
o.expressions.each.with_index do |v,
|
|
455
|
+
o.expressions.each.with_index do |v,i|
|
|
526
456
|
if i != 0
|
|
527
|
-
collector << COMMA
|
|
457
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
528
458
|
end
|
|
529
459
|
collector = visit v, collector
|
|
530
460
|
end
|
|
@@ -532,29 +462,29 @@ module ArelExtensions
|
|
|
532
462
|
collector
|
|
533
463
|
end
|
|
534
464
|
|
|
535
|
-
def visit_ArelExtensions_Nodes_JsonGet o,
|
|
465
|
+
def visit_ArelExtensions_Nodes_JsonGet o,collector
|
|
536
466
|
collector << 'JSON_EXTRACT('
|
|
537
467
|
collector = visit o.dict, collector
|
|
538
|
-
collector << COMMA
|
|
468
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
539
469
|
if o.key.is_a?(Integer)
|
|
540
470
|
collector << "\"$[#{o.key}]\""
|
|
541
471
|
else
|
|
542
|
-
collector = visit Arel.
|
|
472
|
+
collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
|
|
543
473
|
end
|
|
544
474
|
collector << ')'
|
|
545
475
|
collector
|
|
546
476
|
end
|
|
547
477
|
|
|
548
|
-
def visit_ArelExtensions_Nodes_JsonSet o,
|
|
478
|
+
def visit_ArelExtensions_Nodes_JsonSet o,collector
|
|
549
479
|
collector << 'JSON_SET('
|
|
550
480
|
collector = visit o.dict, collector
|
|
551
|
-
collector << COMMA
|
|
481
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
552
482
|
if o.key.is_a?(Integer)
|
|
553
483
|
collector << "\"$[#{o.key}]\""
|
|
554
484
|
else
|
|
555
|
-
collector = visit Arel.
|
|
485
|
+
collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
|
|
556
486
|
end
|
|
557
|
-
collector << COMMA
|
|
487
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
558
488
|
collector = visit o.value, collector
|
|
559
489
|
collector << ')'
|
|
560
490
|
collector
|
|
@@ -562,7 +492,6 @@ module ArelExtensions
|
|
|
562
492
|
|
|
563
493
|
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
|
564
494
|
return super if !json_supported?
|
|
565
|
-
|
|
566
495
|
if o.as_array
|
|
567
496
|
collector << 'JSON_ARRAYAGG('
|
|
568
497
|
collector = visit o.dict, collector
|
|
@@ -571,13 +500,13 @@ module ArelExtensions
|
|
|
571
500
|
case o.dict
|
|
572
501
|
when Hash
|
|
573
502
|
collector << 'JSON_MERGE_PATCH(' if o.dict.length > 1
|
|
574
|
-
o.dict.each.with_index do |(k,
|
|
503
|
+
o.dict.each.with_index do |(k,v),i|
|
|
575
504
|
if i != 0
|
|
576
|
-
collector << COMMA
|
|
505
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
577
506
|
end
|
|
578
507
|
collector << 'JSON_OBJECTAGG('
|
|
579
508
|
collector = visit k, collector
|
|
580
|
-
collector << COMMA
|
|
509
|
+
collector << Arel::Visitors::MySQL::COMMA
|
|
581
510
|
collector = visit v, collector
|
|
582
511
|
collector << ')'
|
|
583
512
|
end
|
|
@@ -590,6 +519,7 @@ module ArelExtensions
|
|
|
590
519
|
end
|
|
591
520
|
collector
|
|
592
521
|
end
|
|
522
|
+
|
|
593
523
|
end
|
|
594
524
|
end
|
|
595
525
|
end
|