arel_extensions 1.1.9 → 1.1.10
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/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
|