arel_toolkit 0.2.0 → 0.4.3

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 (150) 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 -2
  7. data/Appraisals +13 -0
  8. data/CHANGELOG.md +132 -6
  9. data/Gemfile +5 -0
  10. data/Gemfile.lock +92 -12
  11. data/Guardfile +23 -12
  12. data/README.md +104 -6
  13. data/Rakefile +18 -0
  14. data/arel_toolkit.gemspec +19 -4
  15. data/benchmark.rb +54 -0
  16. data/bin/console +1 -0
  17. data/ext/pg_result_init/extconf.rb +52 -0
  18. data/ext/pg_result_init/pg_result_init.c +138 -0
  19. data/ext/pg_result_init/pg_result_init.h +6 -0
  20. data/gemfiles/active_record_6.gemfile +7 -0
  21. data/gemfiles/active_record_6.gemfile.lock +210 -0
  22. data/gemfiles/arel_gems.gemfile +10 -0
  23. data/gemfiles/arel_gems.gemfile.lock +284 -0
  24. data/gemfiles/default.gemfile +5 -0
  25. data/gemfiles/default.gemfile.lock +208 -0
  26. data/lib/arel/enhance.rb +17 -0
  27. data/lib/arel/enhance/context_enhancer/arel_table.rb +92 -0
  28. data/lib/arel/enhance/node.rb +232 -0
  29. data/lib/arel/enhance/path.rb +38 -0
  30. data/lib/arel/enhance/path_node.rb +26 -0
  31. data/lib/arel/enhance/query.rb +38 -0
  32. data/lib/arel/enhance/query_methods.rb +23 -0
  33. data/lib/arel/enhance/visitor.rb +97 -0
  34. data/lib/arel/extensions.rb +55 -3
  35. data/lib/arel/extensions/active_model_attribute_with_cast_value.rb +22 -0
  36. data/lib/arel/extensions/active_record_relation_query_attribute.rb +22 -0
  37. data/lib/arel/extensions/active_record_type_caster_connection.rb +7 -0
  38. data/lib/arel/extensions/active_record_type_caster_map.rb +7 -0
  39. data/lib/arel/extensions/array.rb +2 -9
  40. data/lib/arel/extensions/assignment.rb +22 -0
  41. data/lib/arel/extensions/at_time_zone.rb +37 -0
  42. data/lib/arel/extensions/attributes_attribute.rb +47 -0
  43. data/lib/arel/extensions/binary.rb +7 -0
  44. data/lib/arel/extensions/bind_param.rb +15 -0
  45. data/lib/arel/extensions/bit_string.rb +2 -9
  46. data/lib/arel/extensions/case.rb +17 -0
  47. data/lib/arel/extensions/coalesce.rb +17 -3
  48. data/lib/arel/extensions/conflict.rb +9 -0
  49. data/lib/arel/extensions/contained_within_equals.rb +10 -0
  50. data/lib/arel/extensions/contains.rb +27 -5
  51. data/lib/arel/extensions/contains_equals.rb +10 -0
  52. data/lib/arel/extensions/current_catalog.rb +4 -0
  53. data/lib/arel/extensions/current_date.rb +4 -0
  54. data/lib/arel/extensions/current_of_expression.rb +2 -9
  55. data/lib/arel/extensions/current_role.rb +4 -0
  56. data/lib/arel/extensions/current_row.rb +7 -0
  57. data/lib/arel/extensions/current_schema.rb +4 -0
  58. data/lib/arel/extensions/current_user.rb +4 -0
  59. data/lib/arel/extensions/dealocate.rb +31 -0
  60. data/lib/arel/extensions/default_values.rb +4 -0
  61. data/lib/arel/extensions/delete_manager.rb +25 -0
  62. data/lib/arel/extensions/delete_statement.rb +32 -8
  63. data/lib/arel/extensions/distinct_from.rb +3 -16
  64. data/lib/arel/extensions/dot.rb +11 -0
  65. data/lib/arel/extensions/equality.rb +2 -4
  66. data/lib/arel/extensions/exists.rb +59 -0
  67. data/lib/arel/extensions/extract_from.rb +25 -0
  68. data/lib/arel/extensions/factorial.rb +10 -2
  69. data/lib/arel/extensions/false.rb +7 -0
  70. data/lib/arel/extensions/function.rb +44 -14
  71. data/lib/arel/extensions/greatest.rb +17 -3
  72. data/lib/arel/extensions/indirection.rb +3 -12
  73. data/lib/arel/extensions/infer.rb +7 -7
  74. data/lib/arel/extensions/infix_operation.rb +17 -0
  75. data/lib/arel/extensions/insert_manager.rb +21 -0
  76. data/lib/arel/extensions/insert_statement.rb +35 -9
  77. data/lib/arel/extensions/into.rb +21 -0
  78. data/lib/arel/extensions/json_get_field.rb +10 -0
  79. data/lib/arel/extensions/json_get_object.rb +10 -0
  80. data/lib/arel/extensions/json_path_get_field.rb +10 -0
  81. data/lib/arel/extensions/json_path_get_object.rb +10 -0
  82. data/lib/arel/extensions/jsonb_all_key_exists.rb +10 -0
  83. data/lib/arel/extensions/jsonb_any_key_exists.rb +10 -0
  84. data/lib/arel/extensions/jsonb_key_exists.rb +10 -0
  85. data/lib/arel/extensions/least.rb +17 -3
  86. data/lib/arel/extensions/named_argument.rb +24 -0
  87. data/lib/arel/extensions/named_function.rb +7 -0
  88. data/lib/arel/extensions/node.rb +10 -0
  89. data/lib/arel/extensions/not_distinct_from.rb +3 -16
  90. data/lib/arel/extensions/not_equal.rb +2 -4
  91. data/lib/arel/extensions/ordering.rb +21 -6
  92. data/lib/arel/extensions/overlap.rb +1 -1
  93. data/lib/arel/extensions/overlaps.rb +49 -0
  94. data/lib/arel/extensions/overlay.rb +53 -0
  95. data/lib/arel/extensions/position.rb +27 -0
  96. data/lib/arel/extensions/prepare.rb +39 -0
  97. data/lib/arel/extensions/range_function.rb +10 -2
  98. data/lib/arel/extensions/row.rb +3 -8
  99. data/lib/arel/extensions/select_core.rb +73 -0
  100. data/lib/arel/extensions/select_manager.rb +25 -0
  101. data/lib/arel/extensions/select_statement.rb +31 -9
  102. data/lib/arel/extensions/session_user.rb +4 -0
  103. data/lib/arel/extensions/set_to_default.rb +4 -0
  104. data/lib/arel/extensions/substring.rb +46 -0
  105. data/lib/arel/extensions/table.rb +43 -10
  106. data/lib/arel/extensions/time_with_precision.rb +6 -0
  107. data/lib/arel/extensions/to_sql.rb +27 -0
  108. data/lib/arel/extensions/top.rb +8 -0
  109. data/lib/arel/extensions/transaction.rb +45 -0
  110. data/lib/arel/extensions/tree_manager.rb +15 -0
  111. data/lib/arel/extensions/trim.rb +44 -0
  112. data/lib/arel/extensions/true.rb +7 -0
  113. data/lib/arel/extensions/type_cast.rb +11 -0
  114. data/lib/arel/extensions/unary.rb +7 -0
  115. data/lib/arel/extensions/unary_operation.rb +16 -0
  116. data/lib/arel/extensions/unknown.rb +4 -0
  117. data/lib/arel/extensions/update_manager.rb +25 -0
  118. data/lib/arel/extensions/update_statement.rb +31 -6
  119. data/lib/arel/extensions/user.rb +4 -0
  120. data/lib/arel/extensions/values_list.rb +15 -0
  121. data/lib/arel/extensions/variable_set.rb +55 -0
  122. data/lib/arel/extensions/variable_show.rb +26 -0
  123. data/lib/arel/middleware.rb +27 -0
  124. data/lib/arel/middleware/active_record_extension.rb +13 -0
  125. data/lib/arel/middleware/cache_accessor.rb +35 -0
  126. data/lib/arel/middleware/chain.rb +172 -0
  127. data/lib/arel/middleware/database_executor.rb +77 -0
  128. data/lib/arel/middleware/no_op_cache.rb +9 -0
  129. data/lib/arel/middleware/postgresql_adapter.rb +62 -0
  130. data/lib/arel/middleware/railtie.rb +25 -0
  131. data/lib/arel/middleware/result.rb +170 -0
  132. data/lib/arel/middleware/to_sql_executor.rb +15 -0
  133. data/lib/arel/middleware/to_sql_middleware.rb +33 -0
  134. data/lib/arel/sql_to_arel.rb +8 -4
  135. data/lib/arel/sql_to_arel/error.rb +6 -0
  136. data/lib/arel/sql_to_arel/pg_query_visitor.rb +324 -76
  137. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +112 -0
  138. data/lib/arel/sql_to_arel/result.rb +30 -0
  139. data/lib/arel/transformer.rb +8 -0
  140. data/lib/arel/transformer/prefix_schema_name.rb +183 -0
  141. data/lib/arel/transformer/remove_active_record_info.rb +40 -0
  142. data/lib/arel/transformer/replace_table_with_subquery.rb +31 -0
  143. data/lib/arel_toolkit.rb +16 -1
  144. data/lib/arel_toolkit/version.rb +1 -1
  145. metadata +278 -25
  146. data/.travis.yml +0 -21
  147. data/lib/arel/extensions/generate_series.rb +0 -9
  148. data/lib/arel/extensions/rank.rb +0 -9
  149. data/lib/arel/sql_to_arel/frame_options.rb +0 -110
  150. data/lib/arel/sql_to_arel/unbound_column_reference.rb +0 -5
