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,10 @@
1
+ module Arel
2
+ module Nodes
3
+ class Node
4
+ def to_sql_and_binds(engine = Arel::Table.engine)
5
+ collector = engine.connection.send(:collector)
6
+ engine.connection.visitor.accept(self, collector).value
7
+ end
8
+ end
9
+ end
10
+ end
@@ -3,15 +3,19 @@
3
3
 
4
4
  module Arel
5
5
  module Nodes
6
- Arel::Nodes::Ordering.class_eval do
7
- # Postgres: https://www.postgresql.org/docs/9.4/queries-order.html
8
- attr_accessor :nulls
6
+ class Ordering
7
+ module OrderingExtension
8
+ # Postgres: https://www.postgresql.org/docs/9.4/queries-order.html
9
+ attr_accessor :nulls
9
10
 
10
- def initialize(expr, nulls = 0)
11
- super(expr)
11
+ def initialize(expr, nulls = 0)
12
+ super(expr)
12
13
 
13
- @nulls = nulls
14
+ @nulls = nulls
15
+ end
14
16
  end
17
+
18
+ prepend OrderingExtension
15
19
  end
16
20
  end
17
21
 
@@ -40,6 +44,17 @@ module Arel
40
44
  end
41
45
  end
42
46
  end
47
+
48
+ class Dot
49
+ module OrderingExtension
50
+ def visit_Arel_Nodes_Ordering(o)
51
+ super
52
+ visit_edge o, 'nulls'
53
+ end
54
+ end
55
+
56
+ prepend OrderingExtension
57
+ end
43
58
  end
44
59
  end
45
60
 
@@ -33,6 +33,15 @@ module Arel
33
33
  collector << ')'
34
34
  end
35
35
  end
36
+
37
+ class Dot
38
+ def visit_Arel_Nodes_Overlaps(o)
39
+ visit_edge o, 'start1'
40
+ visit_edge o, 'end1'
41
+ visit_edge o, 'start2'
42
+ visit_edge o, 'end2'
43
+ end
44
+ end
36
45
  end
37
46
  end
38
47
 
@@ -36,6 +36,15 @@ module Arel
36
36
  collector << ')'
37
37
  end
38
38
  end
39
+
40
+ class Dot
41
+ def visit_Arel_Nodes_Overlay(o)
42
+ visit_edge o, 'string'
43
+ visit_edge o, 'substring'
44
+ visit_edge o, 'start'
45
+ visit_edge o, 'length'
46
+ end
47
+ end
39
48
  end
40
49
  end
41
50
 
@@ -4,14 +4,9 @@
4
4
  module Arel
5
5
  module Nodes
6
6
  # https://www.postgresql.org/docs/9.1/functions-string.html#FUNCTIONS-STRING-SQL
7
- class Position < Arel::Nodes::Node
8
- attr_reader :substring
9
- attr_reader :string
10
-
11
- def initialize(substring, string)
12
- @substring = substring
13
- @string = string
14
- end
7
+ class Position < Arel::Nodes::Binary
8
+ alias substring left
9
+ alias string right
15
10
  end
16
11
  end
17
12
 
@@ -0,0 +1,39 @@
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_Prepare(o)
8
+ visit_edge o, 'name'
9
+ visit_edge o, 'argtypes'
10
+ visit_edge o, 'query'
11
+ end
12
+ end
13
+
14
+ class ToSql
15
+ def visit_Arel_Nodes_Prepare(o, collector)
16
+ collector << "PREPARE #{o.name}"
17
+ collector << " (#{o.argtypes.join(', ')})" if o.argtypes
18
+ collector << ' AS ('
19
+ visit(o.query, collector)
20
+ collector << ')'
21
+ end
22
+ end
23
+ end
24
+
25
+ module Nodes
26
+ class Prepare < Node
27
+ attr_reader :name, :query, :argtypes
28
+
29
+ def initialize(name, argtypes, query)
30
+ @name = name
31
+ @query = query
32
+ @argtypes = argtypes
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ # rubocop:enable Naming/MethodName
39
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -5,15 +5,23 @@ module Arel
5
5
  module Nodes
6
6
  # Postgres: https://www.postgresql.org/docs/9.4/sql-select.html
7
7
  class RangeFunction < Arel::Nodes::Unary
8
+ attr_reader :is_rowsfrom
9
+
10
+ def initialize(*args, is_rowsfrom:, **kwargs)
11
+ @is_rowsfrom = is_rowsfrom
12
+ super(*args, **kwargs)
13
+ end
8
14
  end
