use crate::catalog::TviewMeta;
use crate::queue::key::KeyValue;
use crate::jsonb_delta::jsonb_delta_schema;
use crate::utils::{ident, qualified_relname_from_oid};
pub fn refresh_key(meta: &TviewMeta, key: &KeyValue) -> crate::TViewResult<super::Touched> {
let keys = std::slice::from_ref(key);
let locked = super::lock_rows(
meta,
&qualified_relname_from_oid(meta.tview_oid)?,
keys,
!meta.identity.is_pk(&meta.entity_name),
)?;
let key_type = meta.key_type()?;
super::refuse_duplicate_keys(
meta,
&format!(
"{} = {}",
ident::quoted(&meta.identity.column),
super::key_cast(&key_type, "$1", false)
),
&[super::key_scalar(&key_type, key)?],
)?;
crate::metrics::metrics_api::record_view_recomputes(&meta.entity_name, 1);
let produced = write_row(meta, key, locked.old.as_ref())?;
let deleted = if produced.keys.is_empty() {
delete_tview_row(meta, key)?
} else {
Vec::new()
};
Ok(super::touched(
meta,
keys,
locked.pks,
produced.written,
deleted,
))
}
fn delete_tview_row(meta: &TviewMeta, key: &KeyValue) -> crate::TViewResult<Vec<i64>> {
let key_type = meta.key_type()?;
let qi_tv = qualified_relname_from_oid(meta.tview_oid)?;
let qi_key = ident::quoted(&meta.identity.column);
let qi_pk = ident::quoted(&format!("pk_{}", meta.entity_name));
let sql = format!(
"DELETE FROM {qi_tv} WHERE {qi_key} = {} \
RETURNING {qi_pk}::pg_catalog.int8, {}",
super::key_cast(&key_type, "$1", false),
meta.returned(&qi_tv, false)
);
super::run_journaled_delete(meta, &sql, &[super::key_scalar(&key_type, key)?])
}
fn write_row(
meta: &TviewMeta,
key: &KeyValue,
old: Option<&crate::catalog::collections::OldKeys>,
) -> crate::TViewResult<super::Produced> {
if jsonb_delta_schema().is_none() {
crate::utils::log_once(
crate::jsonb_delta::JSONB_DELTA_MISSING,
"jsonb_delta is not installed: writes recompute TVIEW rows instead of patching \
them in place. CREATE EXTENSION jsonb_delta to enable the direct and fan-out \
patches.",
);
}
let key_type = meta.key_type()?;
let qi_tv = qualified_relname_from_oid(meta.tview_oid)?;
let key_col = &meta.identity.column;
let qi_key = ident::quoted(key_col);
let qi_view = qualified_relname_from_oid(meta.view_oid)?;
let col_names = crate::utils::get_view_columns_by_oid(meta.view_oid)?;
let col_list = super::column_list(&col_names);
super::run_counted_upsert(
meta,
&qi_tv,
&col_list,
&format!(
"SELECT {col_list} FROM {qi_view} WHERE {qi_key} = {}",
super::key_cast(&key_type, "$1", false)
),
&format!(
"ON CONFLICT ({qi_key}) {}",
super::upsert_conflict_action(&qi_tv, &col_names, key_col)
),
&[super::key_scalar(&key_type, key)?],
old,
)
}