arel_extensions 1.0.6 → 1.0.7
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/README.md +10 -1
- data/TODO +1 -1
- data/lib/arel_extensions/math_functions.rb +2 -1
- data/lib/arel_extensions/nodes/formatted_number.rb +2 -1
- data/lib/arel_extensions/nodes/is_null.rb +5 -0
- data/lib/arel_extensions/null_functions.rb +6 -0
- data/lib/arel_extensions/predications.rb +76 -0
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors.rb +18 -0
- data/lib/arel_extensions/visitors/mssql.rb +66 -2
- data/lib/arel_extensions/visitors/mysql.rb +68 -1
- data/lib/arel_extensions/visitors/oracle.rb +73 -1
- data/lib/arel_extensions/visitors/postgresql.rb +68 -0
- data/lib/arel_extensions/visitors/sqlite.rb +31 -3
- data/lib/arel_extensions/visitors/to_sql.rb +63 -96
- data/test/visitors/test_to_sql.rb +16 -7
- data/test/with_ar/all_agnostic_test.rb +79 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e6925dda8ff2e84e0501da7f283326b69feb5ad
|
4
|
+
data.tar.gz: 8935f5b0b37b38c8bfa63f5858eea8fc00fbe389
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e14c35a07d01adce7aec5b79a5b0e063262cdb4ae35c6684d45ab334ea19fd988790eb158a539fe25d9f6801562295fbb80afc3e630fadf0cd3af58debd08e66
|
7
|
+
data.tar.gz: a81609fa1c9281814271fa5d3fcebf269c08818e60c67c89b550d9072e0196f5606e1cadd3cb8465ab82899b9bec6a4878713b66a01ab62c4015a74c7bfaa58d
|
data/README.md
CHANGED
@@ -192,7 +192,7 @@ User.connection.execute(insert_manager.to_sql)
|
|
192
192
|
</thead>
|
193
193
|
<tbody>
|
194
194
|
<tr>
|
195
|
-
<th class="tg-82sq" rowspan="
|
195
|
+
<th class="tg-82sq" rowspan="7"><div>Number functions</div></th>
|
196
196
|
<td class="tg-yw4l">ABS<br>column.abs<br></td>
|
197
197
|
<td class="ok">✔</td>
|
198
198
|
<td class="ok">✔</td>
|
@@ -246,6 +246,15 @@ User.connection.execute(insert_manager.to_sql)
|
|
246
246
|
<td class="ok">✔</td>
|
247
247
|
<td class="ok">✔</td>
|
248
248
|
</tr>
|
249
|
+
<tr>
|
250
|
+
<td class="tg-yw4l">POSIX FORMATTING<br>column.format_number("$ %7.2f","en_US")</td>
|
251
|
+
<td class="ok">✔</td>
|
252
|
+
<td class="ok">✔</td>
|
253
|
+
<td class="ok">✔</td>
|
254
|
+
<td class="ok">✔</td>
|
255
|
+
<td class="ok">✔</td>
|
256
|
+
<td class="ko">not implemented</td>
|
257
|
+
</tr>
|
249
258
|
<tr>
|
250
259
|
<th class="tg-ffjm" rowspan="17"><div>String functions</div></th>
|
251
260
|
<td class="tg-yw4l">CONCAT<br>column + "string"</td>
|
data/TODO
CHANGED
@@ -14,7 +14,7 @@ TODO:
|
|
14
14
|
New features:
|
15
15
|
- POSIX format numbers (%.2f), dates (man 3 printf)
|
16
16
|
- cast, to_char
|
17
|
-
- auto-remove order by in sub queries
|
17
|
+
- auto-remove order by (when no limit) in sub queries
|
18
18
|
- avoid incompatible queries in PgSQL/Oracle/SQLServer when columns are used outside of group by columns (in select or order by)
|
19
19
|
|
20
20
|
Tests improvements:
|
@@ -68,7 +68,8 @@ module ArelExtensions
|
|
68
68
|
:precision => m[4] != '' ? m[4].to_i : 6,
|
69
69
|
:type => m[5],
|
70
70
|
:suffix => m[6],
|
71
|
-
:locale => locale
|
71
|
+
:locale => locale,
|
72
|
+
:original_string => format_string
|
72
73
|
}
|
73
74
|
# opts = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
|
74
75
|
ArelExtensions::Nodes::FormattedNumber.new [self,opts]
|
@@ -3,7 +3,7 @@ module ArelExtensions
|
|
3
3
|
class FormattedNumber < Function
|
4
4
|
RETURN_TYPE = :string
|
5
5
|
|
6
|
-
attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width,:precision, :type
|
6
|
+
attr_accessor :locale, :prefix, :suffix, :flags, :scientific_notation, :width,:precision, :type, :original_string
|
7
7
|
|
8
8
|
def initialize expr
|
9
9
|
# expr[1] = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
|
@@ -16,6 +16,7 @@ module ArelExtensions
|
|
16
16
|
@type = expr[1][:type]
|
17
17
|
@flags = expr[1][:flags]
|
18
18
|
@scientific_notation = /[eE]/.match(expr[1][:type]) || false
|
19
|
+
@original_string = expr[1][:original_string]
|
19
20
|
super [col]
|
20
21
|
end
|
21
22
|
|
@@ -8,6 +8,12 @@ module ArelExtensions
|
|
8
8
|
def is_null
|
9
9
|
ArelExtensions::Nodes::IsNull.new [self]
|
10
10
|
end
|
11
|
+
|
12
|
+
#ISNOTNULL function lets you return an alternative value when an expression is NOT NULL.
|
13
|
+
def is_not_null
|
14
|
+
ArelExtensions::Nodes::IsNotNull.new [self]
|
15
|
+
end
|
16
|
+
|
11
17
|
# returns the first non-null expr in the expression list. You must specify at least two expressions.
|
12
18
|
#If all occurrences of expr evaluate to null, then the function returns null.
|
13
19
|
def coalesce *args
|
@@ -18,6 +18,82 @@ module ArelExtensions
|
|
18
18
|
ArelExtensions::Nodes::Cast.new([self,right])
|
19
19
|
end
|
20
20
|
|
21
|
+
def in(other) #In should handle nil element in the Array
|
22
|
+
res = nil
|
23
|
+
case other
|
24
|
+
when Enumerable
|
25
|
+
if other.include?(nil)
|
26
|
+
other.delete(nil)
|
27
|
+
case other.length
|
28
|
+
when 0
|
29
|
+
res = self.is_null
|
30
|
+
when 1
|
31
|
+
res = self.is_null.or(self==other[0])
|
32
|
+
else
|
33
|
+
res = self.is_null.or(Arel::Nodes::In.new(self,other.map{|e| convert_to_node(e)}))
|
34
|
+
end
|
35
|
+
else
|
36
|
+
res = Arel::Nodes::In.new(self,other.map{|e| convert_to_node(e)})
|
37
|
+
end
|
38
|
+
when nil
|
39
|
+
res = self.is_null
|
40
|
+
when Arel::SelectManager
|
41
|
+
res = Arel::Nodes::In.new(self, other.ast)
|
42
|
+
when Range
|
43
|
+
res = self.between(other)
|
44
|
+
else
|
45
|
+
res = Arel::Nodes::In.new(self,convert_to_node(other))
|
46
|
+
end
|
47
|
+
res
|
48
|
+
end
|
49
|
+
|
50
|
+
def not_in(other) #In should handle nil element in the Array
|
51
|
+
res = nil
|
52
|
+
case other
|
53
|
+
when Enumerable
|
54
|
+
if other.include?(nil)
|
55
|
+
other.delete(nil)
|
56
|
+
case other.length
|
57
|
+
when 0
|
58
|
+
res = self.is_not_null
|
59
|
+
when 1
|
60
|
+
res = self.is_not_null.and(self!=other[0])
|
61
|
+
else
|
62
|
+
res = self.is_not_null.and(Arel::Nodes::NotIn.new(self,other.map{|e| convert_to_node(e)}))
|
63
|
+
end
|
64
|
+
else
|
65
|
+
res = Arel::Nodes::NotIn.new(self,other.map{|e| convert_to_node(e)})
|
66
|
+
end
|
67
|
+
when nil
|
68
|
+
res = self.is_not_null
|
69
|
+
when Arel::SelectManager
|
70
|
+
res = Arel::Nodes::NotIn.new(self, other.ast)
|
71
|
+
else
|
72
|
+
res = Arel::Nodes::NotIn.new(self,convert_to_node(other))
|
73
|
+
end
|
74
|
+
res
|
75
|
+
end
|
76
|
+
|
77
|
+
def convert_to_node(object)
|
78
|
+
case object
|
79
|
+
when Arel::Attributes::Attribute, Arel::Nodes::Node, Integer
|
80
|
+
object
|
81
|
+
when DateTime
|
82
|
+
Arel::Nodes.build_quoted(object, self)
|
83
|
+
when Time
|
84
|
+
Arel::Nodes.build_quoted(object.strftime('%H:%M:%S'), self)
|
85
|
+
when String
|
86
|
+
Arel::Nodes.build_quoted(object)
|
87
|
+
when Date
|
88
|
+
Arel::Nodes.build_quoted(object.to_s, self)
|
89
|
+
when NilClass
|
90
|
+
Arel.sql('NULL')
|
91
|
+
when ActiveSupport::Duration
|
92
|
+
object.to_i
|
93
|
+
else
|
94
|
+
raise(ArgumentError, "#{object.class} can not be converted to CONCAT arg")
|
95
|
+
end
|
96
|
+
end
|
21
97
|
|
22
98
|
end
|
23
99
|
end
|
@@ -7,6 +7,15 @@ require 'arel_extensions/visitors/mssql'
|
|
7
7
|
|
8
8
|
Arel::Visitors::MSSQL.class_eval do
|
9
9
|
include ArelExtensions::Visitors::MSSQL
|
10
|
+
|
11
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
12
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
13
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
14
|
+
o = o.dup
|
15
|
+
o.orders = []
|
16
|
+
end
|
17
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
18
|
+
end
|
10
19
|
end
|
11
20
|
|
12
21
|
begin
|
@@ -15,6 +24,15 @@ begin
|
|
15
24
|
if Arel::Visitors::VISITORS['sqlserver'] && Arel::Visitors::VISITORS['sqlserver'] != Arel::Visitors::MSSQL
|
16
25
|
Arel::Visitors::VISITORS['sqlserver'].class_eval do
|
17
26
|
include ArelExtensions::Visitors::MSSQL
|
27
|
+
|
28
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
29
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
30
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
31
|
+
o = o.dup
|
32
|
+
o.orders = []
|
33
|
+
end
|
34
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
35
|
+
end
|
18
36
|
end
|
19
37
|
end
|
20
38
|
end
|
@@ -56,6 +56,14 @@ module ArelExtensions
|
|
56
56
|
collector << " IS NULL)"
|
57
57
|
collector
|
58
58
|
end
|
59
|
+
|
60
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
61
|
+
collector << "("
|
62
|
+
collector = visit o.left, collector
|
63
|
+
# collector << Arel::Visitors::MSSQL::COMMA
|
64
|
+
collector << " IS NOT NULL)"
|
65
|
+
collector
|
66
|
+
end
|
59
67
|
|
60
68
|
# Deprecated
|
61
69
|
def visit_ArelExtensions_Nodes_ConcatOld o, collector
|
@@ -231,11 +239,11 @@ module ArelExtensions
|
|
231
239
|
end
|
232
240
|
|
233
241
|
def visit_ArelExtensions_Nodes_Blank o, collector
|
234
|
-
visit o.left.trim.length.eq(0), collector
|
242
|
+
visit o.left.coalesce('').trim.length.eq(0), collector
|
235
243
|
end
|
236
244
|
|
237
245
|
def visit_ArelExtensions_Nodes_NotBlank o, collector
|
238
|
-
visit o.left.trim.length.gt(0), collector
|
246
|
+
visit o.left.coalesce('').trim.length.gt(0), collector
|
239
247
|
end
|
240
248
|
|
241
249
|
def visit_ArelExtensions_Nodes_Format o, collector
|
@@ -432,6 +440,62 @@ module ArelExtensions
|
|
432
440
|
collector << ")"
|
433
441
|
collector
|
434
442
|
end
|
443
|
+
|
444
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
445
|
+
col = o.left
|
446
|
+
locale = Arel::Nodes.build_quoted(o.locale.tr('_','-'))
|
447
|
+
param = Arel::Nodes.build_quoted("N#{o.precision}")
|
448
|
+
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
449
|
+
then('-').
|
450
|
+
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
451
|
+
sign_length = o.flags.include?('+') || o.flags.include?(' ') ?
|
452
|
+
Arel::Nodes.build_quoted(1) :
|
453
|
+
ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
|
454
|
+
|
455
|
+
if o.scientific_notation
|
456
|
+
number = ArelExtensions::Nodes::Concat.new([
|
457
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
458
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
459
|
+
param,
|
460
|
+
locale
|
461
|
+
]),
|
462
|
+
o.type,
|
463
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
464
|
+
col.abs.log10.floor,
|
465
|
+
Arel::Nodes.build_quoted('N0'),
|
466
|
+
locale
|
467
|
+
])
|
468
|
+
])
|
469
|
+
else
|
470
|
+
number = Arel::Nodes::NamedFunction.new('FORMAT',[
|
471
|
+
Arel::Nodes.build_quoted(col.abs),
|
472
|
+
param,
|
473
|
+
locale
|
474
|
+
])
|
475
|
+
end
|
476
|
+
|
477
|
+
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
478
|
+
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
479
|
+
then(Arel::Nodes.build_quoted(
|
480
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
481
|
+
).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
|
482
|
+
).
|
483
|
+
else('')
|
484
|
+
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
485
|
+
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
486
|
+
after = o.flags.include?('-') ? repeated_char : ''
|
487
|
+
full_number = col.when(0).then('0').else(
|
488
|
+
ArelExtensions::Nodes::Concat.new([
|
489
|
+
before,
|
490
|
+
sign,
|
491
|
+
middle,
|
492
|
+
number,
|
493
|
+
after
|
494
|
+
])
|
495
|
+
)
|
496
|
+
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
497
|
+
collector
|
498
|
+
end
|
435
499
|
|
436
500
|
end
|
437
501
|
end
|
@@ -255,6 +255,17 @@ module ArelExtensions
|
|
255
255
|
collector << ")"
|
256
256
|
collector
|
257
257
|
end
|
258
|
+
|
259
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
260
|
+
collector << "NOT ISNULL("
|
261
|
+
collector = visit o.left, collector
|
262
|
+
if o.right
|
263
|
+
collector << Arel::Visitors::MySQL::COMMA
|
264
|
+
collector = visit o.right, collector
|
265
|
+
end
|
266
|
+
collector << ")"
|
267
|
+
collector
|
268
|
+
end
|
258
269
|
|
259
270
|
def visit_ArelExtensions_Nodes_Wday o, collector
|
260
271
|
collector << "(WEEKDAY("
|
@@ -285,7 +296,63 @@ module ArelExtensions
|
|
285
296
|
collector << ")"
|
286
297
|
collector
|
287
298
|
end
|
288
|
-
|
299
|
+
|
300
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
301
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
302
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
303
|
+
o = o.dup
|
304
|
+
o.orders = []
|
305
|
+
end
|
306
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
307
|
+
end
|
308
|
+
|
309
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
310
|
+
col = o.left
|
311
|
+
params = o.locale ? [o.precision,Arel::Nodes.build_quoted(o.locale)] : [o.precision]
|
312
|
+
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
313
|
+
then('-').
|
314
|
+
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
315
|
+
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
316
|
+
|
317
|
+
if o.scientific_notation
|
318
|
+
number = ArelExtensions::Nodes::Concat.new([
|
319
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
320
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
|
321
|
+
]+params),
|
322
|
+
o.type,
|
323
|
+
Arel::Nodes::NamedFunction.new('FORMAT',[
|
324
|
+
col.abs.log10.floor,
|
325
|
+
0
|
326
|
+
])
|
327
|
+
])
|
328
|
+
else
|
329
|
+
number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
|
330
|
+
end
|
331
|
+
|
332
|
+
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
333
|
+
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
334
|
+
then(Arel::Nodes.build_quoted(
|
335
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
336
|
+
).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
|
337
|
+
).
|
338
|
+
else('')
|
339
|
+
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
340
|
+
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
341
|
+
after = o.flags.include?('-') ? repeated_char : ''
|
342
|
+
full_number = col.when(0).then('0').else(
|
343
|
+
ArelExtensions::Nodes::Concat.new([
|
344
|
+
before,
|
345
|
+
sign,
|
346
|
+
middle,
|
347
|
+
number,
|
348
|
+
after
|
349
|
+
])
|
350
|
+
)
|
351
|
+
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
352
|
+
collector
|
353
|
+
end
|
354
|
+
|
355
|
+
|
289
356
|
end
|
290
357
|
end
|
291
358
|
end
|
@@ -9,6 +9,7 @@ module ArelExtensions
|
|
9
9
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
10
10
|
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
11
11
|
}
|
12
|
+
Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ', ' }
|
12
13
|
|
13
14
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
14
15
|
collector << "LOG("
|
@@ -241,6 +242,12 @@ module ArelExtensions
|
|
241
242
|
collector << ' IS NULL'
|
242
243
|
collector
|
243
244
|
end
|
245
|
+
|
246
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
247
|
+
collector = visit o.left, collector
|
248
|
+
collector << ' IS NOT NULL'
|
249
|
+
collector
|
250
|
+
end
|
244
251
|
|
245
252
|
def visit_ArelExtensions_Nodes_Rand o, collector
|
246
253
|
collector << "DBMS_RANDOM.VALUE("
|
@@ -374,7 +381,9 @@ module ArelExtensions
|
|
374
381
|
end
|
375
382
|
|
376
383
|
def visit_ArelExtensions_Nodes_Repeat o, collector
|
377
|
-
collector << "LPAD(
|
384
|
+
collector << "LPAD("
|
385
|
+
collector = visit o.expressions[0], collector #can't put empty string, otherwise it wouldn't work
|
386
|
+
collector << Arel::Visitors::ToSql::COMMA
|
378
387
|
collector = visit o.expressions[1], collector
|
379
388
|
collector << Arel::Visitors::ToSql::COMMA
|
380
389
|
collector = visit o.expressions[0], collector
|
@@ -493,6 +502,69 @@ module ArelExtensions
|
|
493
502
|
collector
|
494
503
|
end
|
495
504
|
|
505
|
+
|
506
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
507
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
508
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
509
|
+
o = o.dup
|
510
|
+
o.orders = []
|
511
|
+
end
|
512
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
513
|
+
end
|
514
|
+
|
515
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
516
|
+
col = o.left
|
517
|
+
comma = Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
518
|
+
options = Arel::Nodes.build_quoted("NLS_NUMERIC_CHARACTERS = '"+comma+"'")
|
519
|
+
nines_after = (1..o.precision).map{'9'}.join('')
|
520
|
+
nines_before = (1..16).map{'9'}.join('')
|
521
|
+
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
522
|
+
then('-').
|
523
|
+
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
524
|
+
sign_length = o.flags.include?('+') || o.flags.include?(' ') ?
|
525
|
+
Arel::Nodes.build_quoted(1) :
|
526
|
+
ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
|
527
|
+
|
528
|
+
if o.scientific_notation
|
529
|
+
number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
530
|
+
Arel::Nodes.build_quoted(col.abs),
|
531
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'D'+nines_after+'EEEE'),
|
532
|
+
options
|
533
|
+
])
|
534
|
+
if o.type == 'e'
|
535
|
+
number = number.replace('E','e')
|
536
|
+
end
|
537
|
+
else
|
538
|
+
number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
539
|
+
Arel::Nodes.build_quoted(col.abs),
|
540
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'D'+nines_after),
|
541
|
+
options
|
542
|
+
])
|
543
|
+
end
|
544
|
+
|
545
|
+
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
546
|
+
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
547
|
+
then(Arel::Nodes.build_quoted(
|
548
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
549
|
+
).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
|
550
|
+
).
|
551
|
+
else('')
|
552
|
+
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
553
|
+
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
554
|
+
after = o.flags.include?('-') ? repeated_char : ''
|
555
|
+
full_number = col.when(0).then('0').else(
|
556
|
+
ArelExtensions::Nodes::Concat.new([
|
557
|
+
before,
|
558
|
+
sign,
|
559
|
+
middle,
|
560
|
+
number,
|
561
|
+
after
|
562
|
+
])
|
563
|
+
)
|
564
|
+
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
565
|
+
collector
|
566
|
+
end
|
567
|
+
|
496
568
|
|
497
569
|
end
|
498
570
|
end
|
@@ -8,6 +8,7 @@ module ArelExtensions
|
|
8
8
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
9
9
|
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
10
10
|
}
|
11
|
+
Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = { 'en_US' => '.', 'fr_FR' => ',' }
|
11
12
|
|
12
13
|
def visit_ArelExtensions_Nodes_Rand o, collector
|
13
14
|
collector << "RANDOM("
|
@@ -234,6 +235,12 @@ module ArelExtensions
|
|
234
235
|
collector << ' IS NULL'
|
235
236
|
collector
|
236
237
|
end
|
238
|
+
|
239
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
240
|
+
collector = visit o.left, collector
|
241
|
+
collector << ' IS NOT NULL'
|
242
|
+
collector
|
243
|
+
end
|
237
244
|
|
238
245
|
def visit_ArelExtensions_Nodes_Sum o, collector
|
239
246
|
collector << "sum("
|
@@ -272,6 +279,67 @@ module ArelExtensions
|
|
272
279
|
collector
|
273
280
|
end
|
274
281
|
|
282
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
283
|
+
col = o.left
|
284
|
+
comma = Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] || '.'
|
285
|
+
nines_after = (1..o.precision).map{'9'}.join('')
|
286
|
+
nines_before = (1..16).map{'9'}.join('')
|
287
|
+
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
288
|
+
then('-').
|
289
|
+
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
290
|
+
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
291
|
+
|
292
|
+
if o.scientific_notation
|
293
|
+
number = ArelExtensions::Nodes::Concat.new([
|
294
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
295
|
+
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
|
296
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
297
|
+
]),
|
298
|
+
o.type,
|
299
|
+
Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
300
|
+
col.abs.log10.floor,
|
301
|
+
Arel::Nodes.build_quoted('FM'+nines_before)
|
302
|
+
])
|
303
|
+
])
|
304
|
+
else
|
305
|
+
number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
306
|
+
Arel::Nodes.build_quoted(col.abs),
|
307
|
+
Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
|
308
|
+
])
|
309
|
+
end
|
310
|
+
|
311
|
+
repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
|
312
|
+
when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
|
313
|
+
then(Arel::Nodes.build_quoted(
|
314
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
315
|
+
).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
|
316
|
+
).
|
317
|
+
else('')
|
318
|
+
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
319
|
+
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
320
|
+
after = o.flags.include?('-') ? repeated_char : ''
|
321
|
+
full_number = col.when(0).then('0').else(
|
322
|
+
ArelExtensions::Nodes::Concat.new([
|
323
|
+
before,
|
324
|
+
sign,
|
325
|
+
middle,
|
326
|
+
number,
|
327
|
+
after
|
328
|
+
])
|
329
|
+
)
|
330
|
+
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
331
|
+
collector
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
336
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
337
|
+
if !collector.value.blank? && o.limit.blank? && o.offset.blank?
|
338
|
+
o = o.dup
|
339
|
+
o.orders = []
|
340
|
+
end
|
341
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
342
|
+
end
|
275
343
|
|
276
344
|
end
|
277
345
|
end
|
@@ -8,6 +8,7 @@ module ArelExtensions
|
|
8
8
|
'%H' => '%H', '%k' => '%k', '%I' => '%I', '%l' => '%l', '%P' => '%p', '%p' => '%p', # hours
|
9
9
|
'%M' => '%M', '%S' => '%S', '%L' => '', '%N' => '%f', '%z' => '' # seconds, subseconds
|
10
10
|
}
|
11
|
+
Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING = { 'fr_FR' => {',' => ' ','.' =>','} }
|
11
12
|
|
12
13
|
#String functions
|
13
14
|
def visit_ArelExtensions_Nodes_IMatches o, collector # insensitive on ASCII
|
@@ -153,6 +154,12 @@ module ArelExtensions
|
|
153
154
|
collector << ' IS NULL'
|
154
155
|
collector
|
155
156
|
end
|
157
|
+
|
158
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
159
|
+
collector = visit o.left, collector
|
160
|
+
collector << ' IS NOT NULL'
|
161
|
+
collector
|
162
|
+
end
|
156
163
|
|
157
164
|
def visit_ArelExtensions_Nodes_Rand o, collector
|
158
165
|
collector << "RANDOM("
|
@@ -319,7 +326,7 @@ module ArelExtensions
|
|
319
326
|
|
320
327
|
remove_method(:visit_Arel_Nodes_GreaterThan) rescue nil
|
321
328
|
def visit_Arel_Nodes_GreaterThan o, collector
|
322
|
-
|
329
|
+
collector = visit get_time_converted(o.left), collector
|
323
330
|
collector << " > "
|
324
331
|
collector = visit get_time_converted(o.right), collector
|
325
332
|
collector
|
@@ -327,7 +334,7 @@ module ArelExtensions
|
|
327
334
|
|
328
335
|
remove_method(:visit_Arel_Nodes_LessThanOrEqual) rescue nil
|
329
336
|
def visit_Arel_Nodes_LessThanOrEqual o, collector
|
330
|
-
|
337
|
+
collector = visit get_time_converted(o.left), collector
|
331
338
|
collector << " <= "
|
332
339
|
collector = visit get_time_converted(o.right), collector
|
333
340
|
collector
|
@@ -335,12 +342,33 @@ module ArelExtensions
|
|
335
342
|
|
336
343
|
remove_method(:visit_Arel_Nodes_LessThan) rescue nil
|
337
344
|
def visit_Arel_Nodes_LessThan o, collector
|
338
|
-
|
345
|
+
collector = visit get_time_converted(o.left), collector
|
339
346
|
collector << " < "
|
340
347
|
collector = visit get_time_converted(o.right), collector
|
341
348
|
collector
|
342
349
|
end
|
350
|
+
|
351
|
+
|
352
|
+
alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
|
353
|
+
def visit_Arel_Nodes_SelectStatement o, collector
|
354
|
+
if !collector.value.blank? && o.limit.blank?
|
355
|
+
o = o.dup
|
356
|
+
o.orders = []
|
357
|
+
end
|
358
|
+
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
359
|
+
end
|
343
360
|
|
361
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
362
|
+
|
363
|
+
format = Arel::Nodes::NamedFunction.new('printf',[Arel::Nodes.build_quoted(o.original_string),o.left])
|
364
|
+
locale_map = Arel::Visitors::SQLite::NUMBER_COMMA_MAPPING[o.locale]
|
365
|
+
if locale_map
|
366
|
+
format = format.replace(',',locale_map[',']).replace('.',locale_map['.'])
|
367
|
+
end
|
368
|
+
visit format, collector
|
369
|
+
collector
|
370
|
+
end
|
371
|
+
|
344
372
|
end
|
345
373
|
end
|
346
374
|
end
|
@@ -366,6 +366,13 @@ module ArelExtensions
|
|
366
366
|
collector << ")"
|
367
367
|
collector
|
368
368
|
end
|
369
|
+
|
370
|
+
def visit_ArelExtensions_Nodes_IsNotNull o, collector
|
371
|
+
collector << "NOT ISNULL("
|
372
|
+
collector = visit o.left, collector
|
373
|
+
collector << ")"
|
374
|
+
collector
|
375
|
+
end
|
369
376
|
|
370
377
|
def visit_ArelExtensions_Nodes_Then o, collector
|
371
378
|
collector << "CASE WHEN ("
|
@@ -434,109 +441,67 @@ module ArelExtensions
|
|
434
441
|
end
|
435
442
|
end
|
436
443
|
|
437
|
-
|
438
|
-
collector = visit o.left, collector
|
439
|
-
collector << " UNION "
|
440
|
-
collector = visit o.right, collector
|
441
|
-
collector
|
442
|
-
end
|
443
|
-
|
444
|
-
def visit_ArelExtensions_Nodes_UnionAll o, collector
|
445
|
-
collector = visit o.left, collector
|
446
|
-
collector << " UNION ALL "
|
447
|
-
collector = visit o.right, collector
|
448
|
-
collector
|
449
|
-
end
|
450
|
-
|
451
|
-
def visit_ArelExtensions_Nodes_As o, collector
|
452
|
-
if o.left.is_a?(ArelExtensions::Nodes::Union) || o.left.is_a?(ArelExtensions::Nodes::UnionAll)
|
453
|
-
collector << "("
|
444
|
+
def visit_ArelExtensions_Nodes_Union o, collector
|
454
445
|
collector = visit o.left, collector
|
455
|
-
collector << "
|
456
|
-
visit o.right, collector
|
457
|
-
|
446
|
+
collector << " UNION "
|
447
|
+
collector = visit o.right, collector
|
448
|
+
collector
|
449
|
+
end
|
450
|
+
|
451
|
+
def visit_ArelExtensions_Nodes_UnionAll o, collector
|
458
452
|
collector = visit o.left, collector
|
459
|
-
collector << "
|
453
|
+
collector << " UNION ALL "
|
454
|
+
collector = visit o.right, collector
|
455
|
+
collector
|
456
|
+
end
|
457
|
+
|
458
|
+
def visit_ArelExtensions_Nodes_As o, collector
|
459
|
+
if o.left.is_a?(ArelExtensions::Nodes::Union) || o.left.is_a?(ArelExtensions::Nodes::UnionAll)
|
460
|
+
collector << "("
|
461
|
+
collector = visit o.left, collector
|
462
|
+
collector << ") "
|
463
|
+
visit o.right, collector
|
464
|
+
else
|
465
|
+
collector = visit o.left, collector
|
466
|
+
collector << " AS "
|
467
|
+
visit o.right, collector
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
def visit_ArelExtensions_Nodes_Case o, collector
|
472
|
+
collector << "CASE "
|
473
|
+
if o.case
|
474
|
+
visit o.case, collector
|
475
|
+
collector << " "
|
476
|
+
end
|
477
|
+
o.conditions.each do |condition|
|
478
|
+
visit condition, collector
|
479
|
+
collector << " "
|
480
|
+
end
|
481
|
+
if o.default
|
482
|
+
visit o.default, collector
|
483
|
+
collector << " "
|
484
|
+
end
|
485
|
+
collector << "END"
|
486
|
+
end
|
487
|
+
|
488
|
+
def visit_ArelExtensions_Nodes_When o, collector
|
489
|
+
collector << "WHEN "
|
490
|
+
visit o.left, collector
|
491
|
+
collector << " THEN "
|
460
492
|
visit o.right, collector
|
461
493
|
end
|
462
|
-
end
|
463
|
-
|
464
|
-
def visit_ArelExtensions_Nodes_Case o, collector
|
465
|
-
collector << "CASE "
|
466
|
-
if o.case
|
467
|
-
visit o.case, collector
|
468
|
-
collector << " "
|
469
|
-
end
|
470
|
-
o.conditions.each do |condition|
|
471
|
-
visit condition, collector
|
472
|
-
collector << " "
|
473
|
-
end
|
474
|
-
if o.default
|
475
|
-
visit o.default, collector
|
476
|
-
collector << " "
|
477
|
-
end
|
478
|
-
collector << "END"
|
479
|
-
end
|
480
|
-
|
481
|
-
def visit_ArelExtensions_Nodes_When o, collector
|
482
|
-
collector << "WHEN "
|
483
|
-
visit o.left, collector
|
484
|
-
collector << " THEN "
|
485
|
-
visit o.right, collector
|
486
|
-
end
|
487
494
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
end
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
496
|
-
col = o.left
|
497
|
-
params = o.locale ? [o.precision,Arel::Nodes.build_quoted(o.locale)] : [o.precision]
|
498
|
-
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
499
|
-
then('-').
|
500
|
-
else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
|
501
|
-
sign_length = ArelExtensions::Nodes::Length.new([sign])
|
502
|
-
|
503
|
-
if o.scientific_notation
|
504
|
-
number = ArelExtensions::Nodes::Concat.new([
|
505
|
-
Arel::Nodes::NamedFunction.new('FORMAT',[
|
506
|
-
col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
|
507
|
-
]+params),
|
508
|
-
o.type,
|
509
|
-
Arel::Nodes::NamedFunction.new('FORMAT',[
|
510
|
-
col.abs.log10.floor,
|
511
|
-
0
|
512
|
-
])
|
513
|
-
])
|
514
|
-
else
|
515
|
-
number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
|
495
|
+
def visit_ArelExtensions_Nodes_Else o, collector
|
496
|
+
collector << "ELSE "
|
497
|
+
visit o.expr, collector
|
516
498
|
end
|
517
499
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
).
|
524
|
-
else('')
|
525
|
-
before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
526
|
-
middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
|
527
|
-
after = o.flags.include?('-') ? repeated_char : ''
|
528
|
-
full_number = col.when(0).then(0).else(
|
529
|
-
ArelExtensions::Nodes::Concat.new([
|
530
|
-
before,
|
531
|
-
sign,
|
532
|
-
middle,
|
533
|
-
number,
|
534
|
-
after
|
535
|
-
])
|
536
|
-
)
|
537
|
-
collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
|
538
|
-
collector
|
539
|
-
end
|
500
|
+
|
501
|
+
|
502
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
503
|
+
visit o.left, collector
|
504
|
+
end
|
540
505
|
|
541
506
|
remove_method(:visit_Arel_Nodes_LessThan) rescue nil
|
542
507
|
def visit_Arel_Nodes_LessThan o, collector
|
@@ -545,6 +510,8 @@ module ArelExtensions
|
|
545
510
|
visit o.right, collector
|
546
511
|
end
|
547
512
|
|
513
|
+
|
514
|
+
|
548
515
|
end
|
549
516
|
end
|
550
517
|
end
|
@@ -302,15 +302,24 @@ module ArelExtensions
|
|
302
302
|
.must_be_like %{(CAST("users"."id" AS int) + 2)}
|
303
303
|
end
|
304
304
|
|
305
|
+
it "should be possible to to have nil element in the function NIL" do
|
306
|
+
compile(@table[:id].in(nil))
|
307
|
+
.must_be_like %{ISNULL("users"."id")}
|
308
|
+
compile(@table[:id].in([nil]))
|
309
|
+
.must_be_like %{ISNULL("users"."id")}
|
310
|
+
compile(@table[:id].in([nil,1]))
|
311
|
+
.must_be_like %{(ISNULL("users"."id") OR "users"."id" = 1)}
|
312
|
+
compile(@table[:id].in([nil,1,2]))
|
313
|
+
.must_be_like %{(ISNULL("users"."id") OR "users"."id" IN (1, 2))}
|
314
|
+
compile(@table[:id].in(1))
|
315
|
+
.must_be_like %{"users"."id" IN (1)}
|
316
|
+
compile(@table[:id].in([1]))
|
317
|
+
.must_be_like %{"users"."id" IN (1)}
|
318
|
+
compile(@table[:id].in([1,2]))
|
319
|
+
.must_be_like %{"users"."id" IN (1, 2)}
|
305
320
|
|
306
|
-
it "should be possible to specify a cool format on number" do
|
307
|
-
#puts @price.format_number("$$ %+030.2e €€","fr_FR").to_sql
|
308
|
-
compile(@price.format_number("$$ %+030.2e €€","fr_FR"))
|
309
|
-
.must_be_like %{CONCAT('$$ ', CASE \"products\".\"price\" WHEN 0 THEN 0 ELSE CONCAT('', CASE WHEN \"products\".\"price\" < 0 THEN '-' ELSE '+' END, CASE WHEN (ABS(30) - (LENGTH(CONCAT(FORMAT(ABS(\"products\".\"price\") / POW(10, FLOOR(LOG10(ABS(\"products\".\"price\")))), 2, 'fr_FR'), 'e', FORMAT(FLOOR(LOG10(ABS(\"products\".\"price\"))), 0))) + LENGTH(CASE WHEN \"products\".\"price\" < 0 THEN '-' ELSE '+' END))) > 0 THEN REPEAT('0', (ABS(30) - (LENGTH(CONCAT(FORMAT(ABS(\"products\".\"price\") / POW(10, FLOOR(LOG10(ABS(\"products\".\"price\")))), 2, 'fr_FR'), 'e', FORMAT(FLOOR(LOG10(ABS(\"products\".\"price\"))), 0))) + LENGTH(CASE WHEN \"products\".\"price\" < 0 THEN '-' ELSE '+' END)))) ELSE '' END, CONCAT(FORMAT(ABS(\"products\".\"price\") / POW(10, FLOOR(LOG10(ABS(\"products\".\"price\")))), 2, 'fr_FR'), 'e', FORMAT(FLOOR(LOG10(ABS(\"products\".\"price\"))), 0)), '') END, ' €€')}
|
310
321
|
end
|
311
|
-
|
312
|
-
|
313
|
-
|
322
|
+
|
314
323
|
puts "AREL VERSION : " + Arel::VERSION.to_s
|
315
324
|
end
|
316
325
|
end
|
@@ -55,7 +55,7 @@ module ArelExtensions
|
|
55
55
|
@lucas = User.where(:id => u.id)
|
56
56
|
u = User.create :age => 15, :name => "Sophie", :created_at => d, :score => 20.16
|
57
57
|
@sophie = User.where(:id => u.id)
|
58
|
-
u = User.create :age => 20, :name => "Camille", :created_at => d, :score => -20.16
|
58
|
+
u = User.create :age => 20, :name => "Camille", :created_at => d, :score => -20.16, :comments => ''
|
59
59
|
@camille = User.where(:id => u.id)
|
60
60
|
u = User.create :age => 21, :name => "Arthur", :created_at => d, :score => 65.62, :comments => 'arrêté'
|
61
61
|
@arthur = User.where(:id => u.id)
|
@@ -310,9 +310,14 @@ module ArelExtensions
|
|
310
310
|
assert_equal 0, @myung.where(@name.blank).count
|
311
311
|
assert_equal 1, @myung.where(@name.not_blank).count
|
312
312
|
assert_equal 1, @myung.where(@comments.blank).count
|
313
|
+
assert_equal 0, @myung.where(@comments.not_blank).count
|
314
|
+
assert_equal 1, @sophie.where(@comments.blank).count
|
315
|
+
assert_equal 0, @sophie.where(@comments.not_blank).count
|
316
|
+
assert_equal 1, @camille.where(@comments.blank).count
|
317
|
+
assert_equal 0, @camille.where(@comments.not_blank).count
|
318
|
+
|
313
319
|
assert_equal 0, @neg.where(@comments.blank).count
|
314
320
|
assert_equal 1, @neg.where(@comments.not_blank).count
|
315
|
-
assert_equal 0, @myung.where(@comments.not_blank).count
|
316
321
|
assert_equal 'false', t(@myung, @name.blank.then('true', 'false'))
|
317
322
|
assert_equal 'true', t(@myung, @name.not_blank.then('true', 'false'))
|
318
323
|
assert_equal 'true', t(@myung, @comments.blank.then('true', 'false'))
|
@@ -437,9 +442,12 @@ module ArelExtensions
|
|
437
442
|
assert_equal "Sophie2", t(@sophie, @name + 2)
|
438
443
|
assert_equal "Sophie1997-06-15", t(@sophie, @name + d)
|
439
444
|
assert_equal "Sophie15", t(@sophie, @name + @age)
|
440
|
-
assert_equal "SophieSophie", t(@sophie, @name + @name)
|
445
|
+
assert_equal "SophieSophie", t(@sophie, @name + @name)
|
446
|
+
assert_equal "SophieSophieSophie", t(@sophie, @name + @name + @name)
|
447
|
+
assert_equal "SophieSophieSophie", t(@sophie, @name.concat(@name.concat(@name)))
|
448
|
+
assert_equal "SophieSophieSophie", t(@sophie, @name.concat(@name).concat(@name))
|
441
449
|
#FIXME: should work as expected in Oracle
|
442
|
-
assert_equal "Sophie2016-05-23", t(@sophie, @name + @created_at) unless @env_db == 'oracle'
|
450
|
+
assert_equal "Sophie2016-05-23", t(@sophie, @name + @created_at) unless @env_db == 'oracle'
|
443
451
|
#concat Integer
|
444
452
|
assert_equal 1, User.where((@age + 10).eq(33)).count
|
445
453
|
assert_equal 1, User.where((@age + "1").eq(6)).count
|
@@ -496,20 +504,22 @@ module ArelExtensions
|
|
496
504
|
assert_equal 4, User.find_by_sql(@ut.project(@score.when(20.16).then(1).else(0).as('score_bin')).to_sql).sum(&:score_bin)
|
497
505
|
end
|
498
506
|
|
499
|
-
def test_format_numbers
|
500
|
-
skip "Not yet implemented" if @env_db != 'mysql'
|
507
|
+
def test_format_numbers
|
501
508
|
#score of Arthur = 65.62
|
509
|
+
skip " Works with SQLite if the version used knows printf" if @env_db = $sqlite
|
502
510
|
assert_equal "AZERTY65,62" , t(@arthur, @score.format_number("AZERTY%.2f","fr_FR"))
|
503
511
|
assert_equal "65,62AZERTY" , t(@arthur, @score.format_number("%.2fAZERTY","fr_FR"))
|
504
|
-
assert_equal "$ 65.62 €" , t(@arthur, @score.format_number("$ %.2f €","
|
512
|
+
assert_equal "$ 65.62 €" , t(@arthur, @score.format_number("$ %.2f €","en_US"))
|
505
513
|
assert_equal "$ 0065,62 €" , t(@arthur, @score.format_number("$ %07.2f €","fr_FR"))
|
506
514
|
assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-07.2f €","fr_FR"))
|
507
515
|
assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-7.2f €","fr_FR"))
|
508
516
|
assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ % 7.2f €","fr_FR"))
|
517
|
+
assert_equal "$ 65,6 €" , t(@arthur, @score.format_number("$ % 7.1f €","fr_FR"))
|
509
518
|
assert_equal "$ +65,62 €" , t(@arthur, @score.format_number("$ % +7.2f €","fr_FR"))
|
510
|
-
assert_equal "$ +065,62 €" , t(@arthur, @score.format_number("$ %0+7.2f €","fr_FR"))
|
511
|
-
|
512
|
-
|
519
|
+
assert_equal "$ +065,62 €" , t(@arthur, @score.format_number("$ %0+7.2f €","fr_FR"))
|
520
|
+
assert_includes ["$ 6,56e1 €","$ 6,56e+01 €"], t(@arthur, @score.format_number("$ %.2e €","fr_FR"))
|
521
|
+
assert_includes ["$ 6,56E1 €","$ 6,56E+01 €"], t(@arthur, @score.format_number("$ %.2E €","fr_FR"))
|
522
|
+
assert_includes ["$ 6,562E1 €","$ 6,562E+01 €"], t(@arthur, @score.format_number("$ %.3E €","fr_FR"))
|
513
523
|
assert_equal "Wrong Format" , t(@arthur, @score.format_number("$ %...234.6F €","fr_FR"))
|
514
524
|
end
|
515
525
|
|
@@ -554,6 +564,65 @@ module ArelExtensions
|
|
554
564
|
assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrete")).then("1").else("0"))
|
555
565
|
assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrêté")).then("1").else("0"))
|
556
566
|
end
|
567
|
+
|
568
|
+
def test_subquery_with_order
|
569
|
+
assert_equal 8, User.where(:name => User.select(:name).order(:name)).count
|
570
|
+
assert_equal 8, User.where(@ut[:name].in(@ut.project(@ut[:name]).order(@ut[:name]))).count
|
571
|
+
if !['mysql'].include?(@env_db) # MySql can't have limit in IN subquery
|
572
|
+
assert_equal 2, User.where(:name => User.select(:name).order(:name).limit(2)).count
|
573
|
+
#assert_equal 6, User.where(:name => User.select(:name).order(:name).offset(2)).count
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_in_with_nil
|
578
|
+
assert_equal true , @myung.where(@age.in(1)).blank?
|
579
|
+
assert_equal false , @myung.where(@age.in(23)).blank?
|
580
|
+
assert_equal true , @myung.where(@age.in([1])).blank?
|
581
|
+
assert_equal true , @myung.where(@age.in([1,2])).blank?
|
582
|
+
assert_equal false , @myung.where(@age.in([1,23])).blank?
|
583
|
+
assert_equal true , @myung.where(@age.in(nil)).blank?
|
584
|
+
assert_equal true , @myung.where(@age.in([nil])).blank?
|
585
|
+
assert_equal true , @myung.where(@age.in([nil,1])).blank?
|
586
|
+
assert_equal false , @myung.where(@age.in([nil,23])).blank?
|
587
|
+
assert_equal true , @myung.where(@age.in([nil,1,2])).blank?
|
588
|
+
assert_equal false , @myung.where(@age.in([nil,1,23])).blank?
|
589
|
+
assert_equal true , @test.where(@age.in(1)).blank?
|
590
|
+
assert_equal true , @test.where(@age.in([1])).blank?
|
591
|
+
assert_equal true , @test.where(@age.in([1,2])).blank?
|
592
|
+
assert_equal false , @test.where(@age.in(nil)).blank?
|
593
|
+
assert_equal false , @test.where(@age.in([nil])).blank?
|
594
|
+
assert_equal false , @test.where(@age.in([nil,1])).blank?
|
595
|
+
assert_equal false , @test.where(@age.in([nil,1,2])).blank?
|
596
|
+
end
|
597
|
+
|
598
|
+
def test_is_not_null
|
599
|
+
assert_equal false , @myung.where(@age.is_not_null).blank?
|
600
|
+
assert_equal true , @test.where(@age.is_not_null).blank?
|
601
|
+
end
|
602
|
+
|
603
|
+
def test_not_in_with_nil
|
604
|
+
assert_equal false , @myung.where(@age.not_in(1)).blank?
|
605
|
+
assert_equal true , @myung.where(@age.not_in(23)).blank?
|
606
|
+
assert_equal false , @myung.where(@age.not_in([1])).blank?
|
607
|
+
assert_equal false , @myung.where(@age.not_in([1,2])).blank?
|
608
|
+
assert_equal true , @myung.where(@age.not_in([1,23])).blank?
|
609
|
+
assert_equal false , @myung.where(@age.not_in(nil)).blank?
|
610
|
+
assert_equal false , @myung.where(@age.not_in([nil])).blank?
|
611
|
+
assert_equal false , @myung.where(@age.not_in([nil,1])).blank?
|
612
|
+
assert_equal true , @myung.where(@age.not_in([nil,23])).blank?
|
613
|
+
assert_equal false , @myung.where(@age.not_in([nil,1,2])).blank?
|
614
|
+
assert_equal true , @myung.where(@age.not_in([nil,1,23])).blank?
|
615
|
+
|
616
|
+
#if the column is null, the entry will never be selected with not in (like every DBMS does)
|
617
|
+
#assert_equal false , @test.where(@age.not_in(1)).blank?
|
618
|
+
#assert_equal false , @test.where(@age.not_in([1])).blank?
|
619
|
+
#assert_equal false , @test.where(@age.not_in([1,2])).blank?
|
620
|
+
#assert_equal true , @test.where(@age.not_in(nil)).blank?
|
621
|
+
#assert_equal true , @test.where(@age.not_in([nil])).blank?
|
622
|
+
#assert_equal true , @test.where(@age.not_in([nil,1])).blank?
|
623
|
+
#assert_equal true , @test.where(@age.not_in([nil,1,2])).blank?
|
624
|
+
end
|
625
|
+
|
557
626
|
end
|
558
627
|
end
|
559
628
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yann Azoury
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-
|
13
|
+
date: 2018-06-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|