arel_toolkit 0.3.0 → 0.4.4

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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -0
  3. data/.github/workflows/develop.yml +90 -0
  4. data/.github/workflows/master.yml +67 -0
  5. data/.gitignore +8 -0
  6. data/.rubocop.yml +13 -5
  7. data/Appraisals +13 -0
  8. data/CHANGELOG.md +94 -5
  9. data/Gemfile +5 -0
  10. data/Gemfile.lock +62 -33
  11. data/Guardfile +4 -0
  12. data/README.md +67 -23
  13. data/Rakefile +11 -1
  14. data/arel_toolkit.gemspec +15 -6
  15. data/benchmark.rb +54 -0
  16. data/ext/pg_result_init/extconf.rb +52 -0
  17. data/ext/pg_result_init/pg_result_init.c +138 -0
  18. data/ext/pg_result_init/pg_result_init.h +6 -0
  19. data/gemfiles/active_record_6.gemfile +7 -0
  20. data/gemfiles/active_record_6.gemfile.lock +210 -0
  21. data/gemfiles/arel_gems.gemfile +10 -0
  22. data/gemfiles/arel_gems.gemfile.lock +284 -0
  23. data/gemfiles/default.gemfile +5 -0
  24. data/gemfiles/default.gemfile.lock +208 -0
  25. data/lib/arel/enhance.rb +17 -0
  26. data/lib/arel/enhance/context_enhancer/arel_table.rb +92 -0
  27. data/lib/arel/enhance/node.rb +232 -0
  28. data/lib/arel/enhance/path.rb +38 -0
  29. data/lib/arel/enhance/path_node.rb +26 -0
  30. data/lib/arel/enhance/query.rb +38 -0
  31. data/lib/arel/enhance/query_methods.rb +23 -0
  32. data/lib/arel/enhance/visitor.rb +97 -0
  33. data/lib/arel/extensions.rb +32 -6
  34. data/lib/arel/extensions/active_model_attribute_with_cast_value.rb +22 -0
  35. data/lib/arel/extensions/active_record_relation_query_attribute.rb +22 -0
  36. data/lib/arel/extensions/active_record_type_caster_connection.rb +7 -0
  37. data/lib/arel/extensions/active_record_type_caster_map.rb +7 -0
  38. data/lib/arel/extensions/array.rb +2 -9
  39. data/lib/arel/extensions/at_time_zone.rb +10 -3
  40. data/lib/arel/extensions/attributes_attribute.rb +47 -0
  41. data/lib/arel/extensions/binary.rb +7 -0
  42. data/lib/arel/extensions/bind_param.rb +15 -0
  43. data/lib/arel/extensions/bit_string.rb +2 -9
  44. data/lib/arel/extensions/case.rb +17 -0
  45. data/lib/arel/extensions/coalesce.rb +17 -3
  46. data/lib/arel/extensions/conflict.rb +9 -0
  47. data/lib/arel/extensions/contains.rb +27 -5
  48. data/lib/arel/extensions/current_catalog.rb +4 -0
  49. data/lib/arel/extensions/current_date.rb +4 -0
  50. data/lib/arel/extensions/current_of_expression.rb +2 -9
  51. data/lib/arel/extensions/current_role.rb +4 -0
  52. data/lib/arel/extensions/current_row.rb +7 -0
  53. data/lib/arel/extensions/current_schema.rb +4 -0
  54. data/lib/arel/extensions/current_user.rb +4 -0
  55. data/lib/arel/extensions/dealocate.rb +31 -0
  56. data/lib/arel/extensions/default_values.rb +4 -0
  57. data/lib/arel/extensions/delete_manager.rb +22 -6
  58. data/lib/arel/extensions/delete_statement.rb +46 -24
  59. data/lib/arel/extensions/dot.rb +11 -0
  60. data/lib/arel/extensions/exists.rb +59 -0
  61. data/lib/arel/extensions/extract_from.rb +3 -10
  62. data/lib/arel/extensions/factorial.rb +10 -2
  63. data/lib/arel/extensions/false.rb +7 -0
  64. data/lib/arel/extensions/function.rb +44 -14
  65. data/lib/arel/extensions/greatest.rb +17 -3
  66. data/lib/arel/extensions/indirection.rb +3 -12
  67. data/lib/arel/extensions/infer.rb +7 -7
  68. data/lib/arel/extensions/infix_operation.rb +17 -0
  69. data/lib/arel/extensions/insert_manager.rb +19 -3
  70. data/lib/arel/extensions/insert_statement.rb +31 -12
  71. data/lib/arel/extensions/into.rb +21 -0
  72. data/lib/arel/extensions/least.rb +17 -3
  73. data/lib/arel/extensions/named_argument.rb +3 -8
  74. data/lib/arel/extensions/named_function.rb +7 -0
  75. data/lib/arel/extensions/node.rb +10 -0
  76. data/lib/arel/extensions/ordering.rb +21 -6
  77. data/lib/arel/extensions/overlaps.rb +9 -0
  78. data/lib/arel/extensions/overlay.rb +9 -0
  79. data/lib/arel/extensions/position.rb +3 -8
  80. data/lib/arel/extensions/prepare.rb +39 -0
  81. data/lib/arel/extensions/range_function.rb +10 -2
  82. data/lib/arel/extensions/row.rb +3 -8
  83. data/lib/arel/extensions/select_core.rb +73 -0
  84. data/lib/arel/extensions/select_manager.rb +22 -6
  85. data/lib/arel/extensions/select_statement.rb +31 -9
  86. data/lib/arel/extensions/session_user.rb +4 -0
  87. data/lib/arel/extensions/set_to_default.rb +4 -0
  88. data/lib/arel/extensions/substring.rb +8 -0
  89. data/lib/arel/extensions/table.rb +43 -10
  90. data/lib/arel/extensions/time_with_precision.rb +6 -0
  91. data/lib/arel/extensions/to_sql.rb +27 -0
  92. data/lib/arel/extensions/top.rb +8 -0
  93. data/lib/arel/extensions/transaction.rb +3 -8
  94. data/lib/arel/extensions/tree_manager.rb +15 -0
  95. data/lib/arel/extensions/trim.rb +8 -0
  96. data/lib/arel/extensions/true.rb +7 -0
  97. data/lib/arel/extensions/type_cast.rb +7 -0
  98. data/lib/arel/extensions/unary.rb +7 -0
  99. data/lib/arel/extensions/unary_operation.rb +16 -0
  100. data/lib/arel/extensions/unknown.rb +4 -0
  101. data/lib/arel/extensions/update_manager.rb +22 -6
  102. data/lib/arel/extensions/update_statement.rb +36 -33
  103. data/lib/arel/extensions/user.rb +4 -0
  104. data/lib/arel/extensions/values_list.rb +15 -0
  105. data/lib/arel/extensions/variable_set.rb +9 -0
  106. data/lib/arel/extensions/variable_show.rb +3 -8
  107. data/lib/arel/middleware.rb +5 -1
  108. data/lib/arel/middleware/active_record_extension.rb +13 -0
  109. data/lib/arel/middleware/cache_accessor.rb +35 -0
  110. data/lib/arel/middleware/chain.rb +108 -33
  111. data/lib/arel/middleware/database_executor.rb +77 -0
  112. data/lib/arel/middleware/no_op_cache.rb +9 -0
  113. data/lib/arel/middleware/postgresql_adapter.rb +41 -5
  114. data/lib/arel/middleware/railtie.rb +15 -1
  115. data/lib/arel/middleware/result.rb +170 -0
  116. data/lib/arel/middleware/to_sql_executor.rb +15 -0
  117. data/lib/arel/middleware/to_sql_middleware.rb +33 -0
  118. data/lib/arel/sql_to_arel.rb +6 -3
  119. data/lib/arel/sql_to_arel/pg_query_visitor.rb +67 -38
  120. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +1 -1
  121. data/lib/arel/sql_to_arel/result.rb +17 -4
  122. data/lib/arel/transformer.rb +8 -0
  123. data/lib/arel/transformer/prefix_schema_name.rb +183 -0
  124. data/lib/arel/transformer/remove_active_record_info.rb +40 -0
  125. data/lib/arel/transformer/replace_table_with_subquery.rb +31 -0
  126. data/lib/arel_toolkit.rb +15 -2
  127. data/lib/arel_toolkit/version.rb +1 -1
  128. metadata +179 -42
  129. data/.travis.yml +0 -29
  130. data/lib/arel/extensions/generate_series.rb +0 -9
  131. data/lib/arel/extensions/rank.rb +0 -9
  132. data/lib/arel/extensions/unbound_column_reference.rb +0 -5
  133. data/lib/arel/sql_formatter.rb +0 -59
