use async_graphql::dynamic::indexmap::IndexMap;
use async_graphql::{Name, Value as GraphqlValue};
use super::error::GraphqlError;
use crate::dbs::Session;
use crate::expr::LogicalPlan;
use crate::kvs::Datastore;
use crate::val::Value as SqlValue;
pub(crate) trait GraphqlValueUtils {
fn as_i64(&self) -> Option<i64>;
fn as_string(&self) -> Option<String>;
fn as_list(&self) -> Option<&Vec<GraphqlValue>>;
fn as_object(&self) -> Option<&IndexMap<Name, GraphqlValue>>;
}
impl GraphqlValueUtils for GraphqlValue {
fn as_i64(&self) -> Option<i64> {
if let GraphqlValue::Number(n) = self {
n.as_i64()
} else {
None
}
}
fn as_string(&self) -> Option<String> {
if let GraphqlValue::String(s) = self {
Some(s.to_owned())
} else {
None
}
}
fn as_list(&self) -> Option<&Vec<GraphqlValue>> {
if let GraphqlValue::List(a) = self {
Some(a)
} else {
None
}
}
fn as_object(&self) -> Option<&IndexMap<Name, GraphqlValue>> {
if let GraphqlValue::Object(o) = self {
Some(o)
} else {
None
}
}
}
pub(crate) async fn execute_plan(
ds: &Datastore,
sess: &Session,
plan: LogicalPlan,
) -> Result<SqlValue, GraphqlError> {
let results = ds
.process_plan(plan, sess, None)
.await
.map_err(|e| GraphqlError::InternalError(format!("Failed to execute query plan: {}", e)))?;
let first_result = results
.into_iter()
.next()
.ok_or_else(|| GraphqlError::InternalError("No results returned from query".to_string()))?;
first_result
.result
.map(|v| v.into())
.map_err(|e| GraphqlError::InternalError(format!("Query execution failed: {}", e)))
}