arel_toolkit 0.3.0 → 0.4.0

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -0
  3. data/.gitignore +4 -1
  4. data/.rubocop.yml +13 -5
  5. data/.travis.yml +7 -2
  6. data/Appraisals +9 -0
  7. data/CHANGELOG.md +19 -0
  8. data/Gemfile +5 -0
  9. data/Gemfile.lock +22 -5
  10. data/README.md +59 -18
  11. data/arel_toolkit.gemspec +5 -1
  12. data/gemfiles/.bundle/config +2 -0
  13. data/gemfiles/arel_gems.gemfile +10 -0
  14. data/gemfiles/arel_gems.gemfile.lock +274 -0
  15. data/gemfiles/default.gemfile +5 -0
  16. data/gemfiles/default.gemfile.lock +198 -0
  17. data/lib/arel/enhance.rb +16 -0
  18. data/lib/arel/enhance/context_enhancer/arel_table.rb +75 -0
  19. data/lib/arel/enhance/node.rb +189 -0
  20. data/lib/arel/enhance/path.rb +38 -0
  21. data/lib/arel/enhance/path_node.rb +26 -0
  22. data/lib/arel/enhance/query.rb +36 -0
  23. data/lib/arel/enhance/visitor.rb +81 -0
  24. data/lib/arel/extensions.rb +24 -4
  25. data/lib/arel/extensions/active_record_type_caster_map.rb +7 -0
  26. data/lib/arel/extensions/array.rb +2 -9
  27. data/lib/arel/extensions/at_time_zone.rb +10 -3
  28. data/lib/arel/extensions/binary.rb +7 -0
  29. data/lib/arel/extensions/bit_string.rb +2 -9
  30. data/lib/arel/extensions/case.rb +17 -0
  31. data/lib/arel/extensions/conflict.rb +9 -0
  32. data/lib/arel/extensions/contains.rb +27 -5
  33. data/lib/arel/extensions/current_catalog.rb +4 -0
  34. data/lib/arel/extensions/current_date.rb +4 -0
  35. data/lib/arel/extensions/current_of_expression.rb +2 -9
  36. data/lib/arel/extensions/current_role.rb +4 -0
  37. data/lib/arel/extensions/current_row.rb +7 -0
  38. data/lib/arel/extensions/current_schema.rb +4 -0
  39. data/lib/arel/extensions/current_user.rb +4 -0
  40. data/lib/arel/extensions/dealocate.rb +31 -0
  41. data/lib/arel/extensions/default_values.rb +4 -0
  42. data/lib/arel/extensions/delete_manager.rb +22 -6
  43. data/lib/arel/extensions/delete_statement.rb +26 -9
  44. data/lib/arel/extensions/dot.rb +11 -0
  45. data/lib/arel/extensions/extract_from.rb +3 -10
  46. data/lib/arel/extensions/factorial.rb +10 -2
  47. data/lib/arel/extensions/false.rb +7 -0
  48. data/lib/arel/extensions/function.rb +42 -13
  49. data/lib/arel/extensions/indirection.rb +3 -12
  50. data/lib/arel/extensions/infer.rb +6 -6
  51. data/lib/arel/extensions/infix_operation.rb +17 -0
  52. data/lib/arel/extensions/insert_manager.rb +19 -3
  53. data/lib/arel/extensions/insert_statement.rb +30 -11
  54. data/lib/arel/extensions/into.rb +21 -0
  55. data/lib/arel/extensions/named_argument.rb +3 -8
  56. data/lib/arel/extensions/named_function.rb +7 -0
  57. data/lib/arel/extensions/ordering.rb +21 -6
  58. data/lib/arel/extensions/overlaps.rb +9 -0
  59. data/lib/arel/extensions/overlay.rb +9 -0
  60. data/lib/arel/extensions/position.rb +3 -8
  61. data/lib/arel/extensions/prepare.rb +39 -0
  62. data/lib/arel/extensions/row.rb +3 -8
  63. data/lib/arel/extensions/select_core.rb +58 -0
  64. data/lib/arel/extensions/select_manager.rb +22 -6
  65. data/lib/arel/extensions/select_statement.rb +31 -9
  66. data/lib/arel/extensions/session_user.rb +4 -0
  67. data/lib/arel/extensions/set_to_default.rb +4 -0
  68. data/lib/arel/extensions/substring.rb +8 -0
  69. data/lib/arel/extensions/table.rb +43 -10
  70. data/lib/arel/extensions/time_with_precision.rb +6 -0
  71. data/lib/arel/extensions/to_sql.rb +27 -0
  72. data/lib/arel/extensions/transaction.rb +3 -8
  73. data/lib/arel/extensions/tree_manager.rb +10 -0
  74. data/lib/arel/extensions/trim.rb +8 -0
  75. data/lib/arel/extensions/true.rb +7 -0
  76. data/lib/arel/extensions/type_cast.rb +7 -0
  77. data/lib/arel/extensions/unary.rb +7 -0
  78. data/lib/arel/extensions/unary_operation.rb +16 -0
  79. data/lib/arel/extensions/unknown.rb +4 -0
  80. data/lib/arel/extensions/update_manager.rb +22 -6
  81. data/lib/arel/extensions/update_statement.rb +27 -10
  82. data/lib/arel/extensions/user.rb +4 -0
  83. data/lib/arel/extensions/values_list.rb +15 -0
  84. data/lib/arel/extensions/variable_set.rb +9 -0
  85. data/lib/arel/extensions/variable_show.rb +3 -8
  86. data/lib/arel/middleware/chain.rb +1 -5
  87. data/lib/arel/middleware/railtie.rb +10 -0
  88. data/lib/arel/sql_to_arel.rb +6 -3
  89. data/lib/arel/sql_to_arel/pg_query_visitor.rb +43 -15
  90. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +1 -1
  91. data/lib/arel/sql_to_arel/result.rb +0 -4
  92. data/lib/arel/transformer.rb +7 -0
  93. data/lib/arel/transformer/add_schema_to_table.rb +26 -0
  94. data/lib/arel/transformer/remove_active_record_info.rb +42 -0
  95. data/lib/arel_toolkit.rb +8 -1
  96. data/lib/arel_toolkit/version.rb +1 -1
  97. metadata +81 -8
  98. data/lib/arel/extensions/unbound_column_reference.rb +0 -5
  99. data/lib/arel/sql_formatter.rb +0 -59
