diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2018-06-12 10:46:31 +0000 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2018-06-12 10:46:31 +0000 |
commit | 450b9f6e30161e6719cf9ffb051b460eb48378c4 (patch) | |
tree | fd42a8e28ef14e40bfa9bea92041171978e93fdd /lib | |
parent | 9a4eadc87672de5b07b41df24810fbfe6c1f259e (diff) | |
parent | ed3a1be1e33388f3e3560d62fd658d0cc5f972ec (diff) | |
download | gitlab-ce-450b9f6e30161e6719cf9ffb051b460eb48378c4.tar.gz |
Merge branch 'da-port-cte-to-ce' into 'master'
Add Gitlab::SQL:CTE for easily building CTE statements
See merge request gitlab-org/gitlab-ce!19652
Diffstat (limited to 'lib')
-rw-r--r-- | lib/gitlab/sql/cte.rb | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/gitlab/sql/cte.rb b/lib/gitlab/sql/cte.rb new file mode 100644 index 00000000000..f357829ba3f --- /dev/null +++ b/lib/gitlab/sql/cte.rb @@ -0,0 +1,50 @@ +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)) + class CTE + attr_reader :table, :query + + # name - The name of the CTE as a String or Symbol. + def initialize(name, query) + @table = Arel::Table.new(name) + @query = query + end + + # Returns the Arel relation for this CTE. + def to_arel + sql = Arel::Nodes::SqlLiteral.new("(#{query.to_sql})") + + Arel::Nodes::As.new(table, sql) + 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 + end + end +end |