use nodedb_sql::parser::preprocess::lex::find_ascii_case_insensitive;
use serde_json::{Map, Value as JsonValue};
use crate::control::security::identity::AuthenticatedIdentity;
use crate::control::server::response_shape::types::ShapedRows;
use crate::control::state::SharedState;
use super::super::result::{DdlError, DdlResult};
fn err(sqlstate: &str, message: impl Into<String>) -> DdlError {
DdlError {
sqlstate: sqlstate.to_string(),
message: message.into(),
}
}
pub fn subscribe_to(
state: &SharedState,
_identity: &AuthenticatedIdentity,
sql: &str,
parts: &[&str],
) -> Result<Vec<DdlResult>, DdlError> {
let topic_name = parts.get(2).unwrap_or(&"").to_lowercase();
let since_seq: u64 = find_ascii_case_insensitive(sql, " SINCE ")
.and_then(|pos| sql[pos + 7..].split_whitespace().next())
.and_then(|s| s.parse().ok())
.unwrap_or(0);
let group_name = find_ascii_case_insensitive(sql, " GROUP ")
.map(|pos| sql[pos + 7..].split_whitespace().next().unwrap_or(""))
.filter(|g| !g.is_empty())
.map(|g| g.to_lowercase());
let (sub_id, _rx, backlog) = if let Some(ref group) = group_name {
state
.topic_registry
.subscribe_group(&topic_name, group, since_seq)
.map_err(|e| err("42P01", e.to_string()))?
} else {
state
.topic_registry
.subscribe(&topic_name, since_seq)
.map_err(|e| err("42P01", e.to_string()))?
};
let columns = vec![
"subscription_id".to_string(),
"topic".to_string(),
"group".to_string(),
"backlog".to_string(),
];
let mut row = Map::new();
row.insert(
"subscription_id".to_string(),
JsonValue::String(sub_id.to_string()),
);
row.insert("topic".to_string(), JsonValue::String(topic_name));
row.insert(
"group".to_string(),
JsonValue::String(group_name.as_deref().unwrap_or("-").to_string()),
);
row.insert(
"backlog".to_string(),
JsonValue::String(backlog.len().to_string()),
);
let column_types = ShapedRows::text_types(columns.len());
Ok(vec![DdlResult::Rows(ShapedRows {
columns,
column_types,
rows: vec![row],
notice: None,
})])
}