@@ -0,0 +1,38 @@
1
+ module Arel
2
+ module Enhance
3
+ class Path
4
+ attr_reader :nodes
5
+
6
+ def initialize(nodes = [])
7
+ @nodes = nodes
8
+ end
9
+
10
+ def append(path_node)
11
+ Path.new(nodes + [path_node])
12
+ end
13
+
14
+ def dig_send(object)
15
+ selected_object = object
16
+ nodes.each do |path_node|
17
+ selected_object = selected_object.send(*path_node.method)
18
+ end
19
+ selected_object
20
+ end
21
+
22
+ def to_a
23
+ nodes.map(&:value)
24
+ end
25
+
26
+ def current
27
+ nodes.last
28
+ end
29
+
30
+ def inspect
31
+ nodes.inspect
32
+ string = '['
33
+ string << nodes.map(&:inspect).join(', ')
34
+ string << ']'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module Arel
2
+ module Enhance
3
+ class PathNode
4
+ attr_reader :method
5
+ attr_reader :value
6
+
7
+ def initialize(method, value)
8
+ @method = method
9
+ @value = value
10
+ end
11
+
12
+ def arguments?
13
+ method.is_a?(Array)
14
+ end
15
+
16
+ def inspect
17
+ case value
18
+ when String
19
+ "'#{value}'"
20
+ else
21
+ value.inspect
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Arel
2
+ module Enhance
3
+ class Query
4
+ def self.call(node, kwargs)
5
+ node_attributes = %i[context parent]
6
+ node_args = kwargs.slice(*node_attributes)
7
+ object_args = kwargs.except(*node_attributes)
8
+
9
+ node.each.select do |child_node|
10
+ next unless matches?(child_node, node_args)
11
+
12
+ matches?(child_node.object, object_args)
13
+ end
14
+ end
15
+
16
+ def self.matches?(object, test)
17
+ case test
18
+ when Hash
19
+ case object
20
+ when Hash
21
+ test <= object
22
+ else
23
+ test.all? do |test_key, test_value|
24
+ next false unless object.respond_to?(test_key)
25
+
26
+ object_attribute_value = object.public_send(test_key)
27
+ matches? object_attribute_value, test_value
28
+ end
29
+ end
30
+ else
31
+ object == test
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,81 @@
1
+ require_relative './context_enhancer/arel_table'
2
+
3
+ module Arel
4
+ module Enhance
5
+ # rubocop:disable Naming/MethodName
6
+ class Visitor < Arel::Visitors::Dot
7
+ DEFAULT_CONTEXT_ENHANCERS = {
8
+ Arel::Table => Arel::Enhance::ContextEnhancer::ArelTable,
9
+ }.freeze
10
+
11
+ attr_reader :context_enhancers
12
+
13
+ def accept(object, context_enhancers = DEFAULT_CONTEXT_ENHANCERS)
14
+ @context_enhancers = context_enhancers
15
+
16
+ root_node = Arel::Enhance::Node.new(object)
17
+ accept_with_root(object, root_node)
18
+ end
19
+
20
+ def accept_with_root(object, root_node, context_enhancers = DEFAULT_CONTEXT_ENHANCERS)
21
+ @context_enhancers = context_enhancers
22
+
23
+ with_node(root_node) do
24
+ visit object
25
+ end
26
+
27
+ root_node
28
+ end
29
+
30
+ private
31
+
32
+ def visit_edge(object, method)
33
+ arel_node = object.send(method)
34
+
35
+ process_node(arel_node, Arel::Enhance::PathNode.new(method, method))
36
+ end
37
+
38
+ def nary(object)
39
+ visit_edge(object, 'children')
40
+ end
41
+ alias visit_Arel_Nodes_And nary
42
+
43
+ def visit_Hash(_object)
44
+ raise 'Hash is not supported'
45
+ end
46
+
47
+ def visit_Array(object)
48
+ object.each_with_index do |child, index|
49
+ process_node(child, Arel::Enhance::PathNode.new([:[], index], index))
50
+ end
51
+ end
52
+
53
+ def process_node(arel_node, path_node)
54
+ node = Arel::Enhance::Node.new(arel_node)
55
+ current_node.add(path_node, node)
56
+
57
+ update_context(node)
58
+
59
+ with_node node do
60
+ visit arel_node
61
+ end
62
+ end
63
+
64
+ def visit(object)
65
+ Arel::Visitors::Visitor.instance_method(:visit).bind(self).call(object)
66
+ end
67
+
68
+ def current_node
69
+ @node_stack.last
70
+ end
71
+
72
+ def update_context(node)
73
+ enhancer = context_enhancers[node.object.class]
74
+ return if enhancer.nil?
75
+
76
+ enhancer.call(node)
77
+ end
78
+ end
79
+ # rubocop:enable Naming/MethodName
80
+ end
81
+ end
@@ -1,3 +1,4 @@
1
+ require 'arel/extensions/dot'
1
2
  require 'arel/extensions/unknown'
