elefant-tools 0.0.2

A library for doing things like pg_dump and pg_restore, with extra features, and probably more bugs.
Documentation
use super::define_working_query;
use crate::postgres_client_wrapper::{FromPgChar, FromRow, RowEnumExt};
use crate::{ElefantToolsError, TablePartitionStrategy};
use tokio_postgres::Row;

#[derive(Debug, Eq, PartialEq)]
pub struct TablesResult {
    pub schema_name: String,
    pub table_name: String,
    pub comment: Option<String>,
    pub table_type: TableType,
    pub partition_expression: Option<String>,
    pub partition_strategy: Option<TablePartitionStrategy>,
    pub default_partition_name: Option<String>,
    pub partition_column_indices: Option<Vec<i16>>,
    pub partition_expression_columns: Option<String>,
    pub parent_tables: Option<Vec<String>>,
    pub is_partition: bool,
    pub storage_parameters: Option<Vec<String>>,
    pub oid: i64,
    pub depends_on: Option<Vec<i64>>,
    pub type_oid: i64,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
pub enum TableType {
    #[default]
    Table,
    PartitionedTable,
}

impl FromPgChar for TableType {
    fn from_pg_char(c: char) -> Result<Self, ElefantToolsError> {
        match c {
            'r' => Ok(TableType::Table),
            'p' => Ok(TableType::PartitionedTable),
            _ => Err(ElefantToolsError::InvalidTableType(c.to_string())),
        }
    }
}

impl FromRow for TablesResult {
    fn from_row(row: Row) -> crate::Result<Self> {
        Ok(TablesResult {
            schema_name: row.try_get(0)?,
            table_name: row.try_get(1)?,
            comment: row.try_get(2)?,
            table_type: row.try_get_enum_value(3)?,
            partition_expression: row.try_get(4)?,
            partition_strategy: row.try_get_opt_enum_value(5)?,
            default_partition_name: row.try_get(6)?,
            partition_column_indices: row.try_get(7)?,
            partition_expression_columns: row.try_get(8)?,
            parent_tables: row.try_get(9)?,
            is_partition: row.try_get(10)?,
            storage_parameters: row.try_get(11)?,
            oid: row.try_get(12)?,
            depends_on: row.try_get(13)?,
            type_oid: row.try_get(14)?,
        })
    }
}

//language=postgresql
define_working_query!(
    get_tables,
    TablesResult,
    r#"
select
    ns.nspname,
    cl.relname,
    des.description,
    cl.relkind,
    pg_get_expr(cl.relpartbound, cl.oid) as partition_expression,
    pt.partstrat,
    default_partition.relname as default_partition,
    pt.partattrs,
    pg_get_expr(pt.partexprs, pt.partrelid) as partexprs,
    (select array_agg(parent.relname) from (select parent.relname from pg_inherits i
        join pg_class parent on i.inhparent = parent.oid
          where i.inhrelid = cl.oid
          order by i.inhseqno) parent) as parent_table,
    cl.relispartition,
    cl.reloptions,
   cl.oid::int8,
   (select array_agg(refobjid::int8) from pg_depend dep where cl.oid = dep.objid and dep.deptype <> 'e' and dep.refobjid > 16384 and dep.objid <> dep.refobjid) as depends_on,
   cl.reltype::int8
from pg_class cl
         join pg_catalog.pg_namespace ns on ns.oid = cl.relnamespace
         left join pg_description des on des.objoid = cl.oid and des.objsubid = 0
         left join pg_partitioned_table pt on pt.partrelid = cl.oid
         left join pg_class default_partition on default_partition.oid = pt.partdefid
         left join pg_depend dep on dep.objid = ns.oid
where cl.relkind in ('r', 'p')
  and cl.oid > 16384
  and (dep.objid is null or dep.deptype <> 'e' )
    and has_table_privilege(cl.oid, 'SELECT, INSERT, UPDATE')
order by ns.nspname, cl.relname;
"#
);