Class: Gitlab::SQL::RecursiveCTE
- Inherits:
-
Object
- Object
- Gitlab::SQL::RecursiveCTE
- Defined in:
- lib/gitlab/sql/recursive_cte.rb
Overview
Class for easily building recursive CTE statements.
Example:
cte = RecursiveCTE.new(:my_cte_name)
ns = Arel::Table.new(:namespaces)
cte << Namespace.
where(ns[:parent_id].eq(some_namespace_id))
cte << Namespace.
from([ns, cte.table]).
where(ns[:parent_id].eq(cte.table[:id]))
Namespace.with.
recursive(cte.to_arel).
from(cte.alias_to(ns))
Instance Attribute Summary collapse
-
#table ⇒ Object
readonly
Returns the value of attribute table.
Instance Method Summary collapse
-
#<<(relation) ⇒ Object
Adds a query to the body of the CTE.
-
#alias_to(alias_table) ⇒ Object
Returns an “AS” statement that aliases the CTE name as the given table name.
-
#apply_to(relation) ⇒ Object
Applies the CTE to the given relation, returning a new one that will query from it.
-
#initialize(name, union_args: {}) ⇒ RecursiveCTE
constructor
name - The name of the CTE as a String or Symbol.
-
#to_arel ⇒ Object
Returns the Arel relation for this CTE.
Constructor Details
#initialize(name, union_args: {}) ⇒ RecursiveCTE
name - The name of the CTE as a String or Symbol. union_args - The arguments supplied to Gitlab::SQL::Union class when building inner recursive query
27 28 29 30 31 |
# File 'lib/gitlab/sql/recursive_cte.rb', line 27 def initialize(name, union_args: {}) @table = Arel::Table.new(name) @queries = [] @union_args = union_args end |
Instance Attribute Details
#table ⇒ Object (readonly)
Returns the value of attribute table.
23 24 25 |
# File 'lib/gitlab/sql/recursive_cte.rb', line 23 def table @table end |
Instance Method Details
#<<(relation) ⇒ Object
Adds a query to the body of the CTE.
relation - The relation object to add to the body of the CTE.
36 37 38 |
# File 'lib/gitlab/sql/recursive_cte.rb', line 36 def <<(relation) @queries << relation end |
#alias_to(alias_table) ⇒ Object
Returns an “AS” statement that aliases the CTE name as the given table name. This allows one to trick ActiveRecord into thinking it’s selecting from an actual table, when in reality it’s selecting from a CTE.
alias_table - The Arel table to use as the alias.
52 53 54 |
# File 'lib/gitlab/sql/recursive_cte.rb', line 52 def alias_to(alias_table) Arel::Nodes::As.new(table, Arel::Table.new(alias_table.name.tr('.', '_'))) end |
#apply_to(relation) ⇒ Object
Applies the CTE to the given relation, returning a new one that will query from it.
58 59 60 61 62 63 |
# File 'lib/gitlab/sql/recursive_cte.rb', line 58 def apply_to(relation) relation.except(:where) .with .recursive(to_arel) .from(alias_to(relation.model.arel_table)) end |