2
3
  require 'arel/extensions/time_with_precision'
3
4
  require 'arel/extensions/current_time'
@@ -42,11 +43,15 @@ require 'arel/extensions/modulo'
42
43
  require 'arel/extensions/absolute'
43
44
  require 'arel/extensions/bitwise_xor'
44
45
  require 'arel/extensions/exponentiation'
46
+
45
47
  require 'arel/extensions/contains'
48
+ unless Gem.loaded_specs.key?('postgres_ext')
49
+ require 'arel/extensions/contained_within_equals'
50
+ require 'arel/extensions/contains_equals'
51
+ require 'arel/extensions/overlap'
52
+ end
53
+
46
54
  require 'arel/extensions/contained_by'
47
- require 'arel/extensions/contained_within_equals'
48
- require 'arel/extensions/contains_equals'
49
- require 'arel/extensions/overlap'
50
55
  require 'arel/extensions/select_statement'
51
56
  require 'arel/extensions/insert_statement'
52
57
  require 'arel/extensions/default_values'
@@ -80,7 +85,6 @@ require 'arel/extensions/jsonb_key_exists'
80
85
  require 'arel/extensions/jsonb_any_key_exists'
81
86
  require 'arel/extensions/jsonb_all_key_exists'
82
87
  require 'arel/extensions/transaction'
