use sqlx::{postgres::types::Oid, query_as, PgExecutor}; use crate::pg_acls::PgAclItem; pub struct PgClass { /// Row identifier pub oid: Oid, /// Name of the table, index, view, etc. pub relname: String, /// The OID of the namespace that contains this relation pub relnamespace: Oid, /// The OID of the data type that corresponds to this table's row type, if any; zero for indexes, sequences, and toast tables, which have no pg_type entry pub reltype: Oid, /// For typed tables, the OID of the underlying composite type; zero for all other relations pub reloftype: Oid, /// Owner of the relation pub relowner: Oid, /// r = ordinary table, i = index, S = sequence, t = TOAST table, v = view, m = materialized view, c = composite type, f = foreign table, p = partitioned table, I = partitioned index pub relkind: i8, /// Number of user columns in the relation (system columns not counted). There must be this many corresponding entries in pg_attribute. See also pg_attribute.attnum. pub relnatts: i16, /// Number of CHECK constraints on the table; see pg_constraint catalog pub relchecks: i16, /// True if table has (or once had) rules; see pg_rewrite catalog pub relhasrules: bool, /// True if table has (or once had) triggers; see pg_trigger catalog pub relhastriggers: bool, /// True if table or index has (or once had) any inheritance children or partitions pub relhassubclass: bool, /// True if table has row-level security enabled; see pg_policy catalog pub relrowsecurity: bool, /// True if row-level security (when enabled) will also apply to table owner; see pg_policy catalog pub relforcerowsecurity: bool, /// True if relation is populated (this is true for all relations other than some materialized views) pub relispopulated: bool, /// True if table or index is a partition pub relispartition: bool, pub relacl: Option>, } impl PgClass { pub async fn fetch_all_by_kind_any<'a, I: IntoIterator, E: PgExecutor<'a>>( kinds: I, client: E, ) -> Result, sqlx::Error> { let kinds_i8 = kinds .into_iter() .map(|kind| kind.to_u8() as i8) .collect::>(); query_as!( PgClass, r#" select oid, relname, relnamespace, reltype, reloftype, relowner, relkind, relnatts, relchecks, relhasrules, relhastriggers, relhassubclass, relrowsecurity, relforcerowsecurity, relispopulated, relispartition, relacl::text[] as "relacl: Vec" from pg_class where relkind = any($1) "#, kinds_i8.as_slice(), ) .fetch_all(client) .await } } pub enum PgRelKind { OrdinaryTable, Index, Sequence, ToastTable, View, MaterializedView, CompositeType, ForeignTable, PartitionedTable, PartitionedIndex, } impl PgRelKind { pub fn to_u8(&self) -> u8 { let ch = match self { Self::OrdinaryTable => 'r', Self::Index => 'i', Self::Sequence => 'S', Self::ToastTable => 't', Self::View => 'v', Self::MaterializedView => 'm', Self::CompositeType => 'c', Self::ForeignTable => 'f', Self::PartitionedTable => 'p', Self::PartitionedIndex => 'I', }; ch as u8 } }