@@ -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
@@ -0,0 +1,25 @@
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
11
+
12
+ attr_reader :ctx
13
+ end
14
+
15
+ module Visitors
16
+ class Dot
17
+ def visit_Arel_SelectManager(o)
18
+ visit_edge(o, 'ast')
19
+ end
20
+ end
21
+ end
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
 
@@ -0,0 +1,46 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Nodes
6
+ # https://www.postgresql.org/docs/10/functions-string.html
7
+ class Substring < Arel::Nodes::Node
8
+ attr_reader :string
9
+ attr_reader :pattern
10
+ attr_reader :escape
11
+
12
+ def initialize(string, pattern, escape)
13
+ @string = string
14
+ @pattern = pattern
15
+ @escape = escape
16
+ end
17
+ end
18
+ end
19
+
20
+ module Visitors
21
+ class ToSql
22
+ def visit_Arel_Nodes_Substring(o, collector)
23
+ collector << 'substring('
24
+ visit o.string, collector
25
+ collector << ' from '
26
+ visit o.pattern, collector
27
+ unless o.escape.nil?
28
+ collector << ' for '
29
+ visit o.escape, collector
30
+ end
31
+ collector << ')'
32
+ end
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
42
+ end
43
+ end
44
+
45
+ # rubocop:enable Naming/MethodName
46
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -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
@@ -10,4 +10,10 @@ module Arel
10
10
  end
