arel_extensions 1.1.9 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/arel_extensions.rb +11 -4
- data/lib/arel_extensions/nodes/case.rb +91 -91
- data/lib/arel_extensions/nodes/duration.rb +0 -5
- data/lib/arel_extensions/nodes/function.rb +1 -1
- data/lib/arel_extensions/nodes/json.rb +22 -1
- data/lib/arel_extensions/nodes/wday.rb +0 -4
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mysql.rb +38 -0
- data/lib/arel_extensions/visitors/oracle.rb +4 -0
- data/lib/arel_extensions/visitors/postgresql.rb +27 -0
- data/lib/arel_extensions/visitors/to_sql.rb +27 -15
- data/test/with_ar/all_agnostic_test.rb +17 -10
- metadata +2 -3
- data/lib/arel_extensions/nodes/as.rb +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 708dfbc3e662298b3d0cb782b5555182ea9758a3
|
4
|
+
data.tar.gz: 71bb77c55986474cf7a55b4687a2eca93517df47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b98769af5db36a1ad6bc978e5ca5787ef423ad4be3c8708024e199825809fb75fa6a34b7a92468842a55679dd11e4cfb3fcc5dc1105fca6bf7d289f0a120dca0
|
7
|
+
data.tar.gz: ff10289ae7c04a4849bddcdcf5046e9adc7dd20913ab37914d0a81e4825597ce9bff4273608ea524607086191df016d4e6719bf5e3d06258c9135a1756723a65
|
data/lib/arel_extensions.rb
CHANGED
@@ -61,7 +61,6 @@ require 'arel_extensions/common_sql_functions'
|
|
61
61
|
|
62
62
|
require 'arel_extensions/nodes/union'
|
63
63
|
require 'arel_extensions/nodes/union_all'
|
64
|
-
require 'arel_extensions/nodes/as'
|
65
64
|
require 'arel_extensions/nodes/case'
|
66
65
|
require 'arel_extensions/nodes/soundex'
|
67
66
|
require 'arel_extensions/nodes/cast'
|
@@ -75,8 +74,16 @@ module Arel
|
|
75
74
|
end
|
76
75
|
|
77
76
|
def self.shorten s
|
78
|
-
|
79
|
-
end
|
77
|
+
Base64.urlsafe_encode64(Digest::MD5.new.digest(s)).tr('=', '').tr('-', '_')
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.json *expr
|
81
|
+
if expr.length == 1
|
82
|
+
ArelExtensions::Nodes::Json.new(expr.first)
|
83
|
+
else
|
84
|
+
ArelExtensions::Nodes::Json.new(expr)
|
85
|
+
end
|
86
|
+
end
|
80
87
|
end
|
81
88
|
|
82
89
|
Arel::Attributes::Attribute.class_eval do
|
@@ -129,7 +136,7 @@ Arel::SelectManager.class_eval do
|
|
129
136
|
include ArelExtensions::Nodes
|
130
137
|
end
|
131
138
|
|
132
|
-
Arel::Nodes::As.class_eval do
|
139
|
+
Arel::Nodes::As.class_eval do
|
133
140
|
include ArelExtensions::Nodes
|
134
141
|
end
|
135
142
|
|
@@ -1,106 +1,106 @@
|
|
1
1
|
module ArelExtensions
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Nodes
|
3
|
+
if Arel::VERSION < "7.1.0"
|
4
|
+
class Case < Arel::Nodes::Node
|
5
|
+
attr_accessor :case, :conditions, :default
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
def initialize expression = nil, default = nil
|
8
|
+
@case = expression
|
9
|
+
@conditions = []
|
10
|
+
@default = default
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
class When < Arel::Nodes::Binary # :nodoc:
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
class Else < Arel::Nodes::Unary # :nodoc:
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
19
|
+
end
|
20
|
+
else
|
21
|
+
class Case < Arel::Nodes::Case
|
22
|
+
class When < Arel::Nodes::When # :nodoc:
|
23
|
+
end
|
24
|
+
class Else < Arel::Nodes::Else # :nodoc:
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
ArelExtensions::Nodes::Case.class_eval do
|
30
|
+
include Arel::Expressions
|
31
|
+
include Arel::OrderPredications
|
32
|
+
include ArelExtensions::Math
|
33
|
+
include ArelExtensions::Comparators
|
34
|
+
include ArelExtensions::Predications
|
35
|
+
include ArelExtensions::MathFunctions
|
36
|
+
include ArelExtensions::StringFunctions
|
37
|
+
include ArelExtensions::NullFunctions
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
39
|
+
def return_type
|
40
|
+
obj = if @conditions.length > 0
|
41
|
+
@conditions.last.right
|
42
|
+
elsif @default
|
43
|
+
@default.expr
|
44
|
+
else
|
45
|
+
nil
|
46
|
+
end
|
47
|
+
if obj.respond_to?(:return_type)
|
48
|
+
obj.return_type
|
49
|
+
else
|
50
|
+
case obj
|
51
|
+
when Integer, Float
|
52
|
+
:number
|
53
|
+
when Date, DateTime,Time
|
54
|
+
:datetime
|
55
|
+
when Arel::Attributes::Attribute
|
56
|
+
begin
|
57
|
+
Arel::Table.engine.connection.schema_cache.columns_hash(obj.relation.table_name)[obj.name.to_s].type
|
58
|
+
rescue Exception
|
59
|
+
:string
|
60
|
+
end
|
61
|
+
else
|
62
|
+
:string
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
def when condition, expression = nil
|
68
|
+
@conditions << Case::When.new(condition, expression)
|
69
|
+
self
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
def then expression
|
73
|
+
@conditions.last.right = expression
|
74
|
+
self
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
def else expression
|
78
|
+
@default = Case::Else.new expression
|
79
|
+
self
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
def initialize_copy other
|
83
|
+
super
|
84
|
+
@case = @case.clone if @case
|
85
|
+
@conditions = @conditions.map { |x| x.clone }
|
86
|
+
@default = @default.clone if @default
|
87
|
+
end
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
def hash
|
90
|
+
[@case, @conditions, @default].hash
|
91
|
+
end
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
def eql? other
|
94
|
+
self.class == other.class &&
|
95
|
+
self.case == other.case &&
|
96
|
+
self.conditions == other.conditions &&
|
97
|
+
self.default == other.default
|
98
|
+
end
|
99
|
+
alias :== :eql?
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
101
|
+
def as other
|
102
|
+
Arel::Nodes::As.new self, Arel::Nodes::SqlLiteral.new(other)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
106
|
end
|
@@ -17,8 +17,13 @@ module ArelExtensions
|
|
17
17
|
def set key, value
|
18
18
|
JsonSet.new(self,key,value)
|
19
19
|
end
|
20
|
+
|
21
|
+
def group as_array = true, orders= nil
|
22
|
+
JsonGroup.new(self,as_array, orders)
|
23
|
+
end
|
24
|
+
|
20
25
|
end
|
21
|
-
|
26
|
+
|
22
27
|
class Json < JsonNode
|
23
28
|
|
24
29
|
def initialize *expr
|
@@ -56,6 +61,22 @@ module ArelExtensions
|
|
56
61
|
class JsonMerge < JsonNode
|
57
62
|
end
|
58
63
|
|
64
|
+
class JsonGroup < JsonNode
|
65
|
+
attr_accessor :as_array, :orders
|
66
|
+
|
67
|
+
def initialize json, as_array = true, orders = nil
|
68
|
+
@hash = as_array ? json : json.hash
|
69
|
+
@as_array = as_array
|
70
|
+
if orders
|
71
|
+
if orders.is_a?(Array)
|
72
|
+
@orders = orders
|
73
|
+
else
|
74
|
+
@orders = [orders]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
59
80
|
class JsonGet < JsonNode
|
60
81
|
attr_accessor :key
|
61
82
|
|
@@ -386,7 +386,16 @@ module ArelExtensions
|
|
386
386
|
collector
|
387
387
|
end
|
388
388
|
|
389
|
+
# JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
|
390
|
+
def json_supported?
|
391
|
+
Arel::Table.engine.connection.send(:mariadb?) &&
|
392
|
+
Arel::Table.engine.connection.send(:version) >= '10.2.3' ||
|
393
|
+
!Arel::Table.engine.connection.send(:mariadb?) &&
|
394
|
+
Arel::Table.engine.connection.send(:version) >= '5.7.0'
|
395
|
+
end
|
396
|
+
|
389
397
|
def visit_ArelExtensions_Nodes_Json o,collector
|
398
|
+
return super if !json_supported?
|
390
399
|
case o.hash
|
391
400
|
when Array
|
392
401
|
collector << 'JSON_ARRAY('
|
@@ -454,6 +463,35 @@ module ArelExtensions
|
|
454
463
|
collector
|
455
464
|
end
|
456
465
|
|
466
|
+
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
467
|
+
if o.as_array
|
468
|
+
collector << 'JSON_ARRAYAGG('
|
469
|
+
collector = visit o.hash, collector
|
470
|
+
collector << ')'
|
471
|
+
else
|
472
|
+
case o.hash
|
473
|
+
when Hash
|
474
|
+
collector << 'JSON_MERGE_PATCH(' if o.hash.length > 1
|
475
|
+
o.hash.each.with_index do |(k,v),i|
|
476
|
+
if i != 0
|
477
|
+
collector << Arel::Visitors::MySQL::COMMA
|
478
|
+
end
|
479
|
+
collector << 'JSON_OBJECTAGG('
|
480
|
+
collector = visit k, collector
|
481
|
+
collector << Arel::Visitors::MySQL::COMMA
|
482
|
+
collector = visit v, collector
|
483
|
+
collector << ')'
|
484
|
+
end
|
485
|
+
collector << ')' if o.hash.length > 1
|
486
|
+
else
|
487
|
+
collector << 'JSON_OBJECTAGG('
|
488
|
+
collector = visit o.hash, collector
|
489
|
+
collector << ')'
|
490
|
+
end
|
491
|
+
end
|
492
|
+
collector
|
493
|
+
end
|
494
|
+
|
457
495
|
end
|
458
496
|
end
|
459
497
|
end
|
@@ -536,6 +536,10 @@ module ArelExtensions
|
|
536
536
|
collector
|
537
537
|
end
|
538
538
|
|
539
|
+
def visit_ArelExtensions_Nodes_As o, collector
|
540
|
+
visit_Arel_Nodes_As o, collector
|
541
|
+
end
|
542
|
+
|
539
543
|
alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
|
540
544
|
def visit_Arel_Attributes_Attribute o, collector
|
541
545
|
join_name = o.relation.table_alias || o.relation.name
|
@@ -464,6 +464,33 @@ module ArelExtensions
|
|
464
464
|
collector
|
465
465
|
end
|
466
466
|
|
467
|
+
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
468
|
+
if o.as_array
|
469
|
+
collector << 'jsonb_agg('
|
470
|
+
collector = visit o.hash, collector
|
471
|
+
collector << ')'
|
472
|
+
else
|
473
|
+
case o.hash
|
474
|
+
when Hash
|
475
|
+
o.hash.each.with_index do |(k,v),i|
|
476
|
+
if i != 0
|
477
|
+
collector << ' || '
|
478
|
+
end
|
479
|
+
collector << 'jsonb_object_agg('
|
480
|
+
collector = visit k, collector
|
481
|
+
collector << Arel::Visitors::MySQL::COMMA
|
482
|
+
collector = visit v, collector
|
483
|
+
collector << ')'
|
484
|
+
end
|
485
|
+
else
|
486
|
+
collector << 'jsonb_object_agg('
|
487
|
+
collector = visit o.hash, collector
|
488
|
+
collector << ')'
|
489
|
+
end
|
490
|
+
end
|
491
|
+
collector
|
492
|
+
end
|
493
|
+
|
467
494
|
end
|
468
495
|
end
|
469
496
|
end
|
@@ -459,20 +459,7 @@ module ArelExtensions
|
|
459
459
|
collector = visit o.right, collector
|
460
460
|
collector
|
461
461
|
end
|
462
|
-
|
463
|
-
def visit_ArelExtensions_Nodes_As o, collector
|
464
|
-
if o.left.is_a?(ArelExtensions::Nodes::Union) || o.left.is_a?(ArelExtensions::Nodes::UnionAll)
|
465
|
-
collector << "("
|
466
|
-
collector = visit o.left, collector
|
467
|
-
collector << ") "
|
468
|
-
visit o.right, collector
|
469
|
-
else
|
470
|
-
collector = visit o.left, collector
|
471
|
-
collector << " AS "
|
472
|
-
visit o.right, collector
|
473
|
-
end
|
474
|
-
end
|
475
|
-
|
462
|
+
|
476
463
|
def visit_ArelExtensions_Nodes_Case o, collector
|
477
464
|
collector << "CASE "
|
478
465
|
if o.case
|
@@ -591,7 +578,7 @@ module ArelExtensions
|
|
591
578
|
res += ', '
|
592
579
|
end
|
593
580
|
res += Arel::Nodes.build_quoted('"')+k + '": '
|
594
|
-
if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.
|
581
|
+
if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
|
595
582
|
res = res + '"' + v + '"'
|
596
583
|
else
|
597
584
|
res += v
|
@@ -605,6 +592,31 @@ module ArelExtensions
|
|
605
592
|
collector
|
606
593
|
end
|
607
594
|
|
595
|
+
def visit_ArelExtensions_Nodes_JsonGroup o, collector
|
596
|
+
if o.as_array
|
597
|
+
res = Arel::Nodes.build_quoted('[') + (o.orders ? o.hash.group_concat(', ',o.orders) : o.hash.group_concat(', ')) + ']'
|
598
|
+
collector = visit res, collector
|
599
|
+
else
|
600
|
+
res = Arel::Nodes.build_quoted('{')
|
601
|
+
orders = o.orders || o.hash.keys
|
602
|
+
o.hash.each.with_index do |(k,v),i|
|
603
|
+
if i != 0
|
604
|
+
res = res + ', '
|
605
|
+
end
|
606
|
+
kv = Arel::Nodes.build_quoted('"')+k + '": '
|
607
|
+
if (v.is_a?(Arel::Attributes::Attribute) && o.type_of_attribute(v) == :string) || (v.respond_to?(:return_type) && v.return_type == :string)
|
608
|
+
kv = kv + '"' + v + '"'
|
609
|
+
else
|
610
|
+
kv += v
|
611
|
+
end
|
612
|
+
res = res + kv.group_concat(', ',orders)
|
613
|
+
end
|
614
|
+
res = res + '}'
|
615
|
+
collector = visit res, collector
|
616
|
+
end
|
617
|
+
collector
|
618
|
+
end
|
619
|
+
|
608
620
|
end
|
609
621
|
end
|
610
622
|
end
|
@@ -694,18 +694,25 @@ module ArelExtensions
|
|
694
694
|
def test_json
|
695
695
|
skip "Can't be tested on travis"
|
696
696
|
#creation
|
697
|
-
assert_equal 'Arthur', t(@arthur,
|
698
|
-
assert_equal ["Arthur","Arthur"], parse_json(t(@arthur,
|
699
|
-
assert_equal ({"Arthur" => "Arthur", "Arthur2" => "ArthurArthur"}), parse_json(t(@arthur,
|
700
|
-
assert_equal ({"Arthur" => "Arthur","Arthur2" => 1}), parse_json(t(@arthur,
|
701
|
-
assert_equal ([{"age" => 21},{"name" => "Arthur","score" => 65.62}]), parse_json(t(@arthur,
|
702
|
-
|
697
|
+
assert_equal 'Arthur', t(@arthur,Arel.json(@name))
|
698
|
+
assert_equal ["Arthur","Arthur"], parse_json(t(@arthur,Arel.json(@name,@name)))
|
699
|
+
assert_equal ({"Arthur" => "Arthur", "Arthur2" => "ArthurArthur"}), parse_json(t(@arthur,Arel.json({@name => @name,@name+"2" => @name+@name})))
|
700
|
+
assert_equal ({"Arthur" => "Arthur","Arthur2" => 1}), parse_json(t(@arthur,Arel.json({@name => @name,@name+"2" => 1})))
|
701
|
+
assert_equal ([{"age" => 21},{"name" => "Arthur","score" => 65.62}]), parse_json(t(@arthur,Arel.json([{age: @age},{name: @name,score: @score}])))
|
702
|
+
|
703
|
+
# aggregate
|
704
|
+
assert_equal ({"5" => "Lucas", "15" => "Sophie", "23" => "Myung", "25" => "Laure"}),
|
705
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16),Arel.json({@age => @name}).group(false)))
|
706
|
+
assert_equal ({"5" => "Lucas", "15" => "Sophie", "23" => "Myung", "25" => "Laure", "Laure"=>25, "Lucas"=>5, "Myung"=>23, "Sophie"=>15}),
|
707
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16),Arel.json({@age => @name,@name => @age}).group(false)))
|
708
|
+
assert_equal ([{"5" => "Lucas"},{ "15" => "Sophie"},{ "23" => "Myung"},{ "25" => "Laure"}]),
|
709
|
+
parse_json(t(User.group(:score).where(@age.is_not_null).where(@score == 20.16),Arel.json({@age => @name}).group(true,[@age])))
|
710
|
+
|
703
711
|
skip "Not Yet Implemented" if $sqlite || ['oracle','mssql'].include?(@env_db)
|
704
|
-
|
705
712
|
#get
|
706
|
-
h1 =
|
713
|
+
h1 = Arel.json({@name => @name+@name,@name+"2" => 1})
|
707
714
|
assert_equal "ArthurArthur", parse_json(t(@arthur,h1.get(@name)))
|
708
|
-
h2 =
|
715
|
+
h2 = Arel.json([{age: @age},{name: @name,score: @score}])
|
709
716
|
assert_equal ({"age" => 21}), parse_json(t(@arthur,h2.get(0)))
|
710
717
|
assert_equal 21, parse_json(t(@arthur,h2.get(0).get('age')))
|
711
718
|
assert_nil t(@arthur,h2.get('age'))
|
@@ -724,7 +731,7 @@ module ArelExtensions
|
|
724
731
|
name = @arthur.select(@name.as('NaMe')).first.attributes
|
725
732
|
assert_equal 'Arthur', name["NaMe"] || name["name"] #because of Oracle
|
726
733
|
assert_equal 'Arthur', @arthur.select(@name.as('Na Me')).first.attributes["Na Me"]
|
727
|
-
assert_equal '
|
734
|
+
assert_equal 'ArthurArthur', @arthur.select((@name+@name).as('Na-Me')).first.attributes["Na-Me"]
|
728
735
|
end
|
729
736
|
end
|
730
737
|
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.1.
|
4
|
+
version: 1.1.10
|
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: 2019-04-
|
13
|
+
date: 2019-04-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -120,7 +120,6 @@ files:
|
|
120
120
|
- lib/arel_extensions/math_functions.rb
|
121
121
|
- lib/arel_extensions/nodes.rb
|
122
122
|
- lib/arel_extensions/nodes/abs.rb
|
123
|
-
- lib/arel_extensions/nodes/as.rb
|
124
123
|
- lib/arel_extensions/nodes/blank.rb
|
125
124
|
- lib/arel_extensions/nodes/case.rb
|
126
125
|
- lib/arel_extensions/nodes/cast.rb
|