@@ -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
@@ -0,0 +1,15 @@
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_BindParam(o)
8
+ visit_edge o, 'value'
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ # rubocop:enable Naming/MethodName
15
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -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
@@ -1,9 +1,23 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
1
4
  module Arel
2
5
  module Nodes
3
- class Coalesce < Arel::Nodes::NamedFunction
4
- def initialize(args)
5
- super 'COALESCE', args
6
+ # https://www.postgresql.org/docs/10/functions-conditional.html
7
+ class Coalesce < Arel::Nodes::Unary
8
+ end
9
+ end
10
+
11
+ module Visitors
12
+ class ToSql
13
+ def visit_Arel_Nodes_Coalesce(o, collector)
14
+ collector << 'COALESCE('
15
+ collector = inject_join(o.expr, collector, ', ')
16
+ collector << ')'
6
17
  end
7
18
  end
8
19
  end
9
20
  end
21
+
22
+ # rubocop:enable Naming/MethodName
23
+ # 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
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'current_role'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_CurrentRole terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -0,0 +1,7 @@
1
+ module Arel
2
+ module Visitors
3
+ class Dot
4
+ alias visit_Arel_Nodes_CurrentRow terminal
5
+ end
6
+ end
7
+ end
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'current_schema'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_CurrentSchema terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'current_user'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_CurrentUser terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -0,0 +1,31 @@
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_Dealocate(o)
8
+ visit_edge o, 'name'
9
+ end
10
+ end
11
+
12
+ class ToSql
13
+ def visit_Arel_Nodes_Dealocate(o, collector)
14
+ collector << 'DEALLOCATE ' << (o.name || 'ALL')
15
+ end
16
+ end
17
+ end
18
+
19
+ module Nodes
20
+ class Dealocate < Node
21
+ attr_reader :name
22
+
23
+ def initialize(name)
24
+ @name = name
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # rubocop:enable Naming/MethodName
31
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -14,6 +14,10 @@ module Arel
14
14
  collector << 'DEFAULT VALUES'
