phonograph/src/pg_classes.rs
Brent Schroeter ced7eced4a sqlx etc
2025-05-26 22:08:29 -07:00

111 lines
3.4 KiB
Rust

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<Vec<PgAclItem>>,
}
impl PgClass {
pub async fn fetch_all_by_kind_any<'a, I: IntoIterator<Item = PgRelKind>, E: PgExecutor<'a>>(
kinds: I,
client: E,
) -> Result<Vec<PgClass>, sqlx::Error> {
let kinds_i8 = kinds
.into_iter()
.map(|kind| kind.to_u8() as i8)
.collect::<Vec<i8>>();
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<PgAclItem>"
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
}
}