83
- require 'arel/extensions/unbound_column_reference'
84
88
  require 'arel/extensions/assignment'
85
89
  require 'arel/extensions/variable_set'
86
90
  require 'arel/extensions/variable_show'
@@ -90,6 +94,22 @@ require 'arel/extensions/substring'
90
94
  require 'arel/extensions/overlaps'
91
95
  require 'arel/extensions/trim'
92
96
  require 'arel/extensions/named_argument'
97
+ require 'arel/extensions/tree_manager'
98
+ require 'arel/extensions/into'
99
+ require 'arel/extensions/select_core'
100
+ require 'arel/extensions/unary'
101
+ require 'arel/extensions/binary'
102
+ require 'arel/extensions/unary_operation'
103
+ require 'arel/extensions/infix_operation'
104
+ require 'arel/extensions/values_list'
105
+ require 'arel/extensions/case'
106
+ require 'arel/extensions/current_row'
107
+ require 'arel/extensions/false'
108
+ require 'arel/extensions/true'
109
+ require 'arel/extensions/to_sql'
110
+ require 'arel/extensions/prepare'
111
+ require 'arel/extensions/dealocate'
112
+ require 'arel/extensions/active_record_type_caster_map'
93
113
 
94
114
  module Arel
95
115
  module Extensions
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Visitors
3
+ class Dot
4
+ alias visit_ActiveRecord_TypeCaster_Map terminal
5
+ end
6
+ end
7
+ end
@@ -3,14 +3,7 @@
3
3
 
4
4
  module Arel
5
5
  module Nodes
6
- class Array < Arel::Nodes::Node
7
- attr_reader :items
8
-
9
- def initialize(items)
10
- super()
11
-
12
- @items = items
13
- end
6
+ class Array < Arel::Nodes::Unary
14
7
  end
15
8
  end
16
9
 
@@ -18,7 +11,7 @@ module Arel
18
11
  class ToSql
19
12
  def visit_Arel_Nodes_Array(o, collector)
20
13
  collector << 'ARRAY['
21
- inject_join(o.items, collector, ', ')
14
+ inject_join(o.expr, collector, ', ')
22
15
  collector << ']'
23
16
  end
24
17
  end
@@ -4,12 +4,12 @@
4
4
  module Arel
5
5
  module Nodes
6
6
  # https://www.postgresql.org/docs/9.2/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT
7
- class AtTimeZone < Arel::Nodes::Unary
7
+ class AtTimeZone < Arel::Nodes::Node
8
8
  attr_reader :timezone
9
+ attr_reader :expr
9
10
 
10
11
  def initialize(expr, timezone)
11
- super(expr)
12
-
12
+ @expr = expr
13
13
  @timezone = timezone
14
14
  end
15
15
  end
@@ -23,6 +23,13 @@ module Arel
23
23
  visit o.timezone, collector
24
24
  end
25
25
  end
