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
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
module ArelExtensions
|
|
2
2
|
module Visitors
|
|
3
3
|
module MSSQL
|
|
4
|
-
|
|
5
4
|
MSSQL_CLASS_NAMES = %i[MSSQL SQLServer].freeze
|
|
6
5
|
|
|
7
6
|
mssql_class =
|
|
8
7
|
Arel::Visitors
|
|
9
8
|
.constants
|
|
10
|
-
.select { |c| Arel::Visitors.const_get(c).is_a?(Class)
|
|
9
|
+
.select { |c| Arel::Visitors.const_get(c).is_a?(Class) }
|
|
11
10
|
.find { |c| MSSQL_CLASS_NAMES.include?(c) }
|
|
12
11
|
|
|
13
12
|
# This guard is necessary because:
|
|
@@ -47,7 +46,7 @@ module ArelExtensions
|
|
|
47
46
|
Regexp.new(
|
|
48
47
|
LOADED_VISITOR::DATE_FORMAT_DIRECTIVES
|
|
49
48
|
.keys
|
|
50
|
-
.map{|k| Regexp.escape(k)}
|
|
49
|
+
.map { |k| Regexp.escape(k) }
|
|
51
50
|
.join('|')
|
|
52
51
|
).freeze
|
|
53
52
|
|
|
@@ -59,7 +58,7 @@ module ArelExtensions
|
|
|
59
58
|
'MM-DD-YYYY' => 110,
|
|
60
59
|
'YYYY/MM/DD' => 111,
|
|
61
60
|
'DD-MM-YYYY' => 105,
|
|
62
|
-
'DD-MM-YY'
|
|
61
|
+
'DD-MM-YY' => 5,
|
|
63
62
|
'DD.MM.YYYY' => 104,
|
|
64
63
|
'YYYY-MM-DDTHH:MM:SS:MMM' => 126
|
|
65
64
|
}.freeze
|
|
@@ -76,7 +75,7 @@ module ArelExtensions
|
|
|
76
75
|
# The following is adapted from
|
|
77
76
|
# https://github.com/rails/rails/blob/main/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
|
|
78
77
|
#
|
|
79
|
-
if RUBY_PLATFORM == 'java' &&
|
|
78
|
+
if RUBY_PLATFORM == 'java' && AREL_VERSION <= V6
|
|
80
79
|
def quote_string(s)
|
|
81
80
|
s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
|
|
82
81
|
end
|
|
@@ -89,15 +88,15 @@ module ArelExtensions
|
|
|
89
88
|
if value.acts_like?(:time)
|
|
90
89
|
if (ActiveRecord.respond_to?(:default_timezone) && ActiveRecord.default_timezone == :utc) || ActiveRecord::Base.default_timezone == :utc
|
|
91
90
|
value = value.getutc if value.respond_to?(:getutc) && !value.utc?
|
|
92
|
-
|
|
93
|
-
value = value.getlocal
|
|
91
|
+
elsif value.respond_to?(:getlocal)
|
|
92
|
+
value = value.getlocal
|
|
94
93
|
end
|
|
95
94
|
end
|
|
96
95
|
# new versions of AR use `to_fs`, but we want max compatibility, and we're
|
|
97
96
|
# not going to write it over and over, so it's fine like that.
|
|
98
97
|
result = value.to_formatted_s(:db)
|
|
99
98
|
if value.respond_to?(:usec) && value.usec > 0
|
|
100
|
-
result << '.' <<
|
|
99
|
+
result << '.' << format('%06d', value.usec)
|
|
101
100
|
else
|
|
102
101
|
result
|
|
103
102
|
end
|
|
@@ -113,10 +112,10 @@ module ArelExtensions
|
|
|
113
112
|
|
|
114
113
|
def quoted_time(value) # :nodoc:
|
|
115
114
|
value = value.change(year: 2000, month: 1, day: 1)
|
|
116
|
-
quoted_date(value).sub(/\A\d{4}-\d{2}-\d{2} /,
|
|
115
|
+
quoted_date(value).sub(/\A\d{4}-\d{2}-\d{2} /, '')
|
|
117
116
|
end
|
|
118
117
|
|
|
119
|
-
def quote
|
|
118
|
+
def quote(value, _column = nil)
|
|
120
119
|
case value
|
|
121
120
|
when Arel::Nodes::SqlLiteral
|
|
122
121
|
value
|
|
@@ -133,7 +132,7 @@ module ArelExtensions
|
|
|
133
132
|
value.to_s('F')
|
|
134
133
|
when Numeric, ActiveSupport::Duration
|
|
135
134
|
value.to_s
|
|
136
|
-
when
|
|
135
|
+
when AREL_VERSION > V6 && ActiveRecord::Type::Time::Value
|
|
137
136
|
"'#{quoted_time(value)}'"
|
|
138
137
|
when Date, Time
|
|
139
138
|
"'#{quoted_date(value)}'"
|
|
@@ -145,8 +144,8 @@ module ArelExtensions
|
|
|
145
144
|
end
|
|
146
145
|
end
|
|
147
146
|
|
|
148
|
-
|
|
149
|
-
def primary_Key_From_Table
|
|
147
|
+
alias old_primary_Key_From_Table primary_Key_From_Table rescue nil
|
|
148
|
+
def primary_Key_From_Table(t)
|
|
150
149
|
return unless t
|
|
151
150
|
|
|
152
151
|
column_name = @connection.schema_cache.primary_keys(t.name) ||
|
|
@@ -155,48 +154,48 @@ module ArelExtensions
|
|
|
155
154
|
end
|
|
156
155
|
|
|
157
156
|
# Math Functions
|
|
158
|
-
def visit_ArelExtensions_Nodes_Ceil
|
|
157
|
+
def visit_ArelExtensions_Nodes_Ceil(o, collector)
|
|
159
158
|
collector << 'CEILING('
|
|
160
159
|
collector = visit o.expr, collector
|
|
161
160
|
collector << ')'
|
|
162
161
|
collector
|
|
163
162
|
end
|
|
164
163
|
|
|
165
|
-
def visit_ArelExtensions_Nodes_Log10
|
|
164
|
+
def visit_ArelExtensions_Nodes_Log10(o, collector)
|
|
166
165
|
collector << 'LOG10('
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
o.expressions.each_with_index { |arg, i|
|
|
167
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
|
168
|
+
collector = visit arg, collector
|
|
169
|
+
}
|
|
170
|
+
collector << ')'
|
|
171
|
+
collector
|
|
173
172
|
end
|
|
174
173
|
|
|
175
|
-
def visit_ArelExtensions_Nodes_Power
|
|
174
|
+
def visit_ArelExtensions_Nodes_Power(o, collector)
|
|
176
175
|
collector << 'POWER('
|
|
177
176
|
o.expressions.each_with_index { |arg, i|
|
|
178
|
-
collector <<
|
|
177
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
|
179
178
|
collector = visit arg, collector
|
|
180
179
|
}
|
|
181
180
|
collector << ')'
|
|
182
181
|
collector
|
|
183
182
|
end
|
|
184
183
|
|
|
185
|
-
def visit_ArelExtensions_Nodes_IsNull
|
|
184
|
+
def visit_ArelExtensions_Nodes_IsNull(o, collector)
|
|
186
185
|
collector << '('
|
|
187
186
|
collector = visit o.expr, collector
|
|
188
187
|
collector << ' IS NULL)'
|
|
189
188
|
collector
|
|
190
189
|
end
|
|
191
190
|
|
|
192
|
-
def visit_ArelExtensions_Nodes_IsNotNull
|
|
191
|
+
def visit_ArelExtensions_Nodes_IsNotNull(o, collector)
|
|
193
192
|
collector << '('
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
collector = visit o.expr, collector
|
|
194
|
+
collector << ' IS NOT NULL)'
|
|
195
|
+
collector
|
|
197
196
|
end
|
|
198
197
|
|
|
199
|
-
def visit_ArelExtensions_Nodes_Concat
|
|
198
|
+
def visit_ArelExtensions_Nodes_Concat(o, collector)
|
|
200
199
|
collector << 'CONCAT('
|
|
201
200
|
o.expressions.each_with_index { |arg, i|
|
|
202
201
|
collector << LOADED_VISITOR::COMMA if i != 0
|
|
@@ -206,25 +205,23 @@ module ArelExtensions
|
|
|
206
205
|
collector
|
|
207
206
|
end
|
|
208
207
|
|
|
209
|
-
def visit_ArelExtensions_Nodes_Repeat
|
|
208
|
+
def visit_ArelExtensions_Nodes_Repeat(o, collector)
|
|
210
209
|
collector << 'REPLICATE('
|
|
211
210
|
o.expressions.each_with_index { |arg, i|
|
|
212
|
-
collector <<
|
|
211
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
|
213
212
|
collector = visit arg, collector
|
|
214
213
|
}
|
|
215
214
|
collector << ')'
|
|
216
215
|
collector
|
|
217
216
|
end
|
|
218
217
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def visit_ArelExtensions_Nodes_DateDiff o, collector
|
|
218
|
+
def visit_ArelExtensions_Nodes_DateDiff(o, collector)
|
|
222
219
|
case o.right_node_type
|
|
223
220
|
when :ruby_date, :ruby_time, :date, :datetime, :time
|
|
224
221
|
collector << case o.left_node_type
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
when :ruby_time, :datetime, :time then 'DATEDIFF(second'
|
|
223
|
+
else 'DATEDIFF(day'
|
|
224
|
+
end
|
|
228
225
|
collector << LOADED_VISITOR::COMMA
|
|
229
226
|
collector = visit o.right, collector
|
|
230
227
|
collector << LOADED_VISITOR::COMMA
|
|
@@ -246,7 +243,7 @@ module ArelExtensions
|
|
|
246
243
|
collector
|
|
247
244
|
end
|
|
248
245
|
|
|
249
|
-
def visit_ArelExtensions_Nodes_DateAdd
|
|
246
|
+
def visit_ArelExtensions_Nodes_DateAdd(o, collector)
|
|
250
247
|
collector << 'DATEADD('
|
|
251
248
|
collector = visit o.mssql_datepart(o.right), collector
|
|
252
249
|
collector << LOADED_VISITOR::COMMA
|
|
@@ -257,7 +254,7 @@ module ArelExtensions
|
|
|
257
254
|
collector
|
|
258
255
|
end
|
|
259
256
|
|
|
260
|
-
def visit_ArelExtensions_Nodes_Duration
|
|
257
|
+
def visit_ArelExtensions_Nodes_Duration(o, collector)
|
|
261
258
|
if o.with_interval && o.left.end_with?('i')
|
|
262
259
|
collector = visit o.right, collector
|
|
263
260
|
else
|
|
@@ -274,7 +271,24 @@ module ArelExtensions
|
|
|
274
271
|
collector
|
|
275
272
|
end
|
|
276
273
|
|
|
277
|
-
def
|
|
274
|
+
def visit_ArelExtensions_Nodes_ByteSize(o, collector)
|
|
275
|
+
collector << 'DATALENGTH(CAST('
|
|
276
|
+
collector = visit o.expr.coalesce(''), collector
|
|
277
|
+
collector << ' AS VARCHAR(MAX)))'
|
|
278
|
+
collector
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def visit_ArelExtensions_Nodes_CharLength(o, collector)
|
|
282
|
+
# According to the docs https://learn.microsoft.com/en-us/sql/t-sql/functions/len-transact-sql?view=sql-server-ver17
|
|
283
|
+
# LEN doesn't take into account the trailing white space, and that's why
|
|
284
|
+
# we need to do acrobatics.
|
|
285
|
+
collector << 'LEN('
|
|
286
|
+
collector = visit o.expr.coalesce(''), collector
|
|
287
|
+
collector << " + 'x') - 1"
|
|
288
|
+
collector
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def visit_ArelExtensions_Nodes_Length(o, collector)
|
|
278
292
|
if o.bytewise
|
|
279
293
|
collector << '(DATALENGTH('
|
|
280
294
|
collector = visit o.expr, collector
|
|
@@ -290,7 +304,7 @@ module ArelExtensions
|
|
|
290
304
|
end
|
|
291
305
|
end
|
|
292
306
|
|
|
293
|
-
def visit_ArelExtensions_Nodes_Round
|
|
307
|
+
def visit_ArelExtensions_Nodes_Round(o, collector)
|
|
294
308
|
collector << 'ROUND('
|
|
295
309
|
o.expressions.each_with_index { |arg, i|
|
|
296
310
|
collector << LOADED_VISITOR::COMMA if i != 0
|
|
@@ -304,7 +318,7 @@ module ArelExtensions
|
|
|
304
318
|
collector
|
|
305
319
|
end
|
|
306
320
|
|
|
307
|
-
def visit_ArelExtensions_Nodes_Locate
|
|
321
|
+
def visit_ArelExtensions_Nodes_Locate(o, collector)
|
|
308
322
|
collector << 'CHARINDEX('
|
|
309
323
|
collector = visit o.right, collector
|
|
310
324
|
collector << LOADED_VISITOR::COMMA
|
|
@@ -313,7 +327,9 @@ module ArelExtensions
|
|
|
313
327
|
collector
|
|
314
328
|
end
|
|
315
329
|
|
|
316
|
-
def visit_ArelExtensions_Nodes_Substring
|
|
330
|
+
def visit_ArelExtensions_Nodes_Substring(o, collector)
|
|
331
|
+
return visit(o.range_substring_node, collector) if o.range?
|
|
332
|
+
|
|
317
333
|
collector << 'SUBSTRING('
|
|
318
334
|
collector = visit o.expressions[0], collector
|
|
319
335
|
collector << LOADED_VISITOR::COMMA
|
|
@@ -324,24 +340,24 @@ module ArelExtensions
|
|
|
324
340
|
collector
|
|
325
341
|
end
|
|
326
342
|
|
|
327
|
-
def visit_ArelExtensions_Nodes_Trim
|
|
343
|
+
def visit_ArelExtensions_Nodes_Trim(o, collector)
|
|
328
344
|
# NOTE: in MSSQL's `blank`, o.right is the space char so we need to
|
|
329
345
|
# account for it.
|
|
330
346
|
if o.right && !/\A\s\Z/.match(o.right.expr)
|
|
331
347
|
collector << 'dbo.TrimChar('
|
|
332
348
|
collector = visit o.left, collector
|
|
333
|
-
collector <<
|
|
349
|
+
collector << LOADED_VISITOR::COMMA
|
|
334
350
|
collector = visit o.right, collector
|
|
335
351
|
collector << ')'
|
|
336
352
|
else
|
|
337
|
-
collector <<
|
|
353
|
+
collector << 'LTRIM(RTRIM('
|
|
338
354
|
collector = visit o.left, collector
|
|
339
|
-
collector <<
|
|
355
|
+
collector << '))'
|
|
340
356
|
end
|
|
341
357
|
collector
|
|
342
358
|
end
|
|
343
359
|
|
|
344
|
-
def visit_ArelExtensions_Nodes_Ltrim
|
|
360
|
+
def visit_ArelExtensions_Nodes_Ltrim(o, collector)
|
|
345
361
|
if o.right
|
|
346
362
|
collector << 'REPLACE(REPLACE(LTRIM(REPLACE(REPLACE('
|
|
347
363
|
collector = visit o.left, collector
|
|
@@ -358,7 +374,7 @@ module ArelExtensions
|
|
|
358
374
|
collector
|
|
359
375
|
end
|
|
360
376
|
|
|
361
|
-
def visit_ArelExtensions_Nodes_Rtrim
|
|
377
|
+
def visit_ArelExtensions_Nodes_Rtrim(o, collector)
|
|
362
378
|
if o.right
|
|
363
379
|
collector << 'REPLACE(REPLACE(RTRIM(REPLACE(REPLACE('
|
|
364
380
|
collector = visit o.left, collector
|
|
@@ -375,20 +391,20 @@ module ArelExtensions
|
|
|
375
391
|
collector
|
|
376
392
|
end
|
|
377
393
|
|
|
378
|
-
def visit_ArelExtensions_Nodes_Blank
|
|
394
|
+
def visit_ArelExtensions_Nodes_Blank(o, collector)
|
|
379
395
|
visit o.expr.coalesce('').trim.length.eq(0), collector
|
|
380
396
|
end
|
|
381
397
|
|
|
382
|
-
def visit_ArelExtensions_Nodes_NotBlank
|
|
398
|
+
def visit_ArelExtensions_Nodes_NotBlank(o, collector)
|
|
383
399
|
visit o.expr.coalesce('').trim.length.gt(0), collector
|
|
384
400
|
end
|
|
385
401
|
|
|
386
|
-
def visit_ArelExtensions_Nodes_Format
|
|
402
|
+
def visit_ArelExtensions_Nodes_Format(o, collector)
|
|
387
403
|
visit_ArelExtensions_Nodes_FormattedDate o, collector
|
|
388
404
|
end
|
|
389
405
|
|
|
390
|
-
def visit_ArelExtensions_Nodes_FormattedDate
|
|
391
|
-
f = ArelExtensions::Visitors
|
|
406
|
+
def visit_ArelExtensions_Nodes_FormattedDate(o, collector)
|
|
407
|
+
f = ArelExtensions::Visitors.strftime_to_format(o.iso_format, LOADED_VISITOR::DATE_FORMAT_DIRECTIVES)
|
|
392
408
|
if fmt = LOADED_VISITOR::DATE_CONVERT_FORMATS[f]
|
|
393
409
|
collector << "CONVERT(VARCHAR(#{f.length})"
|
|
394
410
|
collector << LOADED_VISITOR::COMMA
|
|
@@ -420,8 +436,7 @@ module ArelExtensions
|
|
|
420
436
|
while !s.eos?
|
|
421
437
|
collector << sep
|
|
422
438
|
sep = ' + '
|
|
423
|
-
|
|
424
|
-
when s.scan(LOADED_VISITOR::DATE_FORMAT_REGEX)
|
|
439
|
+
if s.scan(LOADED_VISITOR::DATE_FORMAT_REGEX)
|
|
425
440
|
dir = LOADED_VISITOR::DATE_FORMAT_DIRECTIVES[s.matched]
|
|
426
441
|
fmt = LOADED_VISITOR::DATE_FORMAT_FORMAT[dir]
|
|
427
442
|
date_name = LOADED_VISITOR::DATE_NAME.include?(s.matched)
|
|
@@ -439,7 +454,8 @@ module ArelExtensions
|
|
|
439
454
|
collector = visit o.left, collector
|
|
440
455
|
case o.time_zone
|
|
441
456
|
when Hash
|
|
442
|
-
src_tz
|
|
457
|
+
src_tz = o.time_zone.first.first
|
|
458
|
+
dst_tz = o.time_zone.first.second
|
|
443
459
|
collector << ') AT TIME ZONE '
|
|
444
460
|
collector = visit Arel.quoted(src_tz), collector
|
|
445
461
|
collector << ' AT TIME ZONE '
|
|
@@ -452,9 +468,9 @@ module ArelExtensions
|
|
|
452
468
|
collector << ')' if !fmt && !date_name
|
|
453
469
|
collector << LOADED_VISITOR::COMMA << "'#{fmt}')" if fmt
|
|
454
470
|
collector << '))'
|
|
455
|
-
|
|
471
|
+
elsif s.scan(/^%%/)
|
|
456
472
|
collector = visit Arel.quoted('%'), collector
|
|
457
|
-
|
|
473
|
+
elsif s.scan(/[^%]+|./)
|
|
458
474
|
collector = visit Arel.quoted(s.matched), collector
|
|
459
475
|
end
|
|
460
476
|
end
|
|
@@ -463,7 +479,7 @@ module ArelExtensions
|
|
|
463
479
|
end
|
|
464
480
|
end
|
|
465
481
|
|
|
466
|
-
def visit_ArelExtensions_Nodes_Replace
|
|
482
|
+
def visit_ArelExtensions_Nodes_Replace(o, collector)
|
|
467
483
|
collector << 'REPLACE('
|
|
468
484
|
o.expressions.each_with_index { |arg, i|
|
|
469
485
|
collector << LOADED_VISITOR::COMMA if i != 0
|
|
@@ -473,7 +489,7 @@ module ArelExtensions
|
|
|
473
489
|
collector
|
|
474
490
|
end
|
|
475
491
|
|
|
476
|
-
def visit_ArelExtensions_Nodes_FindInSet
|
|
492
|
+
def visit_ArelExtensions_Nodes_FindInSet(o, collector)
|
|
477
493
|
collector << 'dbo.FIND_IN_SET('
|
|
478
494
|
o.expressions.each_with_index { |arg, i|
|
|
479
495
|
collector << LOADED_VISITOR::COMMA if i != 0
|
|
@@ -484,7 +500,7 @@ module ArelExtensions
|
|
|
484
500
|
end
|
|
485
501
|
|
|
486
502
|
# TODO; manage case insensitivity
|
|
487
|
-
def visit_ArelExtensions_Nodes_IMatches
|
|
503
|
+
def visit_ArelExtensions_Nodes_IMatches(o, collector)
|
|
488
504
|
collector = visit o.left.ci_collate, collector
|
|
489
505
|
collector << ' LIKE '
|
|
490
506
|
collector = visit o.right.ci_collate, collector
|
|
@@ -497,7 +513,7 @@ module ArelExtensions
|
|
|
497
513
|
end
|
|
498
514
|
|
|
499
515
|
# TODO; manage case insensitivity
|
|
500
|
-
def visit_ArelExtensions_Nodes_IDoesNotMatch
|
|
516
|
+
def visit_ArelExtensions_Nodes_IDoesNotMatch(o, collector)
|
|
501
517
|
collector = visit o.left.ci_collate, collector
|
|
502
518
|
collector << ' NOT LIKE '
|
|
503
519
|
collector = visit o.right.ci_collate, collector
|
|
@@ -509,7 +525,7 @@ module ArelExtensions
|
|
|
509
525
|
end
|
|
510
526
|
end
|
|
511
527
|
|
|
512
|
-
def visit_ArelExtensions_Nodes_AiMatches
|
|
528
|
+
def visit_ArelExtensions_Nodes_AiMatches(o, collector)
|
|
513
529
|
collector = visit o.left.ai_collate, collector
|
|
514
530
|
collector << ' LIKE '
|
|
515
531
|
collector = visit o.right.ai_collate, collector
|
|
@@ -521,7 +537,7 @@ module ArelExtensions
|
|
|
521
537
|
end
|
|
522
538
|
end
|
|
523
539
|
|
|
524
|
-
def visit_ArelExtensions_Nodes_AiIMatches
|
|
540
|
+
def visit_ArelExtensions_Nodes_AiIMatches(o, collector)
|
|
525
541
|
collector = visit o.left.collate(true, true), collector
|
|
526
542
|
collector << ' LIKE '
|
|
527
543
|
collector = visit o.right.collate(true, true), collector
|
|
@@ -533,7 +549,7 @@ module ArelExtensions
|
|
|
533
549
|
end
|
|
534
550
|
end
|
|
535
551
|
|
|
536
|
-
def visit_ArelExtensions_Nodes_SMatches
|
|
552
|
+
def visit_ArelExtensions_Nodes_SMatches(o, collector)
|
|
537
553
|
collector = visit o.left.collate, collector
|
|
538
554
|
collector << ' LIKE '
|
|
539
555
|
collector = visit o.right.collate, collector
|
|
@@ -545,7 +561,7 @@ module ArelExtensions
|
|
|
545
561
|
end
|
|
546
562
|
end
|
|
547
563
|
|
|
548
|
-
def visit_ArelExtensions_Nodes_Collate
|
|
564
|
+
def visit_ArelExtensions_Nodes_Collate(o, collector)
|
|
549
565
|
if o.ai && o.ci
|
|
550
566
|
collector = visit o.expressions.first, collector
|
|
551
567
|
collector << ' COLLATE Latin1_General_CI_AI'
|
|
@@ -562,8 +578,8 @@ module ArelExtensions
|
|
|
562
578
|
collector
|
|
563
579
|
end
|
|
564
580
|
|
|
565
|
-
|
|
566
|
-
def visit_Arel_Nodes_As
|
|
581
|
+
alias old_visit_Arel_Nodes_As visit_Arel_Nodes_As rescue nil
|
|
582
|
+
def visit_Arel_Nodes_As(o, collector)
|
|
567
583
|
if o.left.is_a?(Arel::Nodes::Binary)
|
|
568
584
|
collector << '('
|
|
569
585
|
collector = visit o.left, collector
|
|
@@ -575,11 +591,11 @@ module ArelExtensions
|
|
|
575
591
|
# Sometimes these values are already quoted, if they are, don't double quote it
|
|
576
592
|
lft, rgt =
|
|
577
593
|
if o.right.is_a?(Arel::Nodes::SqlLiteral)
|
|
578
|
-
if
|
|
594
|
+
if AREL_VERSION >= V6 && o.right[0] != '[' && o.right[-1] != ']'
|
|
579
595
|
# This is a lie, it's not about arel version, but SQL Server's (>= 2000).
|
|
580
|
-
[
|
|
581
|
-
elsif o.right[0] != '"' && o.right[-1] != '"'
|
|
582
|
-
[
|
|
596
|
+
%w([ ])
|
|
597
|
+
elsif ACTIVE_RECORD_VERSION < V8_1 && o.right[0] != '"' && o.right[-1] != '"'
|
|
598
|
+
%w[" "]
|
|
583
599
|
else
|
|
584
600
|
[]
|
|
585
601
|
end
|
|
@@ -591,38 +607,38 @@ module ArelExtensions
|
|
|
591
607
|
end
|
|
592
608
|
|
|
593
609
|
# SQL Server does not know about REGEXP
|
|
594
|
-
def visit_Arel_Nodes_Regexp
|
|
610
|
+
def visit_Arel_Nodes_Regexp(o, collector)
|
|
595
611
|
collector = visit o.left, collector
|
|
596
612
|
collector << "LIKE '%#{o.right}%'"
|
|
597
613
|
collector
|
|
598
614
|
end
|
|
599
615
|
|
|
600
|
-
def visit_Arel_Nodes_NotRegexp
|
|
616
|
+
def visit_Arel_Nodes_NotRegexp(o, collector)
|
|
601
617
|
collector = visit o.left, collector
|
|
602
618
|
collector << "NOT LIKE '%#{o.right}%'"
|
|
603
619
|
collector
|
|
604
620
|
end
|
|
605
621
|
|
|
606
622
|
def visit_Arel_Nodes_RollUp(o, collector)
|
|
607
|
-
collector <<
|
|
623
|
+
collector << 'ROLLUP'
|
|
608
624
|
grouping_array_or_grouping_element o, collector
|
|
609
625
|
end
|
|
610
626
|
|
|
611
|
-
def visit_ArelExtensions_Nodes_GroupConcat
|
|
627
|
+
def visit_ArelExtensions_Nodes_GroupConcat(o, collector)
|
|
612
628
|
collector << '(STRING_AGG('
|
|
613
629
|
collector = visit o.left, collector
|
|
614
|
-
collector <<
|
|
630
|
+
collector << LOADED_VISITOR::COMMA
|
|
615
631
|
sep = o.separator.is_a?(Arel::Nodes::Quoted) ? o.separator.expr : o.separator
|
|
616
632
|
collector =
|
|
617
|
-
if 'NULL'
|
|
618
|
-
visit o.separator, collector
|
|
619
|
-
else
|
|
633
|
+
if 'NULL' == sep
|
|
620
634
|
visit Arel.quoted(','), collector
|
|
635
|
+
else
|
|
636
|
+
visit o.separator, collector
|
|
621
637
|
end
|
|
622
638
|
collector << ') WITHIN GROUP (ORDER BY '
|
|
623
639
|
if o.order.present?
|
|
624
640
|
o.order.each_with_index do |order, i|
|
|
625
|
-
collector <<
|
|
641
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
|
626
642
|
collector = visit order, collector
|
|
627
643
|
end
|
|
628
644
|
else
|
|
@@ -632,18 +648,18 @@ module ArelExtensions
|
|
|
632
648
|
collector
|
|
633
649
|
end
|
|
634
650
|
|
|
635
|
-
def visit_ArelExtensions_Nodes_MD5
|
|
636
|
-
collector << "LOWER(CONVERT(NVARCHAR(32),HashBytes('MD5',CONVERT(VARCHAR,"
|
|
651
|
+
def visit_ArelExtensions_Nodes_MD5(o, collector)
|
|
652
|
+
collector << "LOWER(CONVERT(NVARCHAR(32),HashBytes('MD5',CONVERT(VARCHAR(MAX),"
|
|
637
653
|
collector = visit o.left, collector
|
|
638
654
|
collector << ')),2))'
|
|
639
655
|
collector
|
|
640
656
|
end
|
|
641
657
|
|
|
642
|
-
def visit_ArelExtensions_Nodes_Cast
|
|
658
|
+
def visit_ArelExtensions_Nodes_Cast(o, collector)
|
|
643
659
|
as_attr =
|
|
644
660
|
case o.as_attr
|
|
645
661
|
when :string
|
|
646
|
-
'varchar'
|
|
662
|
+
'varchar(MAX)'
|
|
647
663
|
when :time
|
|
648
664
|
'time'
|
|
649
665
|
when :date
|
|
@@ -670,7 +686,7 @@ module ArelExtensions
|
|
|
670
686
|
collector
|
|
671
687
|
end
|
|
672
688
|
|
|
673
|
-
def visit_ArelExtensions_Nodes_FormattedNumber
|
|
689
|
+
def visit_ArelExtensions_Nodes_FormattedNumber(o, collector)
|
|
674
690
|
col = o.left.coalesce(0)
|
|
675
691
|
locale = Arel.quoted(o.locale.tr('_', '-'))
|
|
676
692
|
param = Arel.quoted("N#{o.precision}")
|
|
@@ -731,35 +747,33 @@ module ArelExtensions
|
|
|
731
747
|
collector
|
|
732
748
|
end
|
|
733
749
|
|
|
734
|
-
def visit_ArelExtensions_Nodes_Std
|
|
750
|
+
def visit_ArelExtensions_Nodes_Std(o, collector)
|
|
735
751
|
collector << (o.unbiased_estimator ? 'STDEV(' : 'STDEVP(')
|
|
736
752
|
visit o.left, collector
|
|
737
753
|
collector << ')'
|
|
738
754
|
collector
|
|
739
755
|
end
|
|
740
756
|
|
|
741
|
-
def visit_ArelExtensions_Nodes_Variance
|
|
757
|
+
def visit_ArelExtensions_Nodes_Variance(o, collector)
|
|
742
758
|
collector << (o.unbiased_estimator ? 'VAR(' : 'VARP(')
|
|
743
759
|
visit o.left, collector
|
|
744
760
|
collector << ')'
|
|
745
761
|
collector
|
|
746
762
|
end
|
|
747
763
|
|
|
748
|
-
|
|
749
|
-
def visit_ArelExtensions_Nodes_LevenshteinDistance o, collector
|
|
764
|
+
def visit_ArelExtensions_Nodes_LevenshteinDistance(o, collector)
|
|
750
765
|
collector << 'dbo.LEVENSHTEIN_DISTANCE('
|
|
751
766
|
collector = visit o.left, collector
|
|
752
|
-
collector <<
|
|
767
|
+
collector << LOADED_VISITOR::COMMA
|
|
753
768
|
collector = visit o.right, collector
|
|
754
769
|
collector << ')'
|
|
755
770
|
collector
|
|
756
771
|
end
|
|
757
772
|
|
|
758
|
-
|
|
759
|
-
def visit_ArelExtensions_Nodes_JsonGet o, collector
|
|
773
|
+
def visit_ArelExtensions_Nodes_JsonGet(o, collector)
|
|
760
774
|
collector << 'JSON_VALUE('
|
|
761
775
|
collector = visit o.dict, collector
|
|
762
|
-
collector <<
|
|
776
|
+
collector << LOADED_VISITOR::COMMA
|
|
763
777
|
if o.key.is_a?(Integer)
|
|
764
778
|
collector << "\"$[#{o.key}]\""
|
|
765
779
|
else
|
|
@@ -773,9 +787,9 @@ module ArelExtensions
|
|
|
773
787
|
# handle grouping aggregation semantics
|
|
774
788
|
def grouping_array_or_grouping_element(o, collector)
|
|
775
789
|
if o.expr.is_a? Array
|
|
776
|
-
collector <<
|
|
790
|
+
collector << '( '
|
|
777
791
|
visit o.expr, collector
|
|
778
|
-
collector <<
|
|
792
|
+
collector << ' )'
|
|
779
793
|
else
|
|
780
794
|
visit o.expr, collector
|
|
781
795
|
end
|