use anyhow::Result;
use reblessive::tree::Stk;
use crate::ctx::FrozenContext;
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::expr::FlowResultExt as _;
use crate::expr::paths::ID;
use crate::val::{RecordId, Value};
pub async fn exists(
(stk, ctx, opt, doc): (&mut Stk, &FrozenContext, Option<&Options>, Option<&CursorDoc>),
(arg,): (RecordId,),
) -> Result<Value> {
if let Some(opt) = opt {
let v = match Value::RecordId(arg).get(stk, ctx, opt, doc, ID.as_ref()).await.catch_return()
{
Ok(v) => v,
Err(e) if matches!(e.downcast_ref(), Some(Error::TbNotFound { .. })) => {
return Ok(Value::Bool(false));
}
Err(e) => return Err(e),
};
Ok(Value::Bool(!v.is_none()))
} else {
Ok(Value::None)
}
}
pub fn id((arg,): (RecordId,)) -> Result<Value> {
Ok(arg.key.into_value())
}
pub fn tb((arg,): (RecordId,)) -> Result<Value> {
Ok(Value::String(arg.table.into()))
}
pub mod is {
use anyhow::Result;
use reblessive::tree::Stk;
use crate::catalog::providers::TableProvider;
use crate::ctx::FrozenContext;
use crate::dbs::Options;
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::expr::Base;
use crate::iam::{Action, ResourceKind};
use crate::val::value::Cast;
use crate::val::{RecordId, Value};
pub async fn edge(
(_stk, ctx, opt, doc): (&mut Stk, &FrozenContext, Option<&Options>, Option<&CursorDoc>),
(arg,): (Value,),
) -> Result<Value> {
match opt {
Some(opt) => {
let rid = RecordId::cast(arg).map_err(|_| Error::InvalidFunctionArguments {
name: "record::is_edge".to_owned(),
message: "Expected a record ID".to_owned(),
})?;
if let Some(doc) = doc
&& doc.rid.as_ref().is_some_and(|x| x.as_ref() == &rid)
{
return Ok(Value::Bool(doc.doc.is_edge()));
}
opt.valid_for_db()?;
ctx.is_allowed(opt, Action::View, ResourceKind::Record, Base::Db)?;
let (ns, db) = ctx.expect_ns_db_ids(opt).await?;
let txn = ctx.tx();
let record = txn.get_record(ns, db, &rid.table, &rid.key, opt.version).await?;
Ok(Value::Bool(record.is_edge()))
}
None => Ok(Value::None),
}
}
}