11
11
  end
12
12
  end
13
+
14
+ module Visitors
15
+ class Dot
16
+ alias visit_Arel_Nodes_TimeWithPrecision terminal
17
+ end
18
+ end
13
19
  end
@@ -0,0 +1,27 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+
4
+ module Arel
5
+ module Visitors
6
+ class ToSql
7
+ def visit_Arel_Attributes_Attribute(o, collector)
8
+ if o.relation
9
+ join_name = o.relation.table_alias || o.relation.name
10
+ collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
11
+ else
12
+ visit_Arel_Nodes_UnqualifiedColumn o, collector
13
+ end
14
+ end
15
+
16
+ alias visit_Arel_Attributes_Integer visit_Arel_Attributes_Attribute
17
+ alias visit_Arel_Attributes_Float visit_Arel_Attributes_Attribute
18
+ alias visit_Arel_Attributes_Decimal visit_Arel_Attributes_Attribute
19
+ alias visit_Arel_Attributes_String visit_Arel_Attributes_Attribute
20
+ alias visit_Arel_Attributes_Time visit_Arel_Attributes_Attribute
21
+ alias visit_Arel_Attributes_Boolean visit_Arel_Attributes_Attribute
22
+ end
23
+ end
24
+ end
25
+
26
+ # rubocop:enable Naming/MethodName
27
+ # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arel # :nodoc: all
4
+ module Nodes
5
+ class Top < Unary
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,45 @@
1
+ # rubocop:disable Naming/MethodName
2
+ # rubocop:disable Naming/UncommunicativeMethodParamName
3
+ # rubocop:disable Metrics/CyclomaticComplexity
4
+ # rubocop:disable Metrics/AbcSize
5
+
6
+ module Arel
7
+ module Nodes
8
+ # https://www.postgresql.org/docs/8.3/tutorial-transactions.html
9
+ class Transaction < Arel::Nodes::Binary
10
+ alias type left
11
+ alias options right
12
+ end
13
+ end
14
+
15
+ module Visitors
16
+ class ToSql
17
+ def visit_Arel_Nodes_Transaction(o, collector)
18
+ case o.type
19
+ when 0
20
+ collector << 'BEGIN'
21
+ when 2
22
+ collector << 'COMMIT'
23
+ when 3
24
+ collector << 'ROLLBACK'
25
+ when 4
26
+ collector << 'SAVEPOINT '
27
+ collector << o.options.join(' ')
28
+ when 5
29
+ collector << 'RELEASE SAVEPOINT '
30
+ collector << o.options.join(' ')
31
+ when 6
32
+ collector << 'ROLLBACK TO '
33
+ collector << o.options.join(' ')
34
+ else
35
+ raise "Unknown transaction type `#{o.type}`"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ # rubocop:enable Naming/MethodName
43
+ # rubocop:enable Naming/UncommunicativeMethodParamName
44
+ # rubocop:enable Metrics/CyclomaticComplexity
45
+ # rubocop:enable Metrics/AbcSize