Class: Gitlab::SQL::CTE

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/sql/cte.rb

Overview

Class for easily building CTE statements.

Example:

cte = CTE.new(:my_cte_name)
ns = Arel::Table.new(:namespaces)

cte << Namespace.
  where(ns[:parent_id].eq(some_namespace_id))

Namespace
  with(cte.to_arel).
  from(cte.alias_to(ns))

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, query) ⇒ CTE

name - The name of the CTE as a String or Symbol.


22
23
24
25
# File 'lib/gitlab/sql/cte.rb', line 22

def initialize(name, query)
  @table = Arel::Table.new(name)
  @query = query
end

Instance Attribute Details

#queryObject (readonly)

Returns the value of attribute query


19
20
21
# File 'lib/gitlab/sql/cte.rb', line 19

def query
  @query
end

#tableObject (readonly)

Returns the value of attribute table


19
20
21
# File 'lib/gitlab/sql/cte.rb', line 19

def table
  @table
end

Instance Method Details

#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.


39
40
41
# File 'lib/gitlab/sql/cte.rb', line 39

def alias_to(alias_table)
  Arel::Nodes::As.new(table, alias_table)
end

#apply_to(relation) ⇒ Object

Applies the CTE to the given relation, returning a new one that will query from it.


45
46
47
48
49
# File 'lib/gitlab/sql/cte.rb', line 45

def apply_to(relation)
  relation.except(:where)
    .with(to_arel)
    .from(alias_to(relation.model.arel_table))
end

#to_arelObject

Returns the Arel relation for this CTE.


28
29
30
31
32
# File 'lib/gitlab/sql/cte.rb', line 28

def to_arel
  sql = Arel::Nodes::SqlLiteral.new("(#{query.to_sql})")

  Arel::Nodes::As.new(table, sql)
end