use std::env;
use surreal_client::SurrealConnection;
use vantage_core::Context;
use vantage_expressions::ExprDataSource;
use vantage_surrealdb::{
identifier::Identifier, surreal_expr, surrealdb::SurrealDB, types::AnySurrealType,
};
async fn setup_db() -> vantage_core::Result<SurrealDB> {
let client = SurrealConnection::new()
.url("cbor://localhost:8000/rpc")
.namespace("example")
.database("test")
.auth_root("root", "root")
.connect()
.await
.context("Failed to connect to SurrealDB")?;
Ok(SurrealDB::new(client))
}
async fn setup_table(db: &SurrealDB) -> vantage_core::Result<()> {
let _ = db.execute(&surreal_expr!("DELETE demo_user")).await;
db.execute(&surreal_expr!(
"CREATE demo_user:1 SET name = {}, is_vip = {}, age = {}",
"Alice",
true,
25
))
.await?;
Ok(())
}
async fn execute_field_query(
db: &SurrealDB,
field_name: &str,
) -> vantage_core::Result<AnySurrealType> {
let field_id = Identifier::new(field_name);
let expr = surreal_expr!("SELECT VALUE {} FROM ONLY demo_user:1", (field_id));
let result = db.execute(&expr).await?;
Ok(result)
}
async fn query_field(db: &SurrealDB, field_name: &str) -> vantage_core::Result<()> {
use vantage_core::{Context, error};
let result = execute_field_query(db, field_name)
.await
.with_context(|| error!("Failed to access field", field = field_name))?;
handle_result_value(field_name, result)
.with_context(|| error!("Failed to handle field result", field = field_name))?;
Ok(())
}
fn handle_result_value(field_name: &str, value: AnySurrealType) -> vantage_core::Result<()> {
use vantage_core::error;
use vantage_surrealdb::types::SurrealTypeVariants;
println!("Field '{}' found:", field_name);
match value.type_variant() {
Some(SurrealTypeVariants::String) => {
if let Some(string_val) = value.try_get::<String>() {
println!(" Type: String");
println!(" Value: \"{}\"", string_val);
}
}
Some(SurrealTypeVariants::Bool) => {
if let Some(bool_val) = value.try_get::<bool>() {
println!(" Type: Boolean");
println!(" Value: {}", bool_val);
}
}
Some(SurrealTypeVariants::Int) => {
if let Some(int_val) = value.try_get::<i64>() {
println!(" Type: Integer");
println!(" Value: {}", int_val);
}
}
Some(SurrealTypeVariants::Float) => {
if let Some(float_val) = value.try_get::<f64>() {
println!(" Type: Float");
println!(" Value: {}", float_val);
}
}
Some(other) => {
return Err(error!(
"Unsupported field type",
field = field_name,
type_variant = format!("{:?}", other),
value = format!("{:?}", value.value())
));
}
None => {
return Err(error!(
"Field not found or has null value",
field = field_name,
value = format!("{:?}", value.value())
));
}
}
Ok(())
}
#[tokio::main]
async fn main() {
let args: Vec<String> = env::args().collect();
let result = async {
if args.len() != 2 {
return Err(vantage_core::error!(
"Invalid arguments",
usage = format!("Usage: {} <field_name>", args[0]),
available_fields = "name, is_vip, age"
));
}
let field_name = &args[1];
println!("🚀 Querying field: {}", field_name);
let db = setup_db().await?;
setup_table(&db).await?;
query_field(&db, field_name).await?;
let _ = db.execute(&surreal_expr!("DELETE demo_user")).await;
Ok(())
}
.await;
if let Err(e) = result {
use std::process::Termination;
e.report();
}
}