use nodedb_types::columnar::DocumentMode;
use nodedb_types::{CollectionType, Value};
use crate::control::security::catalog::StoredCollection;
pub(crate) enum TargetPk {
AutoRowId,
Field(String),
}
pub(crate) fn resolve_target_pk(
target: &StoredCollection,
op_label: &str,
) -> crate::Result<TargetPk> {
match &target.collection_type {
CollectionType::Document(DocumentMode::Strict(schema)) => {
match schema.columns.iter().find(|c| c.primary_key) {
Some(col) if col.name == "_rowid" => Ok(TargetPk::AutoRowId),
Some(col) => Ok(TargetPk::Field(col.name.clone())),
None => Ok(TargetPk::AutoRowId),
}
}
CollectionType::Document(DocumentMode::Schemaless) => Ok(TargetPk::Field(
target
.declared_primary_key
.clone()
.unwrap_or_else(|| "id".to_string()),
)),
CollectionType::KeyValue(_) | CollectionType::Columnar(_) => Err(crate::Error::PlanError {
detail: format!(
"{op_label} target '{}' must be a document collection",
target.name
),
}),
}
}
pub(super) fn extract_pk_value(body: &[u8], field: &str) -> Option<String> {
let Value::Object(obj) = nodedb_types::value_from_msgpack(body).ok()? else {
return None;
};
value_to_pk_string(obj.get(field)?)
}
fn value_to_pk_string(v: &Value) -> Option<String> {
match v {
Value::String(s) => Some(s.clone()),
Value::Integer(n) => Some(n.to_string()),
Value::Float(f) => Some(f.to_string()),
Value::Bool(b) => Some(b.to_string()),
Value::Decimal(d) => Some(d.to_string()),
_ => None,
}
}