use sqlx::Row;
pub(crate) fn collection_name(resource_name: &str, index_name: &str) -> String {
if resource_name.trim().is_empty() {
index_name.to_string()
} else {
resource_name.to_string()
}
}
pub(crate) struct StoredIndex {
pub(crate) index_id: String,
pub(crate) index_name: String,
pub(crate) source_message_type: String,
pub(crate) backend: String,
pub(crate) resource_name: String,
pub(crate) vector_dims: i32,
pub(crate) tenant_column: String,
pub(crate) source_cdc_topic: String,
pub(crate) status: String,
}
impl StoredIndex {
pub(crate) fn collection(&self) -> String {
collection_name(&self.resource_name, &self.index_name)
}
}
fn index_json_object(row: &serde_json::Value) -> &serde_json::Map<String, serde_json::Value> {
row.get("n")
.and_then(serde_json::Value::as_object)
.or_else(|| row.as_object())
.unwrap_or_else(|| {
static EMPTY: std::sync::OnceLock<serde_json::Map<String, serde_json::Value>> =
std::sync::OnceLock::new();
EMPTY.get_or_init(serde_json::Map::new)
})
}
pub(crate) fn json_str(row: &serde_json::Map<String, serde_json::Value>, key: &str) -> String {
match row.get(key) {
Some(serde_json::Value::String(value)) => value.clone(),
Some(serde_json::Value::Number(value)) => value.to_string(),
Some(serde_json::Value::Bool(value)) => value.to_string(),
_ => String::new(),
}
}
fn json_i32(row: &serde_json::Map<String, serde_json::Value>, key: &str) -> i32 {
match row.get(key) {
Some(serde_json::Value::Number(value)) => value.as_i64().unwrap_or(0) as i32,
Some(serde_json::Value::String(value)) => value.trim().parse::<i32>().unwrap_or(0),
_ => 0,
}
}
pub(crate) fn stored_index_from_json(row: &serde_json::Value) -> StoredIndex {
let map = index_json_object(row);
StoredIndex {
index_id: json_str(map, "index_id"),
index_name: json_str(map, "index_name"),
source_message_type: json_str(map, "source_message_type"),
backend: json_str(map, "backend"),
resource_name: json_str(map, "resource_name"),
vector_dims: json_i32(map, "vector_dims"),
tenant_column: json_str(map, "tenant_column"),
source_cdc_topic: json_str(map, "source_cdc_topic"),
status: json_str(map, "status"),
}
}
pub(crate) fn stored_index_from_pg_row(row: &sqlx::postgres::PgRow) -> Result<StoredIndex, String> {
Ok(StoredIndex {
index_id: row
.try_get("index_id")
.map_err(|err| format!("decode search index id failed: {err}"))?,
index_name: row
.try_get("index_name")
.map_err(|err| format!("decode search index name failed: {err}"))?,
source_message_type: row
.try_get("source_message_type")
.map_err(|err| format!("decode search source message type failed: {err}"))?,
backend: row
.try_get("backend")
.map_err(|err| format!("decode search index backend failed: {err}"))?,
resource_name: row
.try_get("resource_name")
.map_err(|err| format!("decode search resource name failed: {err}"))?,
vector_dims: row
.try_get("vector_dims")
.map_err(|err| format!("decode search vector dims failed: {err}"))?,
tenant_column: row
.try_get("tenant_column")
.map_err(|err| format!("decode search tenant column failed: {err}"))?,
source_cdc_topic: row
.try_get("source_cdc_topic")
.map_err(|err| format!("decode search source cdc topic failed: {err}"))?,
status: row
.try_get("status")
.map_err(|err| format!("decode search index status failed: {err}"))?,
})
}