arel_extensions 1.0.8 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/README.md +5 -0
- data/lib/arel_extensions.rb +9 -0
- data/lib/arel_extensions/math.rb +33 -25
- data/lib/arel_extensions/math_functions.rb +2 -2
- data/lib/arel_extensions/nodes/case.rb +1 -0
- data/lib/arel_extensions/nodes/concat.rb +43 -30
- data/lib/arel_extensions/nodes/function.rb +2 -1
- data/lib/arel_extensions/string_functions.rb +6 -1
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +0 -23
- data/lib/arel_extensions/visitors/oracle.rb +39 -31
- data/lib/arel_extensions/visitors/postgresql.rb +22 -4
- data/test/visitors/test_bulk_insert_oracle.rb +5 -5
- data/test/visitors/test_to_sql.rb +32 -2
- data/test/with_ar/all_agnostic_test.rb +16 -2
- data/test/with_ar/insert_agnostic_test.rb +1 -1
- metadata +4 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b42393f60593054c04105afad4f4500dc826cd93
|
4
|
+
data.tar.gz: 383b4bc32619fe292c7f7ba31f867f1f49c8da80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a724f2bd5c6d6ecedf567d44cc5d9be29f4270043b9d816b0090e19fce6380af13af3e5d4930f5252add2b4542d58ff7f6a21c202e1a5001665c7aa10b9aee3
|
7
|
+
data.tar.gz: 29f68d3d37bee531b23098ccace43491c42d781f719c451d1a7bbbaa4c0067b54abbf356940be7f955ad72984a07132e59e1bc4b8cea0f061e0abeb7099c416b
|
data/.travis.yml
CHANGED
@@ -12,7 +12,7 @@ before_install:
|
|
12
12
|
- sudo apt-get install -y sqlite3-pcre curl
|
13
13
|
- .travis/sqlite3/extension-functions.sh
|
14
14
|
- .travis/oracle/download.sh
|
15
|
-
- .travis/oracle/install.sh
|
15
|
+
- sh -ex .travis/oracle/install.sh
|
16
16
|
- .travis/setup_accounts.sh
|
17
17
|
install:
|
18
18
|
- gem install bundler
|
data/README.md
CHANGED
@@ -72,6 +72,11 @@ With Arel Extensions:
|
|
72
72
|
```
|
73
73
|
|
74
74
|
Other functions : ABS, RAND, ROUND, FLOOR, CEIL, FORMAT
|
75
|
+
Exemples :
|
76
|
+
```ruby
|
77
|
+
t[:price].format_number("%07.2f €","fr_FR")
|
78
|
+
# equivalent to 'sprintf("%07.2f €",price)' plus locale management
|
79
|
+
```
|
75
80
|
|
76
81
|
## String operations
|
77
82
|
|
data/lib/arel_extensions.rb
CHANGED
@@ -12,6 +12,10 @@ Arel::Nodes::Binary.class_eval do
|
|
12
12
|
include Arel::Expressions
|
13
13
|
end
|
14
14
|
|
15
|
+
Arel::Nodes::Casted.class_eval do
|
16
|
+
include Arel::AliasPredication
|
17
|
+
end
|
18
|
+
|
15
19
|
Arel::Nodes::Unary.class_eval do
|
16
20
|
include Arel::Math
|
17
21
|
include Arel::AliasPredication
|
@@ -21,6 +25,7 @@ end
|
|
21
25
|
Arel::Nodes::Grouping.class_eval do
|
22
26
|
include Arel::Math
|
23
27
|
include Arel::AliasPredication
|
28
|
+
include Arel::OrderPredications
|
24
29
|
include Arel::Expressions
|
25
30
|
end
|
26
31
|
|
@@ -67,6 +72,10 @@ module Arel
|
|
67
72
|
def self.rand
|
68
73
|
ArelExtensions::Nodes::Rand.new
|
69
74
|
end
|
75
|
+
|
76
|
+
def self.shorten s
|
77
|
+
Base64.urlsafe_encode64(Digest::MD5.new.digest(s)).tr('=', '').tr('-', '_')
|
78
|
+
end
|
70
79
|
end
|
71
80
|
|
72
81
|
Arel::Attributes::Attribute.class_eval do
|
data/lib/arel_extensions/math.rb
CHANGED
@@ -15,51 +15,59 @@ module ArelExtensions
|
|
15
15
|
#String and others (convert in string) allows you to concatenate 2 or more strings together.
|
16
16
|
#Date and integer adds or subtracts a specified time interval from a date.
|
17
17
|
def +(other)
|
18
|
-
|
19
|
-
|
18
|
+
case self
|
19
|
+
when Arel::Nodes::Quoted
|
20
|
+
return self.concat(other)
|
21
|
+
when Arel::Nodes::Grouping
|
20
22
|
if self.expr.left.is_a?(String) || self.expr.right.is_a?(String)
|
21
|
-
return
|
23
|
+
return self.concat(other)
|
22
24
|
else
|
23
25
|
return Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
24
26
|
end
|
25
|
-
|
26
|
-
if self.is_a?(ArelExtensions::Nodes::Function)
|
27
|
+
when ArelExtensions::Nodes::Function
|
27
28
|
return case self.return_type
|
28
29
|
when :string, :text
|
29
|
-
|
30
|
+
self.concat(other)
|
30
31
|
when :integer, :decimal, :float, :number, :int
|
31
32
|
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
32
33
|
when :date, :datetime
|
33
34
|
ArelExtensions::Nodes::DateAdd.new [self, other]
|
34
35
|
else
|
35
|
-
|
36
|
+
self.concat(other)
|
36
37
|
end
|
37
|
-
|
38
|
-
if self.is_a?(Arel::Nodes::Function)
|
38
|
+
when Arel::Nodes::Function
|
39
39
|
return Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
40
|
-
end
|
41
|
-
col = Arel::Table.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s]
|
42
|
-
if (!col) #if the column doesn't exist in the database
|
43
|
-
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new(self, other))
|
44
40
|
else
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
41
|
+
col = Arel::Table.engine.connection.schema_cache.columns_hash(self.relation.table_name)[self.name.to_s]
|
42
|
+
if (!col) #if the column doesn't exist in the database
|
43
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new(self, other))
|
44
|
+
else
|
45
|
+
arg = col.type
|
46
|
+
if arg == :integer || (!arg)
|
47
|
+
other = other.to_i if other.is_a?(String)
|
48
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
49
|
+
elsif arg == :decimal || arg == :float
|
50
|
+
other = Arel.sql(other) if other.is_a?(String) # Arel should accept Float & BigDecimal!
|
51
|
+
Arel::Nodes::Grouping.new(Arel::Nodes::Addition.new self, other)
|
52
|
+
elsif arg == :datetime || arg == :date
|
53
|
+
ArelExtensions::Nodes::DateAdd.new [self, other]
|
54
|
+
elsif arg == :string || arg == :text
|
55
|
+
self.concat(other)
|
56
|
+
end
|
57
|
+
end
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
61
|
#function returns the time between two dates
|
61
62
|
#function returns the substraction between two ints
|
62
63
|
def -(other)
|
64
|
+
if self.is_a?(Arel::Nodes::Grouping)
|
65
|
+
if self.expr.left.is_a?(Date) || self.expr.left.is_a?(DateTime)
|
66
|
+
return Arel::Nodes::Grouping.new(ArelExtensions::Nodes::DateSub.new [self, other])
|
67
|
+
else
|
68
|
+
return Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other))
|
69
|
+
end
|
70
|
+
end
|
63
71
|
return case self.return_type
|
64
72
|
when :string, :text # ???
|
65
73
|
Arel::Nodes::Grouping.new(Arel::Nodes::Subtraction.new(self, other)) # ??
|
@@ -59,7 +59,7 @@ module ArelExtensions
|
|
59
59
|
# function returning a number at a specific format
|
60
60
|
def format_number format_string, locale=nil
|
61
61
|
begin
|
62
|
-
sprintf(format_string,0) # this line is to get the right error message if the format_string is not correct
|
62
|
+
sprintf(format_string,0) # this line is to get the right error message if the format_string is not correct
|
63
63
|
m = /^(.*)%([ #+\-0]*)([1-9][0-9]+|[1-9]?)[.]?([0-9]*)([a-zA-Z])(.*)$/.match(format_string)
|
64
64
|
opts = {
|
65
65
|
:prefix => m[1],
|
@@ -73,7 +73,7 @@ module ArelExtensions
|
|
73
73
|
}
|
74
74
|
# opts = {:locale => 'fr_FR', :type => "e"/"f"/"d", :prefix => "$ ", :suffix => " %", :flags => " +-#0", :width => 5, :precision => 6}
|
75
75
|
ArelExtensions::Nodes::FormattedNumber.new [self,opts]
|
76
|
-
rescue
|
76
|
+
rescue Exception => e
|
77
77
|
Arel::Nodes.build_quoted('Wrong Format')
|
78
78
|
end
|
79
79
|
end
|
@@ -1,40 +1,53 @@
|
|
1
|
-
module ArelExtensions
|
2
|
-
|
3
|
-
|
4
|
-
RETURN_TYPE = :string
|
5
|
-
|
6
|
-
def initialize expr
|
7
|
-
tab = expr.map { |arg|
|
8
|
-
convert_to_node(arg)
|
9
|
-
}
|
10
|
-
return super(tab)
|
11
|
-
end
|
12
|
-
|
13
|
-
#def +(other)
|
14
|
-
# return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
15
|
-
#end
|
16
|
-
|
17
|
-
def concat(other)
|
18
|
-
return ArelExtensions::Nodes::Concat.new(self.expressions + [other])
|
19
|
-
end
|
1
|
+
module ArelExtensions::Nodes
|
2
|
+
class Concat < Function
|
3
|
+
RETURN_TYPE = :string
|
20
4
|
|
5
|
+
def initialize expr
|
6
|
+
tab = expr.map { |arg|
|
7
|
+
# flatten nested concats.
|
8
|
+
node = convert_to_node(arg)
|
9
|
+
if node.is_a?(Concat)
|
10
|
+
node.expressions
|
11
|
+
else
|
12
|
+
node
|
13
|
+
end
|
14
|
+
}.flatten.reduce([]) { | res, b |
|
15
|
+
# concatenate successive literal strings.
|
16
|
+
if b.is_a?(Arel::Nodes::Quoted) && b.expr == ""
|
17
|
+
res
|
18
|
+
elsif res.last && res.last.is_a?(Arel::Nodes::Quoted) && b.is_a?(Arel::Nodes::Quoted)
|
19
|
+
res[-1] = Arel::Nodes.build_quoted(res.last.expr + b.expr)
|
20
|
+
else
|
21
|
+
res << b
|
22
|
+
end
|
23
|
+
res
|
24
|
+
}
|
25
|
+
super(tab)
|
21
26
|
end
|
22
27
|
|
23
|
-
|
24
|
-
|
28
|
+
#def +(other)
|
29
|
+
# Concat.new(self.expressions + [other])
|
30
|
+
#end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
+
def concat(other)
|
33
|
+
Concat.new(self.expressions + [other])
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
#end
|
38
|
+
class GroupConcat < Function
|
39
|
+
RETURN_TYPE = :string
|
36
40
|
|
41
|
+
def initialize expr
|
42
|
+
tab = expr.map { |arg|
|
43
|
+
convert_to_node(arg)
|
44
|
+
}
|
45
|
+
super(tab)
|
37
46
|
end
|
38
47
|
|
48
|
+
#def +(other)
|
49
|
+
# return Concat.new([self, other])
|
50
|
+
#end
|
51
|
+
|
39
52
|
end
|
40
53
|
end
|
@@ -4,7 +4,8 @@ module ArelExtensions
|
|
4
4
|
module Nodes
|
5
5
|
class Function < Arel::Nodes::Function
|
6
6
|
include Arel::Math
|
7
|
-
include Arel::Expressions
|
7
|
+
include Arel::Expressions
|
8
|
+
include Arel::OrderPredications
|
8
9
|
include ArelExtensions::Predications
|
9
10
|
|
10
11
|
RETURN_TYPE = :string # by default...
|
@@ -108,7 +108,12 @@ module ArelExtensions
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def concat other
|
111
|
-
ArelExtensions::Nodes::Concat.new [self, other]
|
111
|
+
res = ArelExtensions::Nodes::Concat.new [self, other]
|
112
|
+
if res.expressions.length == 1
|
113
|
+
res.expressions.first
|
114
|
+
else
|
115
|
+
res
|
116
|
+
end
|
112
117
|
end
|
113
118
|
|
114
119
|
def group_concat sep = nil
|
@@ -65,29 +65,6 @@ module ArelExtensions
|
|
65
65
|
collector
|
66
66
|
end
|
67
67
|
|
68
|
-
# Deprecated
|
69
|
-
def visit_ArelExtensions_Nodes_ConcatOld o, collector
|
70
|
-
arg = o.left.relation.engine.columns.find{|c| c.name == o.left.name.to_s}.type
|
71
|
-
if(o.right.is_a?(Arel::Attributes::Attribute))
|
72
|
-
collector = visit o.left, collector
|
73
|
-
collector << ' + '
|
74
|
-
collector = visit o.right, collector
|
75
|
-
collector
|
76
|
-
elsif ( arg == :date || arg == :datetime)
|
77
|
-
collector << "DATEADD(day"
|
78
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
79
|
-
collector = visit o.right, collector
|
80
|
-
collector << Arel::Visitors::MSSQL::COMMA
|
81
|
-
collector = visit o.left, collector
|
82
|
-
collector
|
83
|
-
else
|
84
|
-
collector = visit o.left, collector
|
85
|
-
collector << " + '"
|
86
|
-
collector = visit o.right, collector
|
87
|
-
collector
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
68
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
92
69
|
collector << "CONCAT("
|
93
70
|
o.expressions.each_with_index { |arg, i|
|
@@ -394,21 +394,10 @@ module ArelExtensions
|
|
394
394
|
# add primary_key if not present, avoid zip
|
395
395
|
if Arel::VERSION.to_i < 7
|
396
396
|
def visit_ArelExtensions_InsertManager_BulkValues o, collector
|
397
|
-
|
398
|
-
table = collector.value.sub(/\AINSERT INTO/, '')
|
399
|
-
into = " INTO#{table}"
|
400
|
-
collector = Arel::Collectors::SQLString.new
|
401
|
-
collector << "INSERT ALL\n"
|
402
|
-
pk_name = @connection.primary_key(o.cols.first.relation.name)
|
403
|
-
if pk_name
|
404
|
-
pk_missing = !o.cols.detect{|c| c.name == pk_name }
|
405
|
-
into.sub!(/\(/, %Q[("#{pk_name.upcase}", ]) if pk_missing
|
406
|
-
else
|
407
|
-
pk_missing = false
|
408
|
-
end
|
397
|
+
collector << "("
|
409
398
|
o.left.each_with_index do |row, idx| # values
|
410
|
-
|
411
|
-
collector << "
|
399
|
+
collector << " UNION ALL " if idx != 0
|
400
|
+
collector << "(SELECT "
|
412
401
|
v = Arel::Nodes::Values.new(row, o.cols)
|
413
402
|
len = v.expressions.length - 1
|
414
403
|
v.expressions.each_with_index { |value, i|
|
@@ -421,19 +410,17 @@ module ArelExtensions
|
|
421
410
|
end
|
422
411
|
collector << Arel::Visitors::Oracle::COMMA unless i == len
|
423
412
|
}
|
424
|
-
collector << ')'
|
413
|
+
collector << ' FROM DUAL)'
|
425
414
|
end
|
426
|
-
collector <<
|
415
|
+
collector << ")"
|
427
416
|
collector
|
428
417
|
end
|
429
418
|
else
|
430
419
|
def visit_ArelExtensions_InsertManager_BulkValues o, collector
|
431
|
-
|
432
|
-
into = " INTO#{table}"
|
433
|
-
collector = Arel::Collectors::SQLString.new
|
434
|
-
collector << "INSERT ALL\n"
|
420
|
+
collector << "("
|
435
421
|
o.left.each_with_index do |row, idx|
|
436
|
-
|
422
|
+
collector << " UNION ALL " if idx != 0
|
423
|
+
collector << "(SELECT "
|
437
424
|
v = Arel::Nodes::Values.new(row, o.cols)
|
438
425
|
len = v.expressions.length - 1
|
439
426
|
v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
|
@@ -445,9 +432,9 @@ module ArelExtensions
|
|
445
432
|
end
|
446
433
|
collector << Arel::Visitors::Oracle::COMMA unless i == len
|
447
434
|
}
|
448
|
-
collector << ')'
|
435
|
+
collector << ' FROM DUAL)'
|
449
436
|
end
|
450
|
-
collector <<
|
437
|
+
collector << ")"
|
451
438
|
collector
|
452
439
|
end
|
453
440
|
end
|
@@ -455,18 +442,17 @@ module ArelExtensions
|
|
455
442
|
|
456
443
|
def get_time_converted element
|
457
444
|
if element.is_a?(Time)
|
458
|
-
|
445
|
+
ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
|
459
446
|
elsif element.is_a?(Arel::Attributes::Attribute)
|
460
447
|
col = Arel::Table.engine.connection.schema_cache.columns_hash(element.relation.table_name)[element.name.to_s]
|
461
448
|
if col && (col.type == :time)
|
462
|
-
|
449
|
+
ArelExtensions::Nodes::Format.new [element, '%H:%M:%S']
|
463
450
|
else
|
464
|
-
|
451
|
+
element
|
465
452
|
end
|
466
453
|
else
|
467
|
-
|
454
|
+
element
|
468
455
|
end
|
469
|
-
return res
|
470
456
|
end
|
471
457
|
|
472
458
|
|
@@ -511,10 +497,30 @@ module ArelExtensions
|
|
511
497
|
end
|
512
498
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
513
499
|
end
|
500
|
+
|
501
|
+
alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
|
502
|
+
def visit_Arel_Nodes_TableAlias o, collector
|
503
|
+
if o.name.length > 30
|
504
|
+
o = Arel::Table.new(o.table_name).alias(Base64.urlsafe_encode64(Digest::MD5.new.digest(o.name)).tr('=', '').tr('-', '_'))
|
505
|
+
end
|
506
|
+
old_visit_Arel_Nodes_TableAlias(o,collector)
|
507
|
+
end
|
508
|
+
|
509
|
+
|
510
|
+
alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
|
511
|
+
def visit_Arel_Attributes_Attribute o, collector
|
512
|
+
join_name = o.relation.table_alias || o.relation.name
|
513
|
+
if join_name.length > 30
|
514
|
+
join_name = Arel.shorten(join_name)
|
515
|
+
end
|
516
|
+
collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
|
517
|
+
end
|
518
|
+
|
514
519
|
|
515
520
|
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
516
521
|
col = o.left
|
517
|
-
comma = Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
522
|
+
comma = Arel::Visitors::Oracle::NUMBER_COMMA_MAPPING[o.locale] || '.,'
|
523
|
+
comma_in_format = o.precision == 0 ? '' : 'D'
|
518
524
|
options = Arel::Nodes.build_quoted("NLS_NUMERIC_CHARACTERS = '"+comma+"'")
|
519
525
|
nines_after = (1..o.precision).map{'9'}.join('')
|
520
526
|
nines_before = (1..16).map{'9'}.join('')
|
@@ -528,7 +534,7 @@ module ArelExtensions
|
|
528
534
|
if o.scientific_notation
|
529
535
|
number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
530
536
|
Arel::Nodes.build_quoted(col.abs),
|
531
|
-
Arel::Nodes.build_quoted('FM'+nines_before+
|
537
|
+
Arel::Nodes.build_quoted('FM'+nines_before+comma_in_format+nines_after+'EEEE'),
|
532
538
|
options
|
533
539
|
])
|
534
540
|
if o.type == 'e'
|
@@ -537,7 +543,7 @@ module ArelExtensions
|
|
537
543
|
else
|
538
544
|
number = Arel::Nodes::NamedFunction.new('TO_CHAR',[
|
539
545
|
Arel::Nodes.build_quoted(col.abs),
|
540
|
-
Arel::Nodes.build_quoted('FM'+nines_before+
|
546
|
+
Arel::Nodes.build_quoted('FM'+nines_before+comma_in_format+nines_after),
|
541
547
|
options
|
542
548
|
])
|
543
549
|
end
|
@@ -566,6 +572,8 @@ module ArelExtensions
|
|
566
572
|
end
|
567
573
|
|
568
574
|
|
575
|
+
|
576
|
+
|
569
577
|
end
|
570
578
|
end
|
571
579
|
end
|
@@ -279,9 +279,9 @@ module ArelExtensions
|
|
279
279
|
collector
|
280
280
|
end
|
281
281
|
|
282
|
-
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
282
|
+
def visit_ArelExtensions_Nodes_FormattedNumber o, collector
|
283
283
|
col = o.left
|
284
|
-
comma = Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] || '.'
|
284
|
+
comma = o.precision == 0 ? '' : (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] || '.')
|
285
285
|
nines_after = (1..o.precision).map{'9'}.join('')
|
286
286
|
nines_before = (1..16).map{'9'}.join('')
|
287
287
|
sign = ArelExtensions::Nodes::Case.new.when(col<0).
|
@@ -327,8 +327,8 @@ module ArelExtensions
|
|
327
327
|
after
|
328
328
|
])
|
329
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
|
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
332
|
end
|
333
333
|
|
334
334
|
|
@@ -341,6 +341,24 @@ module ArelExtensions
|
|
341
341
|
old_visit_Arel_Nodes_SelectStatement(o,collector)
|
342
342
|
end
|
343
343
|
|
344
|
+
alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
|
345
|
+
def visit_Arel_Nodes_TableAlias o, collector
|
346
|
+
if o.name.length > 63
|
347
|
+
o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
|
348
|
+
end
|
349
|
+
old_visit_Arel_Nodes_TableAlias(o,collector)
|
350
|
+
end
|
351
|
+
|
352
|
+
alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
|
353
|
+
def visit_Arel_Attributes_Attribute o, collector
|
354
|
+
join_name = o.relation.table_alias || o.relation.name
|
355
|
+
if join_name.length > 63
|
356
|
+
join_name = Arel.shorten(join_name)
|
357
|
+
end
|
358
|
+
collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
|
359
|
+
end
|
360
|
+
|
361
|
+
|
344
362
|
end
|
345
363
|
end
|
346
364
|
end
|
@@ -7,10 +7,10 @@ module ArelExtensions
|
|
7
7
|
@conn = FakeRecord::Base.new
|
8
8
|
@visitor = Arel::Visitors::Oracle.new @conn.connection
|
9
9
|
@table = Arel::Table.new(:users)
|
10
|
-
@cols = ['
|
10
|
+
@cols = ['name', 'comments', 'created_at']
|
11
11
|
@data = [
|
12
|
-
[
|
13
|
-
[
|
12
|
+
['nom1', "sdfdsfdsfsdf", '2016-01-01'],
|
13
|
+
['nom2', "sdfdsfdsfsdf", '2016-01-01']
|
14
14
|
]
|
15
15
|
end
|
16
16
|
|
@@ -26,9 +26,9 @@ module ArelExtensions
|
|
26
26
|
insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
|
27
27
|
insert_manager.bulk_insert(@cols, @data)
|
28
28
|
sql = compile(insert_manager.ast)
|
29
|
-
sql.must_be_like %Q[INSERT
|
29
|
+
sql.must_be_like %Q[INSERT INTO "users" ("name", "comments", "created_at") ((SELECT 'nom1', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL) UNION ALL (SELECT 'nom2', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL))]
|
30
30
|
end
|
31
31
|
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
@@ -63,7 +63,6 @@ module ArelExtensions
|
|
63
63
|
it "should accept functions on strings" do
|
64
64
|
c = @table[:name]
|
65
65
|
compile(c + 'test').must_be_like %{CONCAT(\"users\".\"name\", 'test')}
|
66
|
-
compile(c + 'test' + ' chain').must_be_like %{CONCAT(CONCAT(\"users\".\"name\", 'test'), ' chain')}
|
67
66
|
compile(c.length).must_be_like %{LENGTH("users"."name")}
|
68
67
|
#puts (c.length.round + 42).inspect
|
69
68
|
compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
|
@@ -82,6 +81,13 @@ module ArelExtensions
|
|
82
81
|
compile(c + '0').must_be_like %{CONCAT("users"."name", '0')}
|
83
82
|
compile(c.substring(1) + '0').must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
|
84
83
|
compile(c.substring(1) + c.substring(2)).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
|
84
|
+
compile(c.concat(c).concat(c)).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
|
85
|
+
compile(c + c + c).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
|
86
|
+
|
87
|
+
# some optimization on concat
|
88
|
+
compile(c + 'test' + ' chain').must_be_like %{CONCAT(\"users\".\"name\", 'test chain')}
|
89
|
+
compile(Arel::Nodes.build_quoted('test') + ' chain').must_be_like %{'test chain'}
|
90
|
+
compile(c + '' + c).must_be_like %{CONCAT(\"users\".\"name\", \"users\".\"name\")}
|
85
91
|
end
|
86
92
|
|
87
93
|
# Comparators
|
@@ -302,7 +308,7 @@ module ArelExtensions
|
|
302
308
|
.must_be_like %{(CAST("users"."id" AS int) + 2)}
|
303
309
|
end
|
304
310
|
|
305
|
-
it "should be possible to
|
311
|
+
it "should be possible to have nil element in the function NIL" do
|
306
312
|
compile(@table[:id].in(nil))
|
307
313
|
.must_be_like %{ISNULL("users"."id")}
|
308
314
|
compile(@table[:id].in([nil]))
|
@@ -319,6 +325,30 @@ module ArelExtensions
|
|
319
325
|
.must_be_like %{"users"."id" IN (1, 2)}
|
320
326
|
|
321
327
|
end
|
328
|
+
|
329
|
+
it "should be possible to add and substract as much as we want" do
|
330
|
+
c = @table[:name]
|
331
|
+
compile(c.locate('test')+1)
|
332
|
+
.must_be_like %{(LOCATE('test', "users"."name") + 1)}
|
333
|
+
compile(c.locate('test')-1)
|
334
|
+
.must_be_like %{(LOCATE('test', "users"."name") - 1)}
|
335
|
+
compile(c.locate('test')+c.locate('test'))
|
336
|
+
.must_be_like %{(LOCATE('test', "users"."name") + LOCATE('test', "users"."name"))}
|
337
|
+
compile(c.locate('test')+1+c.locate('test')-1 + 1)
|
338
|
+
.must_be_like %{((((LOCATE('test', "users"."name") + 1) + LOCATE('test', "users"."name")) - 1) + 1)}
|
339
|
+
end
|
340
|
+
|
341
|
+
it "should be possible to desc and asc on functions" do
|
342
|
+
c = @table[:name]
|
343
|
+
compile(c.asc)
|
344
|
+
.must_be_like %{"users"."name" ASC}
|
345
|
+
compile(c.substring(2).asc)
|
346
|
+
.must_be_like %{SUBSTRING("users"."name", 2) ASC}
|
347
|
+
compile(c.substring(2).desc)
|
348
|
+
.must_be_like %{SUBSTRING("users"."name", 2) DESC}
|
349
|
+
compile((c.locate('test')+1).asc)
|
350
|
+
.must_be_like %{(LOCATE('test', "users"."name") + 1) ASC}
|
351
|
+
end
|
322
352
|
|
323
353
|
puts "AREL VERSION : " + Arel::VERSION.to_s
|
324
354
|
end
|
@@ -507,9 +507,12 @@ module ArelExtensions
|
|
507
507
|
def test_format_numbers
|
508
508
|
#score of Arthur = 65.62
|
509
509
|
skip " Works with SQLite if the version used knows printf" if @env_db = $sqlite
|
510
|
+
|
511
|
+
assert_equal "Wrong Format" , t(@arthur, @score.format_number("$ %...234.6F €","fr_FR"))
|
510
512
|
assert_equal "AZERTY65,62" , t(@arthur, @score.format_number("AZERTY%.2f","fr_FR"))
|
511
513
|
assert_equal "65,62AZERTY" , t(@arthur, @score.format_number("%.2fAZERTY","fr_FR"))
|
512
514
|
assert_equal "$ 65.62 €" , t(@arthur, @score.format_number("$ %.2f €","en_US"))
|
515
|
+
assert_equal "$ 66 €" , t(@arthur, @score.format_number("$ %.0f €","en_US"))
|
513
516
|
assert_equal "$ 0065,62 €" , t(@arthur, @score.format_number("$ %07.2f €","fr_FR"))
|
514
517
|
assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-07.2f €","fr_FR"))
|
515
518
|
assert_equal "$ 65,62 €" , t(@arthur, @score.format_number("$ %-7.2f €","fr_FR"))
|
@@ -519,8 +522,7 @@ module ArelExtensions
|
|
519
522
|
assert_equal "$ +065,62 €" , t(@arthur, @score.format_number("$ %0+7.2f €","fr_FR"))
|
520
523
|
assert_includes ["$ 6,56e1 €","$ 6,56e+01 €"], t(@arthur, @score.format_number("$ %.2e €","fr_FR"))
|
521
524
|
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"))
|
523
|
-
assert_equal "Wrong Format" , t(@arthur, @score.format_number("$ %...234.6F €","fr_FR"))
|
525
|
+
assert_includes ["$ 6,562E1 €","$ 6,562E+01 €"], t(@arthur, @score.format_number("$ %.3E €","fr_FR"))
|
524
526
|
end
|
525
527
|
|
526
528
|
def test_accent_insensitive
|
@@ -563,6 +565,7 @@ module ArelExtensions
|
|
563
565
|
assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("arretez")).then("1").else("0"))
|
564
566
|
assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrete")).then("1").else("0"))
|
565
567
|
assert_equal "0", t(@arthur,ArelExtensions::Nodes::Case.new.when(@comments.smatches("Arrêté")).then("1").else("0"))
|
568
|
+
|
566
569
|
end
|
567
570
|
|
568
571
|
def test_subquery_with_order
|
@@ -633,6 +636,17 @@ module ArelExtensions
|
|
633
636
|
#assert_equal true , @test.where(@age.not_in([nil,1,2])).blank?
|
634
637
|
end
|
635
638
|
|
639
|
+
def test_alias_shortened
|
640
|
+
if ['postgresql','oracle'].include?(@env_db)
|
641
|
+
new_alias = Arel.shorten('azerty' * 15)
|
642
|
+
at = User.arel_table.alias('azerty' * 15)
|
643
|
+
assert_equal "\"user_tests\" \"#{new_alias}\"".downcase, User.arel_table.alias('azerty' * 15).to_sql.downcase
|
644
|
+
assert_equal '"user_tests" "u"'.downcase, User.arel_table.alias('u').to_sql.downcase
|
645
|
+
assert_equal %Q[SELECT "#{new_alias}"."id" FROM "user_tests" "#{new_alias}"].downcase,
|
646
|
+
User.select(at[:id]).from(at).to_sql.downcase
|
647
|
+
end
|
648
|
+
end
|
649
|
+
|
636
650
|
end
|
637
651
|
end
|
638
652
|
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.1.0
|
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-08-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -208,26 +208,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
208
|
version: '0'
|
209
209
|
requirements: []
|
210
210
|
rubyforge_project:
|
211
|
-
rubygems_version: 2.
|
211
|
+
rubygems_version: 2.5.2.1
|
212
212
|
signing_key:
|
213
213
|
specification_version: 4
|
214
214
|
summary: Extending Arel
|
215
|
-
test_files:
|
216
|
-
- test/database.yml
|
217
|
-
- test/helper.rb
|
218
|
-
- test/real_db_test.rb
|
219
|
-
- test/support/alter_system_user_password.sql
|
220
|
-
- test/support/create_oracle_enhanced_users.sql
|
221
|
-
- test/support/fake_record.rb
|
222
|
-
- test/test_comparators.rb
|
223
|
-
- test/visitors/test_bulk_insert_oracle.rb
|
224
|
-
- test/visitors/test_bulk_insert_sqlite.rb
|
225
|
-
- test/visitors/test_bulk_insert_to_sql.rb
|
226
|
-
- test/visitors/test_oracle.rb
|
227
|
-
- test/visitors/test_to_sql.rb
|
228
|
-
- test/with_ar/all_agnostic_test.rb
|
229
|
-
- test/with_ar/insert_agnostic_test.rb
|
230
|
-
- test/with_ar/test_bulk_sqlite.rb
|
231
|
-
- test/with_ar/test_math_sqlite.rb
|
232
|
-
- test/with_ar/test_string_mysql.rb
|
233
|
-
- test/with_ar/test_string_sqlite.rb
|
215
|
+
test_files: []
|