15
15
  end
16
16
  end
17
+
18
+ class Dot
19
+ alias visit_Arel_Nodes_DefaultValues terminal
20
+ end
17
21
  end
18
22
  end
19
23
 
@@ -1,9 +1,25 @@
1
- Arel::DeleteManager.class_eval do
2
- def ==(other)
3
- @ast == other.ast && @ctx == other.ctx
4
- end
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ class DeleteManager < Arel::TreeManager
6
+ def ==(other)
7
+ other.is_a?(self.class) && @ast == other.ast && @ctx == other.ctx
8
+ end
9
+
10
+ protected
5
11
 
6
- protected
12
+ attr_reader :ctx
13
+ end
7
14
 
8
- attr_reader :ctx
15
+ module Visitors
16
+ class Dot
17
+ def visit_Arel_DeleteManager(o)
18
+ visit_edge o, 'ast'
19
+ end
20
+ end
21
+ end
9
22
  end
23
+
24
+ # rubocop:enable Naming/MethodName
25
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -3,18 +3,24 @@
3
3
 
4
4
  module Arel
5
5
  module Nodes
6
- # https://www.postgresql.org/docs/9.5/sql-insert.html
7
- Arel::Nodes::DeleteStatement.class_eval do
8
- attr_accessor :using
9
- attr_accessor :with
10
- attr_accessor :returning
6
+ # https://www.postgresql.org/docs/10/sql-delete.html
7
+ class DeleteStatement
8
+ module DeleteStatementExtension
9
+ attr_accessor :using
10
+ attr_accessor :with
11
+ attr_accessor :returning
12
+ attr_accessor :orders
11
13
 
12
- alias_method :old_initialize, :initialize
13
- def initialize(relation = nil, wheres = [])
14
- old_initialize(relation, wheres)
14
+ def initialize(relation = nil, wheres = [])
15
+ super
15
16
 
16
- @returning = []
17
+ @returning = []
18
+ @orders = []
19
+ @using = []
20
+ end
17
21
  end
22
+
23
+ prepend DeleteStatementExtension
18
24
  end
19
25
  end
20
26
 
@@ -24,31 +30,47 @@ module Arel
24
30
  def visit_Arel_Nodes_DeleteStatement(o, collector)
