Current section
Files
Jump to
Current section
Files
lib/endo/adapters/postgres/pg_class.ex
defmodule Endo.Adapters.Postgres.PgClass do
@moduledoc false
use Ecto.Schema
use Endo.Queryable
alias Endo.Adapters.Postgres.Index
alias Endo.Adapters.Postgres.PgAttribute
alias Endo.Adapters.Postgres.PgIndex
alias __MODULE__
@type t :: %__MODULE__{}
@foreign_key_type :string
@primary_key false
schema "pg_class" do
field(:oid, :id)
field(:relname, :string)
# (references pg_namespace.oid)
field(:relnamespace, :id)
# (references pg_type.oid)
field(:reltype, :id)
# (references pg_type.oid)
field(:reloftype, :id)
# (references pg_authid.oid)
field(:relowner, :id)
# (references pg_am.oid)
field(:relam, :id)
field(:relfilenode, :id)
# (references pg_tablespace.oid)
field(:reltablespace, :id)
field(:relpages, :integer)
field(:reltuples, :float)
field(:relallvisible, :integer)
# (references pg_class.oid)
field(:reltoastrelid, :id)
field(:relhasindex, :boolean)
field(:relisshared, :boolean)
field(:relpersistence, :string)
field(:relkind, :string)
field(:relnatts, :integer)
field(:relchecks, :integer)
field(:relhasrules, :boolean)
field(:relhastriggers, :boolean)
field(:relhassubclass, :boolean)
field(:relrowsecurity, :boolean)
field(:relforcerowsecurity, :boolean)
field(:relispopulated, :boolean)
field(:relreplident, :string)
field(:relispartition, :boolean)
# (references pg_class.oid)
field(:relrewrite, :id)
field(:relfrozenxid, :id)
field(:relminmxid, :id)
field(:reloptions, {:array, :string})
# field :relacl aclitem[]
# field :relpartbound pg_node_tree
end
@impl Endo.Queryable
def query(base_query \\ base_query(), filters) do
Enum.reduce(filters, base_query, fn
{:subquery, true}, query ->
from([self: self] in query, where: parent_as(:self).table_name == self.relname)
{:collate_indexes, true}, query ->
from([self: self] in query,
where: self.relkind == "r",
join: pg_index in PgIndex,
on: self.oid == pg_index.indrelid,
as: :pg_index,
join: pg_class in PgClass,
on: pg_class.oid == pg_index.indexrelid,
as: :pg_class,
join: pg_attribute in PgAttribute,
on: pg_attribute.attrelid == self.oid,
as: :pg_attribute,
where: pg_attribute.attnum in pg_index.indkey,
group_by: [self.oid, self.relname, pg_class.relname, pg_index.indexrelid],
select: %{
__struct__: Index,
name: pg_class.relname,
columns: fragment("ARRAY_AGG(?)", pg_attribute.attname),
pg_index: pg_index
}
)
{:having_index, column}, query ->
columns = (is_list(column) && column) || [column]
from([self: self, pg_attribute: pg_attribute] in Ecto.Query.exclude(query, :select),
having: ^columns == fragment("ARRAY_AGG(?)", pg_attribute.attname)
)
{field, value}, query ->
apply_filter(query, field, value)
end)
end
end