9
15
  end
10
16
 
11
17
  module Visitors
12
18
  class ToSql
13
19
  def visit_Arel_Nodes_RangeFunction(o, collector)
14
- collector << 'ROWS FROM ('
20
+ collector << 'ROWS FROM (' if o.is_rowsfrom
15
21
  visit o.expr, collector
16
- collector << ')'
22
+ collector << ')' if o.is_rowsfrom
23
+
24
+ collector
17
25
  end
18
26
  end
19
27
  end
@@ -4,14 +4,9 @@
4
4
  module Arel
5
5
  module Nodes
6
6
  # Postgres: https://www.postgresql.org/docs/9.2/sql-expressions.html
7
- class Row < Arel::Nodes::Unary
8
- attr_reader :row_format
9
-
10
- def initialize(args, row_format)
11
- super(args)
12
-
13
- @row_format = row_format
14
- end
7
+ class Row < Arel::Nodes::Binary
8
+ alias expr left
9
+ alias row_format right
15
10
  end
16
11
  end
17
12
 
@@ -0,0 +1,73 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+ # rubocop:disable Metrics/AbcSize
4
+
5
+ module Arel
6
+ module Nodes
7
+ class SelectCore < Arel::Nodes::Node
8
+ attr_accessor :into
9
+ attr_accessor :top
10
+
11
+ private
12
+
13
+ def hash
14
+ [
15
+ @source, @set_quantifier, @projections, @optimizer_hints,
16
+ @wheres, @groups, @havings, @windows, @comment, @top, @into
17
+ ].hash
18
+ end
19
+
20
+ def eql?(other)
21
+ super &&
22
+ top == other.top &&
23
+ into == other.into
24
+ end
25
+ end
26
+ end
27
+
28
+ module Visitors
29
+ class ToSql
30
+ def visit_Arel_Nodes_SelectCore(o, collector)
31
+ collector << 'SELECT'
32
+
33
+ collector = maybe_visit o.set_quantifier, collector
34
+
35
+ collect_nodes_for o.projections, collector, ' '
36
+
37
+ maybe_visit o.into, collector
38
+
39
+ if o.source && !o.source.empty?
40
+ collector << ' FROM '
41
+ collector = visit o.source, collector
42
+ end
43
+
44
+ collect_nodes_for o.wheres, collector, ' WHERE ', ' AND '
45
+ collect_nodes_for o.groups, collector, ' GROUP BY '
46
+ unless o.havings.empty?
47
+ collector << ' HAVING '
48
+ inject_join o.havings, collector, ' AND '
49
+ end
50
+ collect_nodes_for o.windows, collector, ' WINDOW '
51
+
52
+ collector
53
+ end
54
+ end
55
+
56
+ class Dot
57
+ module SelectCoreExtension
58
+ def visit_Arel_Nodes_SelectCore(o)
59
+ super
60
+
61
+ visit_edge o, 'into'
62
+ visit_edge o, 'top'
63
+ end
64
+ end
65
+
66
+ prepend SelectCoreExtension
67
+ end
68
+ end
69
+ end
70
+
71
+ # rubocop:enable Metrics/AbcSize
72
+ # rubocop:enable Naming/MethodName
73
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -1,9 +1,25 @@
1
- Arel::SelectManager.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 SelectManager
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_SelectManager(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,21 +3,43 @@
3
3
 
4
4
  module Arel
5
5
  module Nodes
6
- Arel::Nodes::SelectStatement.class_eval do
7
- # For INSERT statements
8
- attr_accessor :values_lists
9
- attr_accessor :union
10
- attr_writer :cores
6
+ class SelectStatement
7
+ module SelectStatementExtension
8
+ # For INSERT statements
9
+ attr_accessor :values_lists
10
+ attr_accessor :union
11
+ attr_writer :cores
12
+ end
13
+
14
+ prepend SelectStatementExtension
11
15
  end
12
16
  end
13
17
 
14
18
  module Visitors
15
19
  class ToSql
16
- alias old_visit_Nodes_SelectStatement visit_Arel_Nodes_SelectStatement
17
- def visit_Arel_Nodes_SelectStatement(o, collector)
18
- visit(o.union, collector) if o.union
19
- old_visit_Nodes_SelectStatement(o, collector)
20
+ module SelectStatementExtension
21
+ def visit_Arel_Nodes_SelectStatement(o, collector)
22
+ visit(o.union, collector) if o.union
23
+ super
24
+ end
25
+ end
26
+
27
+ prepend SelectStatementExtension
28
+ end
29
+
30
+ class Dot
31
+ module SelectStatementExtension
32
+ def visit_Arel_Nodes_SelectStatement(o)
33
+ super
34
+
35
+ visit_edge o, 'lock'
36
+ visit_edge o, 'with'
37
+ visit_edge o, 'union'
38
+ visit_edge o, 'values_lists'
39
+ end
20
40
  end
41
+
42
+ prepend SelectStatementExtension
21
43
  end
22
44
  end
23
45
  end
@@ -13,6 +13,10 @@ module Arel
13
13
  collector << 'session_user'
14
14
  end
15
15
  end
16
+
17
+ class Dot
18
+ alias visit_Arel_Nodes_SessionUser terminal
19
+ end
16
20
  end
17
21
  end
18
22
 
@@ -14,6 +14,10 @@ module Arel
14
14
  collector << 'DEFAULT'
15
15
  end
16
16
  end
17
+
18
+ class Dot
19
+ alias visit_Arel_Nodes_SetToDefault terminal
20
+ end
17
21
  end
18
22
  end
19
23
 
@@ -31,6 +31,14 @@ module Arel
31
31
  collector << ')'
32
32
  end
33
33
  end
34
+
35
+ class Dot
36
+ def visit_Arel_Nodes_Substring(o)
37
+ visit_edge o, 'string'
38
+ visit_edge o, 'pattern'
39
+ visit_edge o, 'escape'
40
+ end
41
+ end
34
42
  end
35
43
  end
36
44
 
@@ -3,16 +3,15 @@
3
3
  # rubocop:disable Metrics/ParameterLists
4
4
 
5
5
  module Arel
6
- module Nodes
7
- Arel::Table.class_eval do
6
+ class Table
7
+ module TableExtension
8
8
  # postgres only: https://www.postgresql.org/docs/9.5/sql-select.html
9
9
  attr_accessor :only
10
- # postgres only: https://www.postgresql.org/docs/9.5/ddl-schemas.html
10
+ # postgres only: https://www.postgresql.org/docs/10/ddl-schemas.html
11
11
  attr_accessor :schema_name
12
12
  # postgres only: https://www.postgresql.org/docs/9.1/catalog-pg-class.html
13
13
  attr_accessor :relpersistence
14
14
 
15
- alias_method :old_initialize, :initialize
16
15
  def initialize(
17
16
  name,
18
17
  as: nil,
@@ -25,21 +24,55 @@ module Arel
25
24
  @schema_name = schema_name
26
25
  @relpersistence = relpersistence
27
26
 
28
- old_initialize(name, as: as, type_caster: type_caster)
27
+ super(name, as: as, type_caster: type_caster)
29
28
  end
30
29
  end
30
+
31
+ prepend TableExtension
31
32
  end
32
33
 
33
34
  module Visitors
34
35
  class ToSql
35
- alias old_visit_Arel_Table visit_Arel_Table
36
- def visit_Arel_Table(o, collector)
37
- collector << 'ONLY ' if o.only
36
+ module TableExtension
37
+ def visit_Arel_Table(o, collector)
38
+ collector << 'ONLY ' if o.only
39
+
40
+ case o.relpersistence
41
+ when 'p'
42
+ collector << ''
43
+
44
+ when 'u'
45
+ collector << 'UNLOGGED '
38
46
 
39
- collector << "\"#{o.schema_name}\"." if o.schema_name
47
+ when 't'
48
+ collector << 'TEMPORARY '
40
49
 
41
- old_visit_Arel_Table(o, collector)
50
+ else
51
+ raise "Unknown relpersistence `#{o.relpersistence}`"
52
+ end
53
+
54
+ collector << "\"#{o.schema_name}\"." if o.schema_name
55
+
56
+ super
57
+ end
42
58
  end
59
+
60
+ prepend TableExtension
61
+ end
62
+
63
+ class Dot
64
+ module TableExtension
65
+ def visit_Arel_Table(o)
66
+ super
67
+
68
+ visit_edge o, 'only'
69
+ visit_edge o, 'schema_name'
70
+ visit_edge o, 'relpersistence'
71
+ visit_edge o, 'type_caster'
72
+ end
73
+ end
74
+
75
+ prepend TableExtension
43
76
  end
44
77
  end
45
78
  end