26
+
27
+ class Dot
28
+ def visit_Arel_Nodes_AtTimeZone(o)
29
+ visit_edge o, 'expr'
30
+ visit_edge o, 'timezone'
31
+ end
32
+ end
26
33
  end
27
34
  end
28
35
 
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Visitors
3
+ class Dot
4
+ alias visit_Arel_Nodes_Binary binary
5
+ end
6
+ end
7
+ end
@@ -3,21 +3,14 @@
3
3
 
4
4
  module Arel
5
5
  module Nodes
6
- class BitString < Arel::Nodes::Node
7
- attr_reader :str
8
-
9
- def initialize(str)
10
- super()
11
-
12
- @str = str
13
- end
6
+ class BitString < Arel::Nodes::Unary
14
7
  end
15
8
  end
16
9
 
17
10
  module Visitors
18
11
  class ToSql
19
12
  def visit_Arel_Nodes_BitString(o, collector)
20
- collector << "B'#{o.str[1..-1]}'"
13
+ collector << "B'#{o.expr[1..-1]}'"
21
14
  end
22
15
  end
23
16
  end
@@ -0,0 +1,17 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Visitors
6
+ class Dot
7
+ def visit_Arel_Nodes_Case(o)
8
+ visit_edge o, 'case'
9
+ visit_edge o, 'conditions'
10
+ visit_edge o, 'default'
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ # rubocop:enable Naming/MethodName
17
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -40,6 +40,15 @@ module Arel
40
40
  end
41
41
  # rubocop:enable Metrics/AbcSize
42
42
  end
43
+
44
+ class Dot
45
+ def visit_Arel_Nodes_Conflict(o)
46
+ visit_edge o, 'action'
47
+ visit_edge o, 'infer'
48
+ visit_edge o, 'values'
49
+ visit_edge o, 'wheres'
50
+ end
51
+ end
43
52
  end
44
53
  end
45
54
 
@@ -1,10 +1,32 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
1
4
  module Arel
2
- module Nodes
3
- # https://www.postgresql.org/docs/9.1/functions-array.html
4
- class Contains < Arel::Nodes::InfixOperation
5
- def initialize(left, right)
6
- super(:'@>', left, right)
5
+ if Gem.loaded_specs.key?('postgres_ext')
6
+ module Visitors
7
+ module ContainsPatch
8
+ def visit_Arel_Nodes_Contains(o, collector)
9
+ if o.left.is_a?(Arel::Attribute)
10
+ super
11
+ else
12
+ infix_value o, collector, ' @> '
13
+ end
14
+ end
15
+ end
16
+
17
+ PostgreSQL.prepend(ContainsPatch)
18
+ end
19
+ else
20
+ module Nodes
21
+ # https://www.postgresql.org/docs/9.1/functions-array.html
22
+ class Contains < Arel::Nodes::InfixOperation
23
+ def initialize(left, right)
24
+ super(:'@>', left, right)
25
+ end
7
26
  end
8
27
  end
9
28
  end
10
29
  end
30
+
31
+ # rubocop:enable Naming/MethodName
32
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'current_catalog'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_CurrentCatalog terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'current_date'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_CurrentDate terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -4,14 +4,7 @@
4
4
  module Arel
5
5
  module Nodes
6
6
  # https://www.postgresql.org/docs/10/sql-update.html
7
- class CurrentOfExpression < Arel::Nodes::Node
8
- attr_accessor :cursor_name
9
-
10
- def initialize(cursor_name)
11
- super()
12
-
13
- @cursor_name = cursor_name
14
- end
7
+ class CurrentOfExpression < Arel::Nodes::Unary
15
8
  end
16
9
  end
17
10
 
@@ -19,7 +12,7 @@ module Arel
19
12
  class ToSql
20
13
  def visit_Arel_Nodes_CurrentOfExpression(o, collector)
21
14
  collector << 'CURRENT OF '
22
- collector << o.cursor_name
15
+ collector << o.expr
23
16
  end
24
17
  end
25
18
  end