arel_toolkit 0.4.3 → 0.4.7

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.
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