debian-mirror-gitlab/lib/gitlab/sql/cte.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

66 lines
1.8 KiB
Ruby
Raw Normal View History

2019-02-15 15:39:39 +05:30
# frozen_string_literal: true
2018-11-08 19:23:39 +05:30
module Gitlab
module SQL
# 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))
2021-04-29 21:17:54 +05:30
#
# To skip materialization of the CTE query by passing materialized: false
# More context: https://www.postgresql.org/docs/12/queries-with.html
#
# cte = CTE.new(:my_cte_name, materialized: false)
#
2018-11-08 19:23:39 +05:30
class CTE
attr_reader :table, :query
# name - The name of the CTE as a String or Symbol.
2021-04-29 21:17:54 +05:30
def initialize(name, query, materialized: true)
2018-11-08 19:23:39 +05:30
@table = Arel::Table.new(name)
@query = query
2021-04-29 21:17:54 +05:30
@materialized = materialized
2018-11-08 19:23:39 +05:30
end
# Returns the Arel relation for this CTE.
def to_arel
2022-07-23 23:45:48 +05:30
sql = Arel::Nodes::SqlLiteral.new("(#{query_as_sql})")
2018-11-08 19:23:39 +05:30
2021-04-29 21:17:54 +05:30
Gitlab::Database::AsWithMaterialized.new(table, sql, materialized: @materialized)
2018-11-08 19:23:39 +05:30
end
# 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.
def alias_to(alias_table)
Arel::Nodes::As.new(table, alias_table)
end
# Applies the CTE to the given relation, returning a new one that will
# query from it.
def apply_to(relation)
relation.except(:where)
.with(to_arel)
.from(alias_to(relation.model.arel_table))
end
2022-07-23 23:45:48 +05:30
private
def query_as_sql
query.is_a?(String) ? query : query.to_sql
end
2018-11-08 19:23:39 +05:30
end
end
end