use crate::velesql::IntrospectionStatement;
use crate::{Error, Result, SearchResult};
use super::Database;
impl Database {
pub(super) fn execute_introspection(
&self,
stmt: &IntrospectionStatement,
) -> Result<Vec<SearchResult>> {
match stmt {
IntrospectionStatement::ShowCollections => self.execute_show_collections(),
IntrospectionStatement::DescribeCollection(desc) => {
self.execute_describe_collection(&desc.name)
}
IntrospectionStatement::Explain(inner_query) => {
self.execute_explain_introspection(inner_query)
}
}
}
#[allow(clippy::unnecessary_wraps)]
fn execute_show_collections(&self) -> Result<Vec<SearchResult>> {
let names = self.list_collections();
let results = names
.into_iter()
.enumerate()
.map(|(idx, name)| {
let coll_type = self.resolve_collection_type(&name).unwrap_or("unknown");
build_show_result(idx, &name, coll_type)
})
.collect();
Ok(results)
}
#[allow(deprecated)] fn resolve_collection_type(&self, name: &str) -> Option<&'static str> {
if self.get_graph_collection(name).is_some() {
return Some("graph");
}
if self.get_metadata_collection(name).is_some() {
return Some("metadata");
}
if self.get_vector_collection(name).is_some() || self.get_collection(name).is_some() {
return Some("vector");
}
None
}
fn execute_describe_collection(&self, name: &str) -> Result<Vec<SearchResult>> {
let coll_type = self
.resolve_collection_type(name)
.ok_or_else(|| Error::CollectionNotFound(name.to_string()))?;
let payload = build_describe_payload(self, name, coll_type);
let result = SearchResult::new(crate::Point::metadata_only(0, payload), 0.0);
Ok(vec![result])
}
fn execute_explain_introspection(
&self,
inner_query: &crate::velesql::Query,
) -> Result<Vec<SearchResult>> {
let plan = self.explain_query(inner_query)?;
let plan_json = serde_json::to_value(&plan)
.unwrap_or_else(|_| serde_json::json!({"error": "failed to serialize plan"}));
let mut payload = serde_json::Map::new();
payload.insert("plan".to_string(), plan_json);
payload.insert(
"tree".to_string(),
serde_json::Value::String(plan.to_tree()),
);
let result = SearchResult::new(
crate::Point::metadata_only(0, serde_json::Value::Object(payload)),
0.0,
);
Ok(vec![result])
}
}
fn build_show_result(idx: usize, name: &str, coll_type: &str) -> SearchResult {
let mut payload = serde_json::Map::new();
payload.insert("name".to_string(), serde_json::json!(name));
payload.insert("type".to_string(), serde_json::json!(coll_type));
#[allow(clippy::cast_possible_truncation)]
let id = idx as u64;
SearchResult::new(
crate::Point::metadata_only(id, serde_json::Value::Object(payload)),
0.0,
)
}
fn build_describe_payload(db: &Database, name: &str, coll_type: &str) -> serde_json::Value {
let mut payload = serde_json::Map::new();
payload.insert("name".to_string(), serde_json::json!(name));
payload.insert("type".to_string(), serde_json::json!(coll_type));
add_type_specific_metadata(db, name, coll_type, &mut payload);
serde_json::Value::Object(payload)
}
#[allow(deprecated)] fn add_type_specific_metadata(
db: &Database,
name: &str,
coll_type: &str,
payload: &mut serde_json::Map<String, serde_json::Value>,
) {
match coll_type {
"vector" => add_vector_metadata(db, name, payload),
"graph" => add_graph_metadata(db, name, payload),
"metadata" => add_metadata_metadata(db, name, payload),
_ => {}
}
}
#[allow(deprecated)]
fn add_vector_metadata(
db: &Database,
name: &str,
payload: &mut serde_json::Map<String, serde_json::Value>,
) {
if let Some(vc) = db.get_vector_collection(name) {
payload.insert("dimension".to_string(), serde_json::json!(vc.dimension()));
payload.insert(
"metric".to_string(),
serde_json::json!(format!("{:?}", vc.metric())),
);
payload.insert("point_count".to_string(), serde_json::json!(vc.len()));
} else if let Some(coll) = db.get_collection(name) {
let cfg = coll.config();
payload.insert("dimension".to_string(), serde_json::json!(cfg.dimension));
payload.insert(
"metric".to_string(),
serde_json::json!(format!("{:?}", cfg.metric)),
);
payload.insert("point_count".to_string(), serde_json::json!(coll.len()));
}
}
fn add_graph_metadata(
db: &Database,
name: &str,
payload: &mut serde_json::Map<String, serde_json::Value>,
) {
if let Some(gc) = db.get_graph_collection(name) {
payload.insert("point_count".to_string(), serde_json::json!(gc.len()));
}
}
fn add_metadata_metadata(
db: &Database,
name: &str,
payload: &mut serde_json::Map<String, serde_json::Value>,
) {
if let Some(mc) = db.get_metadata_collection(name) {
payload.insert("point_count".to_string(), serde_json::json!(mc.len()));
}
}