arel_extensions 1.3.4 → 1.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +41 -89
- data/.gitignore +7 -6
- data/.rubocop.yml +37 -0
- data/Gemfile +3 -3
- data/README.md +1 -0
- data/appveyor.yml +73 -0
- data/gemfiles/rails3.gemfile +5 -5
- data/gemfiles/rails4.gemfile +7 -7
- data/gemfiles/rails5_0.gemfile +6 -6
- data/gemfiles/rails5_1_4.gemfile +6 -6
- data/gemfiles/rails5_2.gemfile +6 -5
- data/gemfiles/rails6.gemfile +5 -4
- data/gemfiles/rails6_1.gemfile +5 -4
- data/gemfiles/rails7.gemfile +5 -4
- data/lib/arel_extensions/common_sql_functions.rb +2 -2
- data/lib/arel_extensions/helpers.rb +12 -12
- data/lib/arel_extensions/math.rb +32 -17
- data/lib/arel_extensions/nodes/cast.rb +2 -2
- data/lib/arel_extensions/nodes/coalesce.rb +1 -1
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/date_diff.rb +6 -6
- data/lib/arel_extensions/nodes/locate.rb +1 -1
- data/lib/arel_extensions/nodes/repeat.rb +2 -2
- data/lib/arel_extensions/nodes/substring.rb +1 -1
- 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 +2 -2
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +30 -17
- data/lib/arel_extensions/visitors/mysql.rb +15 -10
- data/lib/arel_extensions/visitors/oracle.rb +22 -17
- data/lib/arel_extensions/visitors/postgresql.rb +17 -12
- data/lib/arel_extensions/visitors/sqlite.rb +4 -4
- data/lib/arel_extensions/visitors/to_sql.rb +4 -1
- data/lib/arel_extensions.rb +10 -0
- data/test/arelx_test_helper.rb +1 -1
- data/test/real_db_test.rb +5 -5
- data/test/support/fake_record.rb +1 -1
- data/test/visitors/test_bulk_insert_oracle.rb +3 -3
- data/test/visitors/test_bulk_insert_sqlite.rb +1 -1
- data/test/visitors/test_bulk_insert_to_sql.rb +1 -1
- data/test/visitors/test_to_sql.rb +6 -6
- data/test/with_ar/all_agnostic_test.rb +67 -60
- data/test/with_ar/insert_agnostic_test.rb +3 -3
- data/test/with_ar/test_bulk_sqlite.rb +1 -1
- data/version_v1.rb +1 -1
- data/version_v2.rb +1 -1
- metadata +3 -2
data/lib/arel_extensions/math.rb
CHANGED
@@ -16,16 +16,16 @@ module ArelExtensions
|
|
16
16
|
# Date and integer adds or subtracts a specified time interval from a date.
|
17
17
|
def +(other)
|
18
18
|
case self
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
when Arel::Nodes::Quoted
|
20
|
+
self.concat(other)
|
21
|
+
when Arel::Nodes::Grouping
|
22
|
+
if self.expr.left.is_a?(String) || self.expr.right.is_a?(String)
|
23
|
+
self.concat(other)
|
24
|
+
else
|
25
|
+
Arel.grouping(Arel::Nodes::Addition.new self, other)
|
26
|
+
end
|
27
|
+
when ArelExtensions::Nodes::Function, ArelExtensions::Nodes::Case
|
28
|
+
case self.return_type
|
29
29
|
when :string, :text
|
30
30
|
self.concat(other)
|
31
31
|
when :integer, :decimal, :float, :number, :int
|
@@ -38,12 +38,17 @@ module ArelExtensions
|
|
38
38
|
when Arel::Nodes::Function
|
39
39
|
Arel.grouping(Arel::Nodes::Addition.new self, other)
|
40
40
|
else
|
41
|
-
col =
|
42
|
-
|
41
|
+
col =
|
42
|
+
if self.is_a?(Arel::Attribute) && self.respond_to?(:type_caster) && self.able_to_type_cast?
|
43
|
+
self.type_caster
|
44
|
+
else
|
45
|
+
Arel.column_of(self.relation.table_name, self.name.to_s) if self.respond_to?(:relation)
|
46
|
+
end
|
47
|
+
if !col # if the column doesn't exist in the database
|
43
48
|
Arel.grouping(Arel::Nodes::Addition.new(self, Arel.quoted(other)))
|
44
49
|
else
|
45
50
|
arg = col.type
|
46
|
-
if arg == :integer ||
|
51
|
+
if arg == :integer || !arg
|
47
52
|
other = other.to_i if other.is_a?(String)
|
48
53
|
Arel.grouping(Arel::Nodes::Addition.new self, Arel.quoted(other))
|
49
54
|
elsif arg == :decimal || arg == :float
|
@@ -82,16 +87,26 @@ module ArelExtensions
|
|
82
87
|
when Arel::Nodes::Function
|
83
88
|
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
84
89
|
else
|
85
|
-
col =
|
86
|
-
|
90
|
+
col =
|
91
|
+
if self.is_a?(Arel::Attribute) && self.respond_to?(:type_caster) && self.able_to_type_cast?
|
92
|
+
self.type_caster
|
93
|
+
else
|
94
|
+
Arel.column_of(self.relation.table_name, self.name.to_s) if self.respond_to?(:relation)
|
95
|
+
end
|
96
|
+
if !col # if the column doesn't exist in the database
|
87
97
|
Arel.grouping(Arel::Nodes::Subtraction.new(self, Arel.quoted(other)))
|
88
98
|
else
|
89
99
|
arg = col.type
|
90
100
|
if (arg == :date || arg == :datetime)
|
91
101
|
case other
|
92
102
|
when Arel::Attributes::Attribute
|
93
|
-
col2 =
|
94
|
-
|
103
|
+
col2 =
|
104
|
+
if other.is_a?(Arel::Attribute) && other.respond_to?(:type_caster) && other.able_to_type_cast?
|
105
|
+
other.type_caster
|
106
|
+
else
|
107
|
+
Arel.column_of(other.relation.table_name, other.name.to_s) if other.respond_to?(:relation)
|
108
|
+
end
|
109
|
+
if !col2 # if the column doesn't exist in the database
|
95
110
|
ArelExtensions::Nodes::DateSub.new [self, other]
|
96
111
|
else
|
97
112
|
arg2 = col2.type
|
@@ -32,13 +32,13 @@ module ArelExtensions
|
|
32
32
|
@as_attr = :string
|
33
33
|
end
|
34
34
|
tab = [convert_to_node(expr.first)]
|
35
|
-
|
35
|
+
super(tab)
|
36
36
|
end
|
37
37
|
|
38
38
|
def +(other)
|
39
39
|
case @return_type
|
40
40
|
when :string
|
41
|
-
|
41
|
+
ArelExtensions::Nodes::Concat.new [self, other]
|
42
42
|
when :ruby_time
|
43
43
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
44
44
|
else
|
@@ -19,7 +19,7 @@ module ArelExtensions
|
|
19
19
|
when DateTime, Time
|
20
20
|
@left_node_type = :ruby_time
|
21
21
|
end
|
22
|
-
res << ([
|
22
|
+
res << (%i[date ruby_date].include?(@left_node_type) ? convert_to_date_node(col) : convert_to_datetime_node(col))
|
23
23
|
case expr[1]
|
24
24
|
when Arel::Nodes::Node, Arel::Attributes::Attribute
|
25
25
|
@right_node_type = type_of_attribute(expr[1])
|
@@ -28,7 +28,7 @@ module ArelExtensions
|
|
28
28
|
when DateTime, Time
|
29
29
|
@right_node_type = :ruby_time
|
30
30
|
end
|
31
|
-
res << ([
|
31
|
+
res << (%i[date ruby_date].include?(@left_node_type) ? convert_to_date_node(expr[1]) : convert_to_datetime_node(expr[1]))
|
32
32
|
super res
|
33
33
|
end
|
34
34
|
end
|
@@ -43,19 +43,19 @@ module ArelExtensions
|
|
43
43
|
tab = expr.map do |arg|
|
44
44
|
convert(arg)
|
45
45
|
end
|
46
|
-
|
46
|
+
super(tab)
|
47
47
|
end
|
48
48
|
|
49
49
|
def sqlite_value
|
50
50
|
v = self.expressions.last
|
51
51
|
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === v
|
52
52
|
if @date_type == :date
|
53
|
-
|
53
|
+
Arel.quoted((v.value >= 0 ? '+' : '-') + v.inspect)
|
54
54
|
elsif @date_type == :datetime
|
55
|
-
|
55
|
+
Arel.quoted((v.value >= 0 ? '+' : '-') + v.inspect)
|
56
56
|
end
|
57
57
|
else
|
58
|
-
|
58
|
+
v
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -7,11 +7,11 @@ module ArelExtensions
|
|
7
7
|
tab = expr.map { |arg|
|
8
8
|
convert_to_node(arg)
|
9
9
|
}
|
10
|
-
|
10
|
+
super(tab)
|
11
11
|
end
|
12
12
|
|
13
13
|
def +(other)
|
14
|
-
|
14
|
+
ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -7,11 +7,11 @@ module ArelExtensions
|
|
7
7
|
tab = expr.map { |arg|
|
8
8
|
convert_to_node(arg)
|
9
9
|
}
|
10
|
-
|
10
|
+
super(tab)
|
11
11
|
end
|
12
12
|
|
13
13
|
def +(other)
|
14
|
-
|
14
|
+
ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -2,15 +2,15 @@ module ArelExtensions
|
|
2
2
|
module Nodes
|
3
3
|
class Union < Arel::Nodes::Union
|
4
4
|
def initialize left, right
|
5
|
-
|
5
|
+
super(left, right)
|
6
6
|
end
|
7
7
|
|
8
8
|
def +(other)
|
9
|
-
|
9
|
+
ArelExtensions::Nodes::Union.new(self, other)
|
10
10
|
end
|
11
11
|
|
12
12
|
def union(other)
|
13
|
-
|
13
|
+
ArelExtensions::Nodes::UnionAll.new(self, other)
|
14
14
|
end
|
15
15
|
|
16
16
|
def as other
|
@@ -2,11 +2,11 @@ module ArelExtensions
|
|
2
2
|
module Nodes
|
3
3
|
class UnionAll < Arel::Nodes::UnionAll
|
4
4
|
def initialize left, right
|
5
|
-
|
5
|
+
super(left, right)
|
6
6
|
end
|
7
7
|
|
8
8
|
def union_all(other)
|
9
|
-
|
9
|
+
ArelExtensions::Nodes::UnionAll.new(self, other)
|
10
10
|
end
|
11
11
|
|
12
12
|
def as other
|
@@ -56,7 +56,7 @@ module ArelExtensions
|
|
56
56
|
collector << 'COALESCE('
|
57
57
|
collector = visit o.left, collector
|
58
58
|
collector << ','
|
59
|
-
if
|
59
|
+
if o.right.is_a?(Arel::Attributes::Attribute)
|
60
60
|
collector = visit o.right, collector
|
61
61
|
else
|
62
62
|
collector << "'#{o.right}'"
|
@@ -157,7 +157,7 @@ module ArelExtensions
|
|
157
157
|
collector = visit o.right, collector
|
158
158
|
else
|
159
159
|
left = o.left.end_with?('i') ? o.left[0..-2] : o.left
|
160
|
-
conv = [
|
160
|
+
conv = %w[h mn s].include?(o.left)
|
161
161
|
collector << 'DATEPART('
|
162
162
|
collector << LOADED_VISITOR::DATE_MAPPING[left]
|
163
163
|
collector << LOADED_VISITOR::COMMA
|
@@ -220,11 +220,19 @@ module ArelExtensions
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def visit_ArelExtensions_Nodes_Trim o, collector
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
223
|
+
# NOTE: in MSSQL's `blank`, o.right is the space char so we need to
|
224
|
+
# account for it.
|
225
|
+
if o.right && !/\A\s\Z/.match(o.right.expr)
|
226
|
+
collector << 'dbo.TrimChar('
|
227
|
+
collector = visit o.left, collector
|
228
|
+
collector << Arel::Visitors::MSSQL::COMMA
|
229
|
+
collector = visit o.right, collector
|
230
|
+
collector << ')'
|
231
|
+
else
|
232
|
+
collector << "LTRIM(RTRIM("
|
233
|
+
collector = visit o.left, collector
|
234
|
+
collector << "))"
|
235
|
+
end
|
228
236
|
collector
|
229
237
|
end
|
230
238
|
|
@@ -308,7 +316,7 @@ module ArelExtensions
|
|
308
316
|
dir = LOADED_VISITOR::DATE_FORMAT_DIRECTIVES[s.matched]
|
309
317
|
fmt = LOADED_VISITOR::DATE_FORMAT_FORMAT[dir]
|
310
318
|
date_name = LOADED_VISITOR::DATE_NAME.include?(s.matched)
|
311
|
-
collector << '
|
319
|
+
collector << 'LTRIM(RTRIM('
|
312
320
|
collector << 'FORMAT(' if fmt
|
313
321
|
collector << 'STR(' if !fmt && !date_name
|
314
322
|
collector << (date_name ? 'DATENAME(' : 'DATEPART(')
|
@@ -334,7 +342,7 @@ module ArelExtensions
|
|
334
342
|
collector << ')'
|
335
343
|
collector << ')' if !fmt && !date_name
|
336
344
|
collector << LOADED_VISITOR::COMMA << "'#{fmt}')" if fmt
|
337
|
-
collector << ')'
|
345
|
+
collector << '))'
|
338
346
|
when s.scan(/^%%/)
|
339
347
|
collector = visit Arel.quoted('%'), collector
|
340
348
|
when s.scan(/[^%]+|./)
|
@@ -575,15 +583,20 @@ module ArelExtensions
|
|
575
583
|
])
|
576
584
|
end
|
577
585
|
|
578
|
-
repeated_char =
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
586
|
+
repeated_char =
|
587
|
+
if o.width == 0
|
588
|
+
Arel.quoted('')
|
589
|
+
else
|
590
|
+
Arel
|
591
|
+
.when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
|
592
|
+
.then(Arel.quoted(
|
593
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
594
|
+
).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
|
595
|
+
)
|
596
|
+
.else('')
|
597
|
+
end
|
598
|
+
before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
599
|
+
middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
587
600
|
after = o.flags.include?('-') ? repeated_char : ''
|
588
601
|
full_number =
|
589
602
|
ArelExtensions::Nodes::Concat.new([
|
@@ -126,7 +126,7 @@ module ArelExtensions
|
|
126
126
|
collector << 'CONCAT('
|
127
127
|
o.expressions.each_with_index { |arg, i|
|
128
128
|
collector << COMMA if i != 0
|
129
|
-
if
|
129
|
+
if arg.is_a?(Numeric) || arg.is_a?(Arel::Attributes::Attribute)
|
130
130
|
collector << 'CAST('
|
131
131
|
collector = visit arg, collector
|
132
132
|
collector << ' AS char)'
|
@@ -398,15 +398,20 @@ module ArelExtensions
|
|
398
398
|
Arel::Nodes::NamedFunction.new('FORMAT', [col.abs] + params)
|
399
399
|
end
|
400
400
|
|
401
|
-
repeated_char =
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
401
|
+
repeated_char =
|
402
|
+
if o.width == 0
|
403
|
+
Arel.quoted('')
|
404
|
+
else
|
405
|
+
Arel
|
406
|
+
.when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
|
407
|
+
.then(Arel.quoted(
|
408
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
409
|
+
).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
|
410
|
+
)
|
411
|
+
.else('')
|
412
|
+
end
|
413
|
+
before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
414
|
+
middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
410
415
|
after = o.flags.include?('-') ? repeated_char : ''
|
411
416
|
full_number = ArelExtensions::Nodes::Concat.new([
|
412
417
|
before,
|
@@ -11,7 +11,7 @@ module ArelExtensions
|
|
11
11
|
'%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
|
12
12
|
'%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
|
13
13
|
}
|
14
|
-
NUMBER_COMMA_MAPPING = {
|
14
|
+
NUMBER_COMMA_MAPPING = {'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '}
|
15
15
|
|
16
16
|
def visit_ArelExtensions_Nodes_Log10 o, collector
|
17
17
|
collector << 'LOG('
|
@@ -455,7 +455,7 @@ module ArelExtensions
|
|
455
455
|
src_tz, dst_tz = o.time_zone.first
|
456
456
|
collector << ' as timestamp) at time zone '
|
457
457
|
collector = visit Arel.quoted(src_tz), collector
|
458
|
-
|
458
|
+
collector < ' at time zone '
|
459
459
|
collector = visit Arel.quoted(dst_tz), collector
|
460
460
|
when String
|
461
461
|
collector << ' as timestamp) at time zone '
|
@@ -587,7 +587,7 @@ module ArelExtensions
|
|
587
587
|
alias_method(:old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias) rescue nil
|
588
588
|
def visit_Arel_Nodes_TableAlias o, collector
|
589
589
|
if o.name.length > 30
|
590
|
-
o = Arel::Table.new(o.table_name).alias(
|
590
|
+
o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
|
591
591
|
end
|
592
592
|
old_visit_Arel_Nodes_TableAlias(o, collector)
|
593
593
|
end
|
@@ -601,7 +601,7 @@ module ArelExtensions
|
|
601
601
|
else
|
602
602
|
collector = visit o.left, collector
|
603
603
|
end
|
604
|
-
quote =
|
604
|
+
quote = /(\A".*"\z)|\A[a-zA-Z_]*\z/.match?(o.right.to_s) ? '' : '"'
|
605
605
|
collector << " AS #{quote}"
|
606
606
|
collector = visit o.right, collector
|
607
607
|
collector << "#{quote}"
|
@@ -627,10 +627,10 @@ module ArelExtensions
|
|
627
627
|
comma_in_format = o.precision == 0 ? '' : 'D'
|
628
628
|
nines_after = (1..o.precision - 1).map{'9'}.join('') + '0'
|
629
629
|
if comma.length == 1
|
630
|
-
options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '
|
630
|
+
options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '#{comma} '")
|
631
631
|
nines_before = ('999' * 4 + '990')
|
632
632
|
else
|
633
|
-
options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '
|
633
|
+
options = Arel.quoted("NLS_NUMERIC_CHARACTERS = '#{comma}'")
|
634
634
|
nines_before = ('999G' * 4 + '990')
|
635
635
|
end
|
636
636
|
sign = Arel.when(col < 0).
|
@@ -643,7 +643,7 @@ module ArelExtensions
|
|
643
643
|
if o.scientific_notation
|
644
644
|
number = Arel::Nodes::NamedFunction.new('TO_CHAR', [
|
645
645
|
Arel.quoted(col.abs),
|
646
|
-
Arel.quoted(
|
646
|
+
Arel.quoted("FM#{nines_before}#{comma_in_format}#{nines_after}EEEE"),
|
647
647
|
options
|
648
648
|
])
|
649
649
|
if o.type == 'e'
|
@@ -652,20 +652,25 @@ module ArelExtensions
|
|
652
652
|
else
|
653
653
|
number = Arel::Nodes::NamedFunction.new('TO_CHAR', [
|
654
654
|
Arel.quoted(col.abs),
|
655
|
-
Arel.quoted(
|
655
|
+
Arel.quoted("FM#{nines_before}#{comma_in_format}#{nines_after}"),
|
656
656
|
options
|
657
657
|
])
|
658
658
|
end
|
659
659
|
|
660
|
-
repeated_char =
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
660
|
+
repeated_char =
|
661
|
+
if o.width == 0
|
662
|
+
Arel.quoted('')
|
663
|
+
else
|
664
|
+
Arel
|
665
|
+
.when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
|
666
|
+
.then(Arel.quoted(
|
667
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
668
|
+
).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
|
669
|
+
)
|
670
|
+
.else('')
|
671
|
+
end
|
672
|
+
before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
673
|
+
middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
669
674
|
after = o.flags.include?('-') ? repeated_char : ''
|
670
675
|
full_number = ArelExtensions::Nodes::Concat.new([
|
671
676
|
before,
|
@@ -425,32 +425,37 @@ module ArelExtensions
|
|
425
425
|
Arel::Nodes::NamedFunction.new('TRIM', [
|
426
426
|
Arel::Nodes::NamedFunction.new('TO_CHAR', [
|
427
427
|
Arel.when(col.not_eq 0).then(col.abs / Arel.quoted(10).pow(col.abs.log10.floor)).else(1),
|
428
|
-
Arel.quoted(
|
428
|
+
Arel.quoted("FM#{nines_before}\"#{comma}\"V#{nines_after}")
|
429
429
|
])]),
|
430
430
|
o.type,
|
431
431
|
Arel::Nodes::NamedFunction.new('TRIM', [
|
432
432
|
Arel::Nodes::NamedFunction.new('TO_CHAR', [
|
433
433
|
Arel.when(col.not_eq 0).then(col.abs.log10.floor).else(0),
|
434
|
-
Arel.quoted(
|
434
|
+
Arel.quoted("FM#{nines_before}")
|
435
435
|
])])
|
436
436
|
])
|
437
437
|
else
|
438
438
|
Arel::Nodes::NamedFunction.new('TRIM', [
|
439
439
|
Arel::Nodes::NamedFunction.new('TO_CHAR', [
|
440
440
|
Arel.quoted(col.abs),
|
441
|
-
Arel.quoted(
|
441
|
+
Arel.quoted("FM#{nines_before}\"#{comma}\"V#{nines_after}")
|
442
442
|
])])
|
443
443
|
end
|
444
444
|
|
445
|
-
repeated_char =
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
445
|
+
repeated_char =
|
446
|
+
if o.width == 0
|
447
|
+
Arel.quoted('')
|
448
|
+
else
|
449
|
+
Arel
|
450
|
+
.when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
|
451
|
+
.then(Arel.quoted(
|
452
|
+
o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
|
453
|
+
).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
|
454
|
+
)
|
455
|
+
.else('')
|
456
|
+
end
|
457
|
+
before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
458
|
+
middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
|
454
459
|
after = o.flags.include?('-') ? repeated_char : ''
|
455
460
|
full_number = ArelExtensions::Nodes::Concat.new([
|
456
461
|
before,
|
@@ -325,16 +325,16 @@ module ArelExtensions
|
|
325
325
|
|
326
326
|
def get_time_converted element
|
327
327
|
if element.is_a?(Time)
|
328
|
-
|
328
|
+
Arel::Nodes::NamedFunction.new('STRFTIME', [element, '%H:%M:%S'])
|
329
329
|
elsif element.is_a?(Arel::Attributes::Attribute)
|
330
330
|
col = Arel.column_of(element.relation.table_name, element.name.to_s)
|
331
331
|
if col && (col.type == :time)
|
332
|
-
|
332
|
+
Arel::Nodes::NamedFunction.new('STRFTIME', [element, '%H:%M:%S'])
|
333
333
|
else
|
334
|
-
|
334
|
+
element
|
335
335
|
end
|
336
336
|
else
|
337
|
-
|
337
|
+
element
|
338
338
|
end
|
339
339
|
end
|
340
340
|
|
@@ -649,7 +649,10 @@ module ArelExtensions
|
|
649
649
|
|
650
650
|
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
651
651
|
if o.as_array
|
652
|
-
res =
|
652
|
+
res =
|
653
|
+
Arel.quoted('[') \
|
654
|
+
+ (o.orders ? o.dict.group_concat(', ', order: Array(o.orders)) : o.dict.group_concat(', ')).coalesce('') \
|
655
|
+
+ ']'
|
653
656
|
collector = visit res, collector
|
654
657
|
else
|
655
658
|
res = Arel.quoted('{')
|
data/lib/arel_extensions.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'arel'
|
2
|
+
require 'base64'
|
2
3
|
|
3
4
|
require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
4
5
|
|
@@ -268,3 +269,12 @@ class Arel::Nodes::TableAlias
|
|
268
269
|
end
|
269
270
|
end
|
270
271
|
end
|
272
|
+
|
273
|
+
|
274
|
+
class Arel::Attributes::Attribute
|
275
|
+
def to_sql(engine = Arel::Table.engine)
|
276
|
+
collector = Arel::Collectors::SQLString.new
|
277
|
+
collector = engine.connection.visitor.accept self, collector
|
278
|
+
collector.value
|
279
|
+
end
|
280
|
+
end
|
data/test/arelx_test_helper.rb
CHANGED
@@ -7,7 +7,7 @@ require 'active_record'
|
|
7
7
|
require 'support/fake_record'
|
8
8
|
|
9
9
|
def colored(color, msg)
|
10
|
-
ENV['TERM']
|
10
|
+
/^xterm|-256color$/.match?(ENV['TERM']) ? "\x1b[#{color}m#{msg}\x1b[89m\x1b[0m" : "#{msg}"
|
11
11
|
end
|
12
12
|
|
13
13
|
YELLOW = '33'
|
data/test/real_db_test.rb
CHANGED
@@ -14,7 +14,7 @@ def setup_db
|
|
14
14
|
ActiveRecord::Base.default_timezone = :utc
|
15
15
|
end
|
16
16
|
@cnx = ActiveRecord::Base.connection
|
17
|
-
if ActiveRecord::Base.connection.adapter_name
|
17
|
+
if /sqlite/i.match?(ActiveRecord::Base.connection.adapter_name)
|
18
18
|
$sqlite = true
|
19
19
|
db = @cnx.raw_connection
|
20
20
|
if !$load_extension_disabled
|
@@ -82,7 +82,7 @@ class ListTest < Minitest::Test
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def test_coalesce
|
85
|
-
if @cnx.adapter_name
|
85
|
+
if /pgsql/i.match?(@cnx.adapter_name)
|
86
86
|
assert_equal 100, User.where(User.arel_table[:name].eq('Test')).select((User.arel_table[:age].coalesce(100)).as('res')).first.res
|
87
87
|
assert_equal 'Camille', User.where(User.arel_table[:name].eq('Camille')).select((User.arel_table[:name].coalesce('Null', 'default')).as('res')).first.res
|
88
88
|
else
|
@@ -128,7 +128,7 @@ class ListTest < Minitest::Test
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def test_isnull
|
131
|
-
if ActiveRecord::Base.connection.adapter_name
|
131
|
+
if /pgsql/i.match?(ActiveRecord::Base.connection.adapter_name)
|
132
132
|
assert_equal 100, User.where(User.arel_table[:name].eq('Test')).select((User.arel_table[:age].isnull(100)).as('res')).first.res
|
133
133
|
else
|
134
134
|
assert_equal 'default', User.where(User.arel_table[:name].eq('Test')).select((User.arel_table[:age].isnull('default')).as('res')).first.res
|
@@ -196,8 +196,8 @@ class ListTest < Minitest::Test
|
|
196
196
|
end
|
197
197
|
|
198
198
|
def test_replace
|
199
|
-
assert_equal 'LucaX', User.where(User.arel_table[:name].eq('Lucas')).select((
|
200
|
-
assert_equal 'replace', User.where(User.arel_table[:name].eq('Lucas')).select((
|
199
|
+
assert_equal 'LucaX', User.where(User.arel_table[:name].eq('Lucas')).select((User.arel_table[:name].replace('s', 'X')).as('res')).first.res
|
200
|
+
assert_equal 'replace', User.where(User.arel_table[:name].eq('Lucas')).select((User.arel_table[:name].replace(User.arel_table[:name], 'replace')).as('res')).first.res
|
201
201
|
end
|
202
202
|
|
203
203
|
def test_round
|