arel_extensions 2.0.22 → 2.1.1
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 +358 -71
- data/Gemfile +8 -8
- data/README.md +86 -0
- data/arel_extensions.gemspec +1 -1
- data/gemfiles/rails5_2.gemfile +8 -7
- data/gemfiles/rails6.gemfile +7 -8
- data/gemfiles/rails6_1.gemfile +6 -7
- data/gemfiles/rails7.gemfile +22 -0
- data/gemspecs/arel_extensions-v1.gemspec +1 -1
- data/gemspecs/arel_extensions-v2.gemspec +1 -1
- data/lib/arel_extensions/aliases.rb +14 -0
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/date_duration.rb +2 -2
- data/lib/arel_extensions/helpers.rb +48 -0
- data/lib/arel_extensions/insert_manager.rb +19 -17
- data/lib/arel_extensions/math.rb +22 -32
- data/lib/arel_extensions/nodes/case.rb +5 -6
- data/lib/arel_extensions/nodes/cast.rb +1 -1
- data/lib/arel_extensions/nodes/date_diff.rb +23 -4
- data/lib/arel_extensions/nodes/format.rb +3 -2
- data/lib/arel_extensions/nodes/function.rb +2 -6
- data/lib/arel_extensions/nodes/json.rb +3 -1
- data/lib/arel_extensions/nodes/replace.rb +0 -8
- data/lib/arel_extensions/nodes/union.rb +1 -1
- data/lib/arel_extensions/nodes/union_all.rb +1 -1
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +109 -51
- data/lib/arel_extensions/visitors/mysql.rb +15 -2
- data/lib/arel_extensions/visitors/oracle.rb +6 -1
- data/lib/arel_extensions/visitors/postgresql.rb +20 -10
- data/lib/arel_extensions/visitors/sqlite.rb +6 -3
- data/lib/arel_extensions/visitors/to_sql.rb +13 -8
- data/lib/arel_extensions/visitors.rb +9 -1
- data/lib/arel_extensions.rb +57 -15
- data/test/arelx_test_helper.rb +45 -0
- data/test/database.yml +8 -2
- data/test/real_db_test.rb +5 -1
- data/test/support/fake_record.rb +1 -1
- data/test/visitors/test_to_sql.rb +39 -11
- data/test/with_ar/all_agnostic_test.rb +79 -6
- data/test/with_ar/insert_agnostic_test.rb +6 -2
- data/test/with_ar/test_bulk_sqlite.rb +6 -2
- data/test/with_ar/test_math_sqlite.rb +6 -2
- data/test/with_ar/test_string_mysql.rb +6 -2
- data/test/with_ar/test_string_sqlite.rb +6 -2
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +10 -8
- data/appveyor.yml +0 -44
@@ -2,27 +2,37 @@ module ArelExtensions
|
|
2
2
|
module Visitors
|
3
3
|
module MSSQL
|
4
4
|
|
5
|
-
Arel::Visitors
|
5
|
+
mssql_class = Arel::Visitors.constants.select { |c|
|
6
|
+
Arel::Visitors.const_get(c).is_a?(Class) && %i[MSSQL SQLServer].include?(c)
|
7
|
+
}.first
|
8
|
+
|
9
|
+
LOADED_VISITOR = Arel::Visitors.const_get(mssql_class) || Arel::Visitors.const_get('MSSQL')
|
10
|
+
|
11
|
+
LOADED_VISITOR::DATE_MAPPING = {
|
6
12
|
'd' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'
|
7
13
|
}.freeze
|
8
14
|
|
9
|
-
|
15
|
+
LOADED_VISITOR::DATE_FORMAT_DIRECTIVES = {
|
10
16
|
'%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => '', '%b' => '', '%^b' => '', # year, month
|
11
17
|
'%d' => 'DD', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
|
12
18
|
'%H' => 'hh', '%k' => '', '%I' => '', '%l' => '', '%P' => '', '%p' => '', # hours
|
13
19
|
'%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
|
14
20
|
}.freeze
|
15
21
|
|
16
|
-
|
22
|
+
LOADED_VISITOR::DATE_FORMAT_FORMAT = {
|
23
|
+
'YY' => '0#', 'MM' => '0#', 'DD' => '0#', 'hh' => '0#', 'mi' => '0#', 'ss' => '0#'
|
24
|
+
}
|
25
|
+
|
26
|
+
LOADED_VISITOR::DATE_FORMAT_REGEX =
|
17
27
|
Regexp.new(
|
18
|
-
|
28
|
+
LOADED_VISITOR::DATE_FORMAT_DIRECTIVES
|
19
29
|
.keys
|
20
30
|
.map{|k| Regexp.escape(k)}
|
21
31
|
.join('|')
|
22
32
|
).freeze
|
23
33
|
|
24
34
|
# TODO; all others... http://www.sql-server-helper.com/tips/date-formats.aspx
|
25
|
-
|
35
|
+
LOADED_VISITOR::DATE_CONVERT_FORMATS = {
|
26
36
|
'YYYY-MM-DD' => 120,
|
27
37
|
'YY-MM-DD' => 120,
|
28
38
|
'MM/DD/YYYY' => 101,
|
@@ -79,7 +89,7 @@ module ArelExtensions
|
|
79
89
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
80
90
|
collector << "CONCAT("
|
81
91
|
o.expressions.each_with_index { |arg, i|
|
82
|
-
collector <<
|
92
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
83
93
|
collector = visit arg, collector
|
84
94
|
}
|
85
95
|
collector << ")"
|
@@ -102,23 +112,23 @@ module ArelExtensions
|
|
102
112
|
case o.right_node_type
|
103
113
|
when :ruby_date, :ruby_time, :date, :datetime, :time
|
104
114
|
collector << case o.left_node_type
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
collector <<
|
115
|
+
when :ruby_time, :datetime, :time then 'DATEDIFF(second'
|
116
|
+
else 'DATEDIFF(day'
|
117
|
+
end
|
118
|
+
collector << LOADED_VISITOR::COMMA
|
109
119
|
collector = visit o.right, collector
|
110
|
-
collector <<
|
120
|
+
collector << LOADED_VISITOR::COMMA
|
111
121
|
collector = visit o.left, collector
|
112
122
|
collector << ')'
|
113
123
|
else
|
114
124
|
da = ArelExtensions::Nodes::DateAdd.new([])
|
115
125
|
collector << "DATEADD("
|
116
126
|
collector = visit da.mssql_datepart(o.right), collector
|
117
|
-
collector <<
|
127
|
+
collector << LOADED_VISITOR::COMMA
|
118
128
|
collector << "-("
|
119
129
|
collector = visit da.mssql_value(o.right), collector
|
120
130
|
collector << ")"
|
121
|
-
collector <<
|
131
|
+
collector << LOADED_VISITOR::COMMA
|
122
132
|
collector = visit o.left, collector
|
123
133
|
collector << ")"
|
124
134
|
collector
|
@@ -129,9 +139,9 @@ module ArelExtensions
|
|
129
139
|
def visit_ArelExtensions_Nodes_DateAdd o, collector
|
130
140
|
collector << "DATEADD("
|
131
141
|
collector = visit o.mssql_datepart(o.right), collector
|
132
|
-
collector <<
|
142
|
+
collector << LOADED_VISITOR::COMMA
|
133
143
|
collector = visit o.mssql_value(o.right), collector
|
134
|
-
collector <<
|
144
|
+
collector << LOADED_VISITOR::COMMA
|
135
145
|
collector = visit o.left, collector
|
136
146
|
collector << ")"
|
137
147
|
collector
|
@@ -144,8 +154,8 @@ module ArelExtensions
|
|
144
154
|
left = o.left.end_with?('i') ? o.left[0..-2] : o.left
|
145
155
|
conv = ['h', 'mn', 's'].include?(o.left)
|
146
156
|
collector << 'DATEPART('
|
147
|
-
collector <<
|
148
|
-
collector <<
|
157
|
+
collector << LOADED_VISITOR::DATE_MAPPING[left]
|
158
|
+
collector << LOADED_VISITOR::COMMA
|
149
159
|
collector << 'CONVERT(datetime,' if conv
|
150
160
|
collector = visit o.right, collector
|
151
161
|
collector << ')' if conv
|
@@ -155,20 +165,29 @@ module ArelExtensions
|
|
155
165
|
end
|
156
166
|
|
157
167
|
def visit_ArelExtensions_Nodes_Length o, collector
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
168
|
+
if o.bytewise
|
169
|
+
collector << "(DATALENGTH("
|
170
|
+
collector = visit o.expr, collector
|
171
|
+
collector << ") / ISNULL(NULLIF(DATALENGTH(LEFT(COALESCE("
|
172
|
+
collector = visit o.expr, collector
|
173
|
+
collector << ", '#' ), 1 )), 0), 1))"
|
174
|
+
collector
|
175
|
+
else
|
176
|
+
collector << "LEN("
|
177
|
+
collector = visit o.expr, collector
|
178
|
+
collector << ")"
|
179
|
+
collector
|
180
|
+
end
|
162
181
|
end
|
163
182
|
|
164
183
|
def visit_ArelExtensions_Nodes_Round o, collector
|
165
184
|
collector << "ROUND("
|
166
185
|
o.expressions.each_with_index { |arg, i|
|
167
|
-
collector <<
|
186
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
168
187
|
collector = visit arg, collector
|
169
188
|
}
|
170
189
|
if o.expressions.length == 1
|
171
|
-
collector <<
|
190
|
+
collector << LOADED_VISITOR::COMMA
|
172
191
|
collector << "0"
|
173
192
|
end
|
174
193
|
collector << ")"
|
@@ -178,7 +197,7 @@ module ArelExtensions
|
|
178
197
|
def visit_ArelExtensions_Nodes_Locate o, collector
|
179
198
|
collector << "CHARINDEX("
|
180
199
|
collector = visit o.right, collector
|
181
|
-
collector <<
|
200
|
+
collector << LOADED_VISITOR::COMMA
|
182
201
|
collector = visit o.left, collector
|
183
202
|
collector << ")"
|
184
203
|
collector
|
@@ -187,28 +206,20 @@ module ArelExtensions
|
|
187
206
|
def visit_ArelExtensions_Nodes_Substring o, collector
|
188
207
|
collector << 'SUBSTRING('
|
189
208
|
collector = visit o.expressions[0], collector
|
190
|
-
collector <<
|
209
|
+
collector << LOADED_VISITOR::COMMA
|
191
210
|
collector = visit o.expressions[1], collector
|
192
|
-
collector <<
|
211
|
+
collector << LOADED_VISITOR::COMMA
|
193
212
|
collector = o.expressions[2] ? visit(o.expressions[2], collector) : visit(o.expressions[0].length, collector)
|
194
213
|
collector << ')'
|
195
214
|
collector
|
196
215
|
end
|
197
216
|
|
198
217
|
def visit_ArelExtensions_Nodes_Trim o, collector
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
collector << ", ' '))), ' ', "
|
205
|
-
collector = visit o.right, collector
|
206
|
-
collector << "), '~', ' ')"
|
207
|
-
else
|
208
|
-
collector << "LTRIM(RTRIM("
|
209
|
-
collector = visit o.left, collector
|
210
|
-
collector << "))"
|
211
|
-
end
|
218
|
+
collector << 'TRIM( '
|
219
|
+
collector = visit o.right, collector
|
220
|
+
collector << " FROM "
|
221
|
+
collector = visit o.left, collector
|
222
|
+
collector << ")"
|
212
223
|
collector
|
213
224
|
end
|
214
225
|
|
@@ -255,12 +266,21 @@ module ArelExtensions
|
|
255
266
|
end
|
256
267
|
|
257
268
|
def visit_ArelExtensions_Nodes_Format o, collector
|
258
|
-
f = ArelExtensions::Visitors::strftime_to_format(o.iso_format,
|
259
|
-
if fmt =
|
269
|
+
f = ArelExtensions::Visitors::strftime_to_format(o.iso_format, LOADED_VISITOR::DATE_FORMAT_DIRECTIVES)
|
270
|
+
if fmt = LOADED_VISITOR::DATE_CONVERT_FORMATS[f]
|
260
271
|
collector << "CONVERT(VARCHAR(#{f.length})"
|
261
|
-
collector <<
|
272
|
+
collector << LOADED_VISITOR::COMMA
|
273
|
+
if o.time_zone
|
274
|
+
collector << 'CONVERT(datetime'
|
275
|
+
collector << LOADED_VISITOR::COMMA
|
276
|
+
collector << ' '
|
277
|
+
end
|
262
278
|
collector = visit o.left, collector
|
263
|
-
|
279
|
+
if o.time_zone
|
280
|
+
collector << ") AT TIME ZONE 'UTC' AT TIME ZONE "
|
281
|
+
collector = visit o.time_zone, collector
|
282
|
+
end
|
283
|
+
collector << LOADED_VISITOR::COMMA
|
264
284
|
collector << fmt.to_s
|
265
285
|
collector << ')'
|
266
286
|
collector
|
@@ -272,13 +292,31 @@ module ArelExtensions
|
|
272
292
|
collector << sep
|
273
293
|
sep = ' + '
|
274
294
|
case
|
275
|
-
when s.scan(
|
276
|
-
dir =
|
277
|
-
|
295
|
+
when s.scan(LOADED_VISITOR::DATE_FORMAT_REGEX)
|
296
|
+
dir = LOADED_VISITOR::DATE_FORMAT_DIRECTIVES[s.matched]
|
297
|
+
fmt = LOADED_VISITOR::DATE_FORMAT_FORMAT[dir]
|
298
|
+
collector << 'TRIM('
|
299
|
+
collector << 'FORMAT(' if fmt
|
300
|
+
collector << 'STR(' if !fmt
|
301
|
+
collector << 'DATEPART('
|
278
302
|
collector << dir
|
279
|
-
collector <<
|
303
|
+
collector << LOADED_VISITOR::COMMA
|
304
|
+
if o.time_zone
|
305
|
+
collector << 'CONVERT(datetime'
|
306
|
+
collector << LOADED_VISITOR::COMMA
|
307
|
+
collector << ' '
|
308
|
+
end
|
280
309
|
collector = visit o.left, collector
|
281
|
-
|
310
|
+
if o.time_zone
|
311
|
+
collector << ") AT TIME ZONE 'UTC' AT TIME ZONE "
|
312
|
+
collector = visit o.time_zone, collector
|
313
|
+
end
|
314
|
+
collector << ')'
|
315
|
+
collector << ')' if !fmt
|
316
|
+
collector << LOADED_VISITOR::COMMA << "'#{fmt}')" if fmt
|
317
|
+
collector << ')'
|
318
|
+
when s.scan(/^%%/)
|
319
|
+
collector = visit Arel::Nodes.build_quoted('%'), collector
|
282
320
|
when s.scan(/[^%]+|./)
|
283
321
|
collector = visit Arel::Nodes.build_quoted(s.matched), collector
|
284
322
|
end
|
@@ -291,7 +329,7 @@ module ArelExtensions
|
|
291
329
|
def visit_ArelExtensions_Nodes_Replace o, collector
|
292
330
|
collector << "REPLACE("
|
293
331
|
o.expressions.each_with_index { |arg, i|
|
294
|
-
collector <<
|
332
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
295
333
|
collector = visit arg, collector
|
296
334
|
}
|
297
335
|
collector << ")"
|
@@ -301,7 +339,7 @@ module ArelExtensions
|
|
301
339
|
def visit_ArelExtensions_Nodes_FindInSet o, collector
|
302
340
|
collector << "dbo.FIND_IN_SET("
|
303
341
|
o.expressions.each_with_index { |arg, i|
|
304
|
-
collector <<
|
342
|
+
collector << LOADED_VISITOR::COMMA if i != 0
|
305
343
|
collector = visit arg, collector
|
306
344
|
}
|
307
345
|
collector << ")"
|
@@ -387,6 +425,27 @@ module ArelExtensions
|
|
387
425
|
collector
|
388
426
|
end
|
389
427
|
|
428
|
+
alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
|
429
|
+
def visit_Arel_Nodes_As o, collector
|
430
|
+
if o.left.is_a?(Arel::Nodes::Binary)
|
431
|
+
collector << '('
|
432
|
+
collector = visit o.left, collector
|
433
|
+
collector << ')'
|
434
|
+
else
|
435
|
+
collector = visit o.left, collector
|
436
|
+
end
|
437
|
+
collector << " AS "
|
438
|
+
|
439
|
+
# sometimes these values are already quoted, if they are, don't double quote it
|
440
|
+
quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '"' && o.right[-1] != '"'
|
441
|
+
|
442
|
+
collector << '"' if quote
|
443
|
+
collector = visit o.right, collector
|
444
|
+
collector << '"' if quote
|
445
|
+
|
446
|
+
collector
|
447
|
+
end
|
448
|
+
|
390
449
|
# SQL Server does not know about REGEXP
|
391
450
|
def visit_Arel_Nodes_Regexp o, collector
|
392
451
|
collector = visit o.left, collector
|
@@ -554,7 +613,6 @@ module ArelExtensions
|
|
554
613
|
collector << ')'
|
555
614
|
collector
|
556
615
|
end
|
557
|
-
|
558
616
|
end
|
559
617
|
end
|
560
618
|
end
|
@@ -209,7 +209,13 @@ module ArelExtensions
|
|
209
209
|
when :date, :datetime, :time
|
210
210
|
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
211
211
|
collector << "DATE_FORMAT("
|
212
|
+
collector << "CONVERT_TZ(" if o.time_zone
|
212
213
|
collector = visit o.left, collector
|
214
|
+
if o.time_zone
|
215
|
+
collector << COMMA << "'UTC'" << COMMA
|
216
|
+
collector = visit o.time_zone, collector
|
217
|
+
collector << ')'
|
218
|
+
end
|
213
219
|
collector << COMMA
|
214
220
|
collector = visit Arel::Nodes.build_quoted(fmt), collector
|
215
221
|
collector << ")"
|
@@ -354,9 +360,16 @@ module ArelExtensions
|
|
354
360
|
else
|
355
361
|
collector = visit o.left, collector
|
356
362
|
end
|
357
|
-
collector << " AS
|
363
|
+
collector << " AS "
|
364
|
+
|
365
|
+
# sometimes these values are already quoted, if they are, don't double quote it
|
366
|
+
quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '`' && o.right[-1] != '`'
|
367
|
+
|
368
|
+
collector << '`' if quote
|
358
369
|
collector = visit o.right, collector
|
359
|
-
collector <<
|
370
|
+
collector << '`' if quote
|
371
|
+
|
372
|
+
collector
|
360
373
|
collector
|
361
374
|
end
|
362
375
|
|
@@ -447,7 +447,12 @@ module ArelExtensions
|
|
447
447
|
def visit_ArelExtensions_Nodes_Format o, collector
|
448
448
|
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
449
449
|
collector << "TO_CHAR("
|
450
|
+
collector << "CAST(" if o.time_zone
|
450
451
|
collector = visit o.left, collector
|
452
|
+
if o.time_zone
|
453
|
+
collector << " as timestamp) at time zone "
|
454
|
+
collector = visit o.time_zone, collector
|
455
|
+
end
|
451
456
|
collector << COMMA
|
452
457
|
collector = visit Arel::Nodes.build_quoted(fmt), collector
|
453
458
|
collector << ")"
|
@@ -517,7 +522,7 @@ module ArelExtensions
|
|
517
522
|
if element.is_a?(Time)
|
518
523
|
ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
|
519
524
|
elsif element.is_a?(Arel::Attributes::Attribute)
|
520
|
-
col =
|
525
|
+
col = ArelExtensions::column_of(element.relation.table_name, element.name.to_s)
|
521
526
|
if col && (col.type == :time)
|
522
527
|
ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
|
523
528
|
else
|
@@ -86,9 +86,15 @@ module ArelExtensions
|
|
86
86
|
else
|
87
87
|
collector = visit o.left, collector
|
88
88
|
end
|
89
|
-
collector << " AS
|
89
|
+
collector << " AS "
|
90
|
+
|
91
|
+
# sometimes these values are already quoted, if they are, don't double quote it
|
92
|
+
quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '"' && o.right[-1] != '"'
|
93
|
+
|
94
|
+
collector << '"' if quote
|
90
95
|
collector = visit o.right, collector
|
91
|
-
collector << "
|
96
|
+
collector << '"' if quote
|
97
|
+
|
92
98
|
collector
|
93
99
|
end
|
94
100
|
|
@@ -170,6 +176,10 @@ module ArelExtensions
|
|
170
176
|
fmt = ArelExtensions::Visitors::strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
|
171
177
|
collector << "TO_CHAR("
|
172
178
|
collector = visit o.left, collector
|
179
|
+
if o.time_zone
|
180
|
+
collector << " AT TIME ZONE "
|
181
|
+
collector = visit o.time_zone, collector
|
182
|
+
end
|
173
183
|
collector << COMMA
|
174
184
|
collector = visit Arel::Nodes.build_quoted(fmt), collector
|
175
185
|
collector << ")"
|
@@ -283,9 +293,9 @@ module ArelExtensions
|
|
283
293
|
return collector
|
284
294
|
end
|
285
295
|
end
|
286
|
-
collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM "
|
296
|
+
collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM CAST("
|
287
297
|
collector = visit o.right, collector
|
288
|
-
collector << ")"
|
298
|
+
collector << " AS TIMESTAMP WITH TIME ZONE))"
|
289
299
|
collector << " * (INTERVAL '1' #{interval})" if interval && o.with_interval
|
290
300
|
collector
|
291
301
|
end
|
@@ -368,11 +378,13 @@ module ArelExtensions
|
|
368
378
|
when :number, :decimal, :float
|
369
379
|
Arel::Nodes::SqlLiteral.new('numeric')
|
370
380
|
when :datetime
|
371
|
-
Arel::Nodes::SqlLiteral.new('timestamp')
|
381
|
+
Arel::Nodes::SqlLiteral.new('timestamp with time zone')
|
372
382
|
when :date
|
373
383
|
Arel::Nodes::SqlLiteral.new('date')
|
374
384
|
when :binary
|
375
385
|
Arel::Nodes::SqlLiteral.new('binary')
|
386
|
+
when :jsonb
|
387
|
+
Arel::Nodes::SqlLiteral.new('jsonb')
|
376
388
|
else
|
377
389
|
Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
|
378
390
|
end
|
@@ -401,13 +413,13 @@ module ArelExtensions
|
|
401
413
|
ArelExtensions::Nodes::Concat.new([
|
402
414
|
Arel::Nodes::NamedFunction.new('TRIM',[
|
403
415
|
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
404
|
-
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
416
|
+
Arel.when(col.not_eq 0).then(col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)).else(1),
|
405
417
|
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
406
418
|
])]),
|
407
419
|
o.type,
|
408
420
|
Arel::Nodes::NamedFunction.new('TRIM',[
|
409
421
|
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
410
|
-
col.abs.log10.floor,
|
422
|
+
Arel.when(col.not_eq 0).then(col.abs.log10.floor).else(0),
|
411
423
|
Arel::Nodes.build_quoted('FM'+nines_before)
|
412
424
|
])])
|
413
425
|
])
|
@@ -511,8 +523,6 @@ module ArelExtensions
|
|
511
523
|
collector << '::jsonb'
|
512
524
|
when NilClass
|
513
525
|
collector << %Q['null'::jsonb]
|
514
|
-
when Arel::Attributes::Attribute
|
515
|
-
collector = visit o.dict.cast(:jsonb), collector
|
516
526
|
else
|
517
527
|
collector = visit o.dict, collector
|
518
528
|
collector << '::jsonb'
|
@@ -532,7 +542,7 @@ module ArelExtensions
|
|
532
542
|
|
533
543
|
def visit_ArelExtensions_Nodes_JsonGet o,collector
|
534
544
|
collector = visit o.dict, collector
|
535
|
-
collector << '
|
545
|
+
collector << ' ->> '
|
536
546
|
collector = visit o.key, collector
|
537
547
|
collector
|
538
548
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'arel_extensions/helpers'
|
2
|
+
|
1
3
|
module ArelExtensions
|
2
4
|
module Visitors
|
3
5
|
class Arel::Visitors::SQLite
|
@@ -327,7 +329,7 @@ module ArelExtensions
|
|
327
329
|
if element.is_a?(Time)
|
328
330
|
return Arel::Nodes::NamedFunction.new('STRFTIME',[element, '%H:%M:%S'])
|
329
331
|
elsif element.is_a?(Arel::Attributes::Attribute)
|
330
|
-
col =
|
332
|
+
col = ArelExtensions::column_of(element.relation.table_name, element.name.to_s)
|
331
333
|
if col && (col.type == :time)
|
332
334
|
return Arel::Nodes::NamedFunction.new('STRFTIME',[element, '%H:%M:%S'])
|
333
335
|
else
|
@@ -379,9 +381,10 @@ module ArelExtensions
|
|
379
381
|
else
|
380
382
|
collector = visit o.left, collector
|
381
383
|
end
|
382
|
-
|
384
|
+
sep = o.right.size > 1 && o.right[0] == '"' && o.right[-1] == '"' ? '' : '"'
|
385
|
+
collector << " AS #{sep}"
|
383
386
|
collector = visit o.right, collector
|
384
|
-
collector << "
|
387
|
+
collector << "#{sep}"
|
385
388
|
collector
|
386
389
|
end
|
387
390
|
|
@@ -8,10 +8,15 @@ module ArelExtensions
|
|
8
8
|
def make_json_string expr
|
9
9
|
Arel::Nodes.build_quoted('"') \
|
10
10
|
+ expr
|
11
|
+
.coalesce('')
|
11
12
|
.replace('\\','\\\\').replace('"','\"').replace("\n", '\n') \
|
12
13
|
+ '"'
|
13
14
|
end
|
14
15
|
|
16
|
+
def make_json_null
|
17
|
+
Arel::Nodes.build_quoted("null")
|
18
|
+
end
|
19
|
+
|
15
20
|
# Math Functions
|
16
21
|
def visit_ArelExtensions_Nodes_Abs o, collector
|
17
22
|
collector << "ABS("
|
@@ -601,20 +606,20 @@ module ArelExtensions
|
|
601
606
|
def json_value(o,v)
|
602
607
|
case o.type_of_node(v)
|
603
608
|
when :string
|
604
|
-
Arel.when(v.is_null).then(
|
609
|
+
Arel.when(v.is_null).then(make_json_null).else(make_json_string(v))
|
605
610
|
when :date
|
606
611
|
s = v.format('%Y-%m-%d')
|
607
|
-
Arel.when(s.is_null).then(
|
612
|
+
Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
|
608
613
|
when :datetime
|
609
614
|
s = v.format('%Y-%m-%dT%H:%M:%S')
|
610
|
-
Arel.when(s.is_null).then(
|
615
|
+
Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
|
611
616
|
when :time
|
612
617
|
s = v.format('%H:%M:%S')
|
613
|
-
Arel.when(s.is_null).then(
|
618
|
+
Arel.when(s.is_null).then(make_json_null).else(make_json_string(s))
|
614
619
|
when :nil
|
615
|
-
|
620
|
+
make_json_null
|
616
621
|
else
|
617
|
-
ArelExtensions::Nodes::Cast.new([v, :string]).coalesce(
|
622
|
+
ArelExtensions::Nodes::Cast.new([v, :string]).coalesce(make_json_null)
|
618
623
|
end
|
619
624
|
end
|
620
625
|
|
@@ -636,7 +641,7 @@ module ArelExtensions
|
|
636
641
|
if i != 0
|
637
642
|
res += ', '
|
638
643
|
end
|
639
|
-
res += make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])
|
644
|
+
res += make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])) + ': '
|
640
645
|
res += json_value(o,v)
|
641
646
|
end
|
642
647
|
res += '}'
|
@@ -658,7 +663,7 @@ module ArelExtensions
|
|
658
663
|
if i != 0
|
659
664
|
res = res + ', '
|
660
665
|
end
|
661
|
-
kv = make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])
|
666
|
+
kv = make_json_string(ArelExtensions::Nodes::Cast.new([k, :string])) + ': '
|
662
667
|
kv += json_value(o,v)
|
663
668
|
res = res + kv.group_concat(', ', order: Array(orders)).coalesce('')
|
664
669
|
end
|
@@ -9,9 +9,17 @@ if defined?(Arel::Visitors::Oracle)
|
|
9
9
|
require 'arel_extensions/visitors/oracle12'
|
10
10
|
end
|
11
11
|
|
12
|
-
if defined?(Arel::Visitors::MSSQL)
|
12
|
+
if defined?(Arel::Visitors::SQLServer) || defined?(Arel::Visitors::MSSQL)
|
13
13
|
require 'arel_extensions/visitors/mssql'
|
14
|
+
end
|
14
15
|
|
16
|
+
if defined?(Arel::Visitors::SQLServer)
|
17
|
+
class Arel::Visitors::SQLServer
|
18
|
+
include ArelExtensions::Visitors::MSSQL
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if defined?(Arel::Visitors::MSSQL)
|
15
23
|
class Arel::Visitors::MSSQL
|
16
24
|
include ArelExtensions::Visitors::MSSQL
|
17
25
|
|