25
31
  if o.with
26
32
  collector = visit o.with, collector
27
- collector << SPACE
33
+ collector << ' '
28
34
  end
29
35
 
30
- collector << 'DELETE FROM '
31
- collector = visit o.relation, collector
36
+ if Gem.loaded_specs['activerecord'].version >= Gem::Version.new('6.0.0')
37
+ o = prepare_delete_statement(o)
32
38
 
33
- if o.using
34
- collector << ' USING '
35
- collector = inject_join o.using, collector, ', '
39
+ if has_join_sources?(o)
40
+ collector << 'DELETE '
41
+ visit o.relation.left, collector
42
+ collector << ' FROM '
43
+ else
44
+ collector << 'DELETE FROM '
45
+ end
46
+ else
47
+ collector << 'DELETE FROM '
36
48
  end
37
49
 
38
- if o.wheres.any?
39
- collector << WHERE
40
- collector = inject_join o.wheres, collector, AND
41
- end
42
-
43
- unless o.returning.empty?
44
- collector << ' RETURNING '
45
- collector = inject_join o.returning, collector, ', '
46
- end
50
+ collector = visit o.relation, collector
47
51
 
52
+ collect_nodes_for o.using, collector, ' USING ', ', '
53
+ collect_nodes_for o.wheres, collector, ' WHERE ', ' AND '
54
+ collect_nodes_for o.returning, collector, ' RETURNING ', ', '
55
+ collect_nodes_for o.orders, collector, ' ORDER BY '
48
56
  maybe_visit o.limit, collector
49
57
  end
50
58
  # rubocop:enable Metrics/AbcSize
51
59
  end
60
+
61
+ class Dot
62
+ module DeleteStatementExtension
63
+ def visit_Arel_Nodes_DeleteStatement(o)
64
+ super
65
+
66
+ visit_edge o, 'using'
67
+ visit_edge o, 'with'
68
+ visit_edge o, 'returning'
69
+ end
70
+ end
71
+
72
+ prepend(DeleteStatementExtension)
73
+ end
52
74
  end
53
75
  end
54
76
 
@@ -0,0 +1,11 @@
1
+ # rubocop:disable Naming/UncommunicativeMethodParamName
2
+
3
+ module Arel
4
+ module Visitors
5
+ class Dot
6
+ def terminal(_o); end
7
+ end
8
+ end
9
+ end
10
+
11
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,59 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # This is a copy of https://github.com/rails/arel/blob/v9.0.0/lib/arel/nodes/function.rb
7
+ # Only difference is the superclass, because EXISTS is not a function but a subquery expression.
8
+ # Semantic meaning is important when transforming the Arel using the enhanced AST,
9
+ # because EXISTS cannot be processed as a function. For example it does not have a schema
10
+ # like a normal function.
11
+ #
12
+ # To change the superclass we're removing the existing Exists class `Arel::Nodes::Exists`
13
+ # and recreating it extending from `Arel::Nodes::Unary`.
14
+ remove_const(:Exists)
15
+
16
+ # https://www.postgresql.org/docs/10/functions-subquery.html
17
+ class Exists < Arel::Nodes::Unary
18
+ include Arel::Predications
19
+ include Arel::WindowPredications
20
+ include Arel::OrderPredications
21
+ attr_accessor :expressions, :alias, :distinct
22
+
23
+ def initialize(expr, aliaz = nil)
24
+ @expressions = expr
25
+ @alias = aliaz && SqlLiteral.new(aliaz)
26
+ @distinct = false
27
+ end
28
+
29
+ def as(aliaz)
30
+ self.alias = SqlLiteral.new(aliaz)
31
+ self
32
+ end
33
+
34
+ def hash
35
+ [@expressions, @alias, @distinct].hash
36
+ end
37
+
38
+ def eql?(other)
39
+ self.class == other.class &&
40
+ expressions == other.expressions &&
41
+ self.alias == other.alias &&
42
+ distinct == other.distinct
43
+ end
44
+ alias == eql?
45
+ end
46
+ end
47
+
48
+ module Visitors
49
+ class Dot
50
+ def visit_Arel_Nodes_Exists(o)
51
+ visit_edge o, 'expressions'
52
+ visit_edge o, 'alias'
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ # rubocop:enable Naming/MethodName
59
+ # rubocop:enable Naming/UncommunicativeMethodParamName