use serde::Serialize;
use sqlx::PgPool;
#[derive(Debug, Clone, Serialize)]
pub struct JsonbColumn {
pub schema: String,
pub table: String,
pub column: String,
pub estimated_rows: Option<i64>,
}
impl JsonbColumn {
pub fn full_name(&self) -> String {
format!("{}.{}.{}", self.schema, self.table, self.column)
}
}
pub async fn discover_jsonb_columns(pool: &PgPool) -> Result<Vec<JsonbColumn>, sqlx::Error> {
let columns = sqlx::query_as::<_, (String, String, String, Option<i64>)>(
r#"
SELECT
c.table_schema,
c.table_name,
c.column_name,
s.n_live_tup as estimated_rows
FROM information_schema.columns c
LEFT JOIN pg_stat_user_tables s
ON s.schemaname = c.table_schema
AND s.relname = c.table_name
WHERE c.data_type = 'jsonb'
AND c.table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY c.table_schema, c.table_name, c.column_name
"#,
)
.fetch_all(pool)
.await?
.into_iter()
.map(|(schema, table, column, estimated_rows)| JsonbColumn {
schema,
table,
column,
estimated_rows,
})
.collect();
Ok(columns)
}
pub async fn get_row_count(pool: &PgPool, schema: &str, table: &str) -> Result<i64, sqlx::Error> {
let count: i64 = sqlx::query_scalar(&format!(
"SELECT COUNT(*) FROM {}.{}",
quote_identifier(schema),
quote_identifier(table)
))
.fetch_one(pool)
.await?;
Ok(count)
}
fn quote_identifier(identifier: &str) -> String {
format!("\"{}\"", identifier.replace("\"", "\"\""))
}