arel_toolkit 0.4.3 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/coverage.yml +48 -0
- data/.github/workflows/test.yml +68 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -0
- data/Appraisals +4 -0
- data/CHANGELOG.md +49 -3
- data/Gemfile.lock +134 -84
- data/README.md +20 -3
- data/arel_toolkit.gemspec +3 -5
- data/bin/console +2 -1
- data/bin/setup +23 -2
- data/docker-compose.yml +11 -0
- data/gemfiles/active_record_6.gemfile +3 -3
- data/gemfiles/active_record_6.gemfile.lock +9 -7
- data/gemfiles/active_record_6_1.gemfile +7 -0
- data/gemfiles/active_record_6_1.gemfile.lock +263 -0
- data/gemfiles/arel_gems.gemfile.lock +9 -7
- data/gemfiles/default.gemfile.lock +9 -7
- data/lib/arel/enhance/context_enhancer/arel_table.rb +20 -0
- data/lib/arel/enhance/node.rb +20 -12
- data/lib/arel/enhance/visitor.rb +1 -1
- data/lib/arel/enhance.rb +2 -2
- data/lib/arel/extensions/conflict.rb +3 -3
- data/lib/arel/extensions/delete_statement.rb +19 -14
- data/lib/arel/extensions/infer.rb +2 -2
- data/lib/arel/extensions/insert_statement.rb +3 -3
- data/lib/arel/extensions/overlaps.rb +7 -1
- data/lib/arel/extensions/table.rb +7 -2
- data/lib/arel/extensions/transaction.rb +9 -9
- data/lib/arel/extensions/tree_manager.rb +0 -5
- data/lib/arel/extensions/update_statement.rb +8 -22
- data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +37 -5
- data/lib/arel/sql_to_arel/pg_query_visitor.rb +430 -521
- data/lib/arel/transformer/prefix_schema_name.rb +5 -3
- data/lib/arel/transformer.rb +0 -1
- data/lib/arel_toolkit/version.rb +1 -1
- metadata +15 -12
- data/.github/workflows/develop.yml +0 -90
- data/.github/workflows/master.yml +0 -67
- data/lib/arel/transformer/remove_active_record_info.rb +0 -40
@@ -42,11 +42,11 @@ module Arel
|
|
42
42
|
end
|
43
43
|
|
44
44
|
case o.override
|
45
|
-
when
|
45
|
+
when :OVERRIDING_KIND_UNDEFINED, :OVERRIDING_NOT_SET, nil
|
46
46
|
collector << ''
|
47
|
-
when
|
47
|
+
when :OVERRIDING_USER_VALUE
|
48
48
|
collector << ' OVERRIDING USER VALUE'
|
49
|
-
when
|
49
|
+
when :OVERRIDING_SYSTEM_VALUE
|
50
50
|
collector << ' OVERRIDING SYSTEM VALUE'
|
51
51
|
else
|
52
52
|
raise "Unknown override `#{o.override}`"
|
@@ -4,7 +4,13 @@
|
|
4
4
|
module Arel
|
5
5
|
module Nodes
|
6
6
|
# https://www.postgresql.org/docs/10/functions-string.html
|
7
|
-
|
7
|
+
inheritance_class = if Gem.loaded_specs['activerecord'].version < Gem::Version.new('6.1.0')
|
8
|
+
Arel::Nodes::Node
|
9
|
+
else
|
10
|
+
Arel::Nodes::InfixOperation
|
11
|
+
end
|
12
|
+
|
13
|
+
class Overlaps < inheritance_class
|
8
14
|
attr_reader :start1
|
9
15
|
attr_reader :end1
|
10
16
|
attr_reader :start2
|
@@ -15,7 +15,8 @@ module Arel
|
|
15
15
|
def initialize(
|
16
16
|
name,
|
17
17
|
as: nil,
|
18
|
-
|
18
|
+
klass: nil,
|
19
|
+
type_caster: klass&.type_caster,
|
19
20
|
only: false,
|
20
21
|
schema_name: nil,
|
21
22
|
relpersistence: 'p'
|
@@ -24,7 +25,11 @@ module Arel
|
|
24
25
|
@schema_name = schema_name
|
25
26
|
@relpersistence = relpersistence
|
26
27
|
|
27
|
-
|
28
|
+
if Gem.loaded_specs['activerecord'].version < Gem::Version.new('6.1.0')
|
29
|
+
super(name, as: as, type_caster: type_caster)
|
30
|
+
else
|
31
|
+
super(name, klass: klass, as: as, type_caster: type_caster)
|
32
|
+
end
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
@@ -16,21 +16,21 @@ module Arel
|
|
16
16
|
class ToSql
|
17
17
|
def visit_Arel_Nodes_Transaction(o, collector)
|
18
18
|
case o.type
|
19
|
-
when
|
19
|
+
when 1
|
20
20
|
collector << 'BEGIN'
|
21
|
-
when 2
|
22
|
-
collector << 'COMMIT'
|
23
21
|
when 3
|
24
|
-
collector << '
|
22
|
+
collector << 'COMMIT'
|
25
23
|
when 4
|
26
|
-
collector << '
|
27
|
-
collector << o.options.join(' ')
|
24
|
+
collector << 'ROLLBACK'
|
28
25
|
when 5
|
29
|
-
collector << '
|
30
|
-
collector << o.
|
26
|
+
collector << 'SAVEPOINT '
|
27
|
+
collector << o.right
|
31
28
|
when 6
|
29
|
+
collector << 'RELEASE SAVEPOINT '
|
30
|
+
collector << o.right
|
31
|
+
when 7
|
32
32
|
collector << 'ROLLBACK TO '
|
33
|
-
collector << o.
|
33
|
+
collector << o.right
|
34
34
|
else
|
35
35
|
raise "Unknown transaction type `#{o.type}`"
|
36
36
|
end
|
@@ -1,11 +1,6 @@
|
|
1
1
|
module Arel
|
2
2
|
class TreeManager
|
3
3
|
# Iterate through AST, nodes will be yielded depth-first
|
4
|
-
def each(&block)
|
5
|
-
return enum_for(:each) unless block_given?
|
6
|
-
|
7
|
-
::Arel::Visitors::DepthFirst.new(block).accept ast
|
8
|
-
end
|
9
4
|
|
10
5
|
def to_sql_and_binds(engine = Arel::Table.engine)
|
11
6
|
collector = engine.connection.send(:collector)
|
@@ -24,16 +24,17 @@ module Arel
|
|
24
24
|
|
25
25
|
module Visitors
|
26
26
|
class ToSql
|
27
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
28
27
|
# rubocop:disable Metrics/AbcSize
|
29
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
30
28
|
def visit_Arel_Nodes_UpdateStatement(o, collector)
|
31
29
|
if o.with
|
32
30
|
collector = visit o.with, collector
|
33
31
|
collector << ' '
|
34
32
|
end
|
35
33
|
|
36
|
-
wheres = if
|
34
|
+
wheres = if Gem.loaded_specs['activerecord'].version >= Gem::Version.new('6.0.0')
|
35
|
+
o = prepare_update_statement(o)
|
36
|
+
o.wheres
|
37
|
+
elsif o.orders.empty? && o.limit.nil?
|
37
38
|
o.wheres
|
38
39
|
else
|
39
40
|
[Nodes::In.new(o.key, [build_subselect(o.key, o)])]
|
@@ -41,31 +42,16 @@ module Arel
|
|
41
42
|
|
42
43
|
collector << 'UPDATE '
|
43
44
|
collector = visit o.relation, collector
|
44
|
-
unless o.values.empty?
|
45
|
-
collector << ' SET '
|
46
|
-
collector = inject_join o.values, collector, ', '
|
47
|
-
end
|
48
|
-
|
49
|
-
unless o.froms.empty?
|
50
|
-
collector << ' FROM '
|
51
|
-
collector = inject_join o.froms, collector, ', '
|
52
|
-
end
|
53
45
|
|
54
|
-
|
55
|
-
|
56
|
-
collector = inject_join wheres, collector, ' AND '
|
57
|
-
end
|
46
|
+
collect_nodes_for o.values, collector, ' SET '
|
47
|
+
collect_nodes_for o.froms, collector, ' FROM ', ', '
|
58
48
|
|
59
|
-
|
60
|
-
|
61
|
-
collector = inject_join o.returning, collector, ', '
|
62
|
-
end
|
49
|
+
collect_nodes_for wheres, collector, ' WHERE ', ' AND '
|
50
|
+
collect_nodes_for o.returning, collector, ' RETURNING ', ', '
|
63
51
|
|
64
52
|
collector
|
65
53
|
end
|
66
54
|
# rubocop:enable Metrics/AbcSize
|
67
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
68
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
69
55
|
end
|
70
56
|
|
71
57
|
class Dot
|
@@ -42,7 +42,7 @@ module Arel
|
|
42
42
|
# RANGE only unbounded
|
43
43
|
# ROWS all
|
44
44
|
# https://github.com/postgres/postgres/blob/REL_10_1/src/include/nodes/parsenodes.h
|
45
|
-
|
45
|
+
FRAMEOPTIONS_V10 = {
|
46
46
|
'FRAMEOPTION_NONDEFAULT' => 0x00001,
|
47
47
|
'FRAMEOPTION_RANGE' => 0x00002,
|
48
48
|
'FRAMEOPTION_ROWS' => 0x00004,
|
@@ -59,6 +59,38 @@ module Arel
|
|
59
59
|
'FRAMEOPTION_END_VALUE_FOLLOWING' => 0x02000,
|
60
60
|
}.freeze
|
61
61
|
|
62
|
+
FRAMEOPTIONS_V11_AND_UP = {
|
63
|
+
'FRAMEOPTION_NONDEFAULT' => 0x00001, # any specified? */
|
64
|
+
'FRAMEOPTION_RANGE' => 0x00002, # RANGE behavior */
|
65
|
+
'FRAMEOPTION_ROWS' => 0x00004, # ROWS behavior */
|
66
|
+
'FRAMEOPTION_GROUPS' => 0x00008, # GROUPS behavior */
|
67
|
+
'FRAMEOPTION_BETWEEN' => 0x00010, # BETWEEN given? */
|
68
|
+
'FRAMEOPTION_START_UNBOUNDED_PRECEDING' => 0x00020, # start is U. P. */
|
69
|
+
'FRAMEOPTION_END_UNBOUNDED_PRECEDING' => 0x00040, # (disallowed) */
|
70
|
+
'FRAMEOPTION_START_UNBOUNDED_FOLLOWING' => 0x00080, # (disallowed) */
|
71
|
+
'FRAMEOPTION_END_UNBOUNDED_FOLLOWING' => 0x00100, # end is U. F. */
|
72
|
+
'FRAMEOPTION_START_CURRENT_ROW' => 0x00200, # start is C. R. */
|
73
|
+
'FRAMEOPTION_END_CURRENT_ROW' => 0x00400, # end is C. R. */
|
74
|
+
'FRAMEOPTION_START_OFFSET_PRECEDING' => 0x00800, # start is O. P. */
|
75
|
+
'FRAMEOPTION_END_OFFSET_PRECEDING' => 0x01000, # end is O. P. */
|
76
|
+
'FRAMEOPTION_START_OFFSET_FOLLOWING' => 0x02000, # start is O. F. */
|
77
|
+
'FRAMEOPTION_END_OFFSET_FOLLOWING' => 0x04000, # end is O. F. */
|
78
|
+
'FRAMEOPTION_EXCLUDE_CURRENT_ROW' => 0x08000, # omit C.R. */
|
79
|
+
'FRAMEOPTION_EXCLUDE_GROUP' => 0x10000, # omit C.R. & peers */
|
80
|
+
'FRAMEOPTION_EXCLUDE_TIES' => 0x20000, # omit C.R.'s peers */
|
81
|
+
}.freeze
|
82
|
+
|
83
|
+
def frameoptions
|
84
|
+
case PG.library_version.to_s[0, 2]
|
85
|
+
when '09', '10'
|
86
|
+
FRAMEOPTIONS_V10
|
87
|
+
when '11', '12', '13', '14'
|
88
|
+
FRAMEOPTIONS_V11_AND_UP
|
89
|
+
else
|
90
|
+
boom "Version #{PG.library_version.to_s[0, 2]} not supported"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
62
94
|
def biggest_detractable_number(number, candidates)
|
63
95
|
high_to_low_candidates = candidates.sort { |a, b| b <=> a }
|
64
96
|
high_to_low_candidates.find do |candidate|
|
@@ -69,8 +101,8 @@ module Arel
|
|
69
101
|
def calculate_frame_option_names(frame_options, names = [])
|
70
102
|
return names if frame_options.zero?
|
71
103
|
|
72
|
-
number = biggest_detractable_number(frame_options,
|
73
|
-
name =
|
104
|
+
number = biggest_detractable_number(frame_options, frameoptions.values)
|
105
|
+
name = frameoptions.key(number)
|
74
106
|
calculate_frame_option_names(
|
75
107
|
frame_options - number, names + [name]
|
76
108
|
)
|
@@ -95,10 +127,10 @@ module Arel
|
|
95
127
|
when 'CURRENT_ROW'
|
96
128
|
Arel::Nodes::CurrentRow.new
|
97
129
|
|
98
|
-
when 'VALUE_PRECEDING'
|
130
|
+
when 'VALUE_PRECEDING', 'OFFSET_PRECEDING'
|
99
131
|
Arel::Nodes::Preceding.new offset
|
100
132
|
|
101
|
-
when 'VALUE_FOLLOWING'
|
133
|
+
when 'VALUE_FOLLOWING', 'OFFSET_FOLLOWING'
|
102
134
|
Arel::Nodes::Following.new offset
|
103
135
|
|
104
136
|
else
|