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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/coverage.yml +48 -0
  3. data/.github/workflows/test.yml +68 -0
  4. data/.gitignore +3 -1
  5. data/.rubocop.yml +2 -0
  6. data/.ruby-version +1 -1
  7. data/.tool-versions +1 -0
  8. data/Appraisals +4 -0
  9. data/CHANGELOG.md +49 -3
  10. data/Gemfile.lock +134 -84
  11. data/README.md +20 -3
  12. data/arel_toolkit.gemspec +3 -5
  13. data/bin/console +2 -1
  14. data/bin/setup +23 -2
  15. data/docker-compose.yml +11 -0
  16. data/gemfiles/active_record_6.gemfile +3 -3
  17. data/gemfiles/active_record_6.gemfile.lock +9 -7
  18. data/gemfiles/active_record_6_1.gemfile +7 -0
  19. data/gemfiles/active_record_6_1.gemfile.lock +263 -0
  20. data/gemfiles/arel_gems.gemfile.lock +9 -7
  21. data/gemfiles/default.gemfile.lock +9 -7
  22. data/lib/arel/enhance/context_enhancer/arel_table.rb +20 -0
  23. data/lib/arel/enhance/node.rb +20 -12
  24. data/lib/arel/enhance/visitor.rb +1 -1
  25. data/lib/arel/enhance.rb +2 -2
  26. data/lib/arel/extensions/conflict.rb +3 -3
  27. data/lib/arel/extensions/delete_statement.rb +19 -14
  28. data/lib/arel/extensions/infer.rb +2 -2
  29. data/lib/arel/extensions/insert_statement.rb +3 -3
  30. data/lib/arel/extensions/overlaps.rb +7 -1
  31. data/lib/arel/extensions/table.rb +7 -2
  32. data/lib/arel/extensions/transaction.rb +9 -9
  33. data/lib/arel/extensions/tree_manager.rb +0 -5
  34. data/lib/arel/extensions/update_statement.rb +8 -22
  35. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +37 -5
  36. data/lib/arel/sql_to_arel/pg_query_visitor.rb +430 -521
  37. data/lib/arel/transformer/prefix_schema_name.rb +5 -3
  38. data/lib/arel/transformer.rb +0 -1
  39. data/lib/arel_toolkit/version.rb +1 -1
  40. metadata +15 -12
  41. data/.github/workflows/develop.yml +0 -90
  42. data/.github/workflows/master.yml +0 -67
  43. 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 nil, 0
45
+ when :OVERRIDING_KIND_UNDEFINED, :OVERRIDING_NOT_SET, nil
46
46
  collector << ''
47
- when 1
47
+ when :OVERRIDING_USER_VALUE
48
48
  collector << ' OVERRIDING USER VALUE'
49
- when 2
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
- class Overlaps < Arel::Nodes::Node
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
- type_caster: nil,
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
- super(name, as: as, type_caster: type_caster)
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 0
19
+ when 1
20
20
  collector << 'BEGIN'
21
- when 2
22
- collector << 'COMMIT'
23
21
  when 3
24
- collector << 'ROLLBACK'
22
+ collector << 'COMMIT'
25
23
  when 4
26
- collector << 'SAVEPOINT '
27
- collector << o.options.join(' ')
24
+ collector << 'ROLLBACK'
28
25
  when 5
29
- collector << 'RELEASE SAVEPOINT '
30
- collector << o.options.join(' ')
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.options.join(' ')
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 o.orders.empty? && o.limit.nil?
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
- unless wheres.empty?
55
- collector << ' WHERE '
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
- unless o.returning.empty?
60
- collector << ' RETURNING '
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
- FRAMEOPTIONS = {
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, FRAMEOPTIONS.values)
73
- name = FRAMEOPTIONS.key(number)
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