use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::dbs::Workable;
use crate::err::Error;
use crate::iam::Action;
use crate::iam::ResourceKind;
use crate::idx::docids::DocId;
use crate::idx::planner::executor::IteratorRef;
use crate::statements::define::DefineEventStatement;
use crate::statements::define::DefineFieldStatement;
use crate::statements::define::DefineIndexStatement;
use crate::statements::define::DefineTableStatement;
use crate::statements::live::LiveStatement;
use crate::thing::Thing;
use crate::value::Value;
use crate::Base;
use std::borrow::Cow;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
pub(crate) struct Document<'a> {
pub(super) id: Option<&'a Thing>,
pub(super) extras: Workable,
pub(super) initial: CursorDoc<'a>,
pub(super) current: CursorDoc<'a>,
}
pub struct CursorDoc<'a> {
pub(crate) ir: Option<IteratorRef>,
pub(crate) rid: Option<&'a Thing>,
pub(crate) doc: Cow<'a, Value>,
pub(crate) doc_id: Option<DocId>,
}
impl<'a> CursorDoc<'a> {
pub(crate) fn new(
ir: Option<IteratorRef>,
rid: Option<&'a Thing>,
doc_id: Option<DocId>,
doc: &'a Value,
) -> Self {
Self {
ir,
rid,
doc: Cow::Borrowed(doc),
doc_id,
}
}
}
impl<'a> From<&'a Value> for CursorDoc<'a> {
fn from(doc: &'a Value) -> Self {
Self {
ir: None,
rid: None,
doc: Cow::Borrowed(doc),
doc_id: None,
}
}
}
impl<'a> From<&'a mut Value> for CursorDoc<'a> {
fn from(doc: &'a mut Value) -> Self {
Self {
ir: None,
rid: None,
doc: Cow::Borrowed(doc),
doc_id: None,
}
}
}
impl<'a> Debug for Document<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Document - id: <{:?}>", self.id)
}
}
impl<'a> From<&Document<'a>> for Vec<u8> {
fn from(val: &Document<'a>) -> Vec<u8> {
val.current.doc.as_ref().into()
}
}
impl<'a> Document<'a> {
pub fn new(
ir: Option<IteratorRef>,
id: Option<&'a Thing>,
doc_id: Option<DocId>,
val: &'a Value,
extras: Workable,
) -> Self {
Document {
id,
extras,
current: CursorDoc::new(ir, id, doc_id, val),
initial: CursorDoc::new(ir, id, doc_id, val),
}
}
}
impl<'a> Document<'a> {
pub fn changed(&self) -> bool {
self.initial.doc != self.current.doc
}
pub fn is_new(&self) -> bool {
self.initial.doc.is_none()
}
pub async fn tb(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<DefineTableStatement>, Error> {
let run = txn.clone();
let mut run = run.lock().await;
let rid = self.id.as_ref().unwrap();
let tb = run.get_and_cache_tb(opt.ns(), opt.db(), &rid.tb).await;
match tb {
Err(Error::TbNotFound {
value: _,
}) => {
opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;
run.add_and_cache_ns(opt.ns(), opt.strict).await?;
run.add_and_cache_db(opt.ns(), opt.db(), opt.strict).await?;
run.add_and_cache_tb(opt.ns(), opt.db(), &rid.tb, opt.strict).await
}
Err(err) => Err(err),
Ok(tb) => Ok(tb),
}
}
pub async fn ft(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineTableStatement]>, Error> {
let id = self.id.as_ref().unwrap();
txn.clone().lock().await.all_tb_views(opt.ns(), opt.db(), &id.tb).await
}
pub async fn ev(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineEventStatement]>, Error> {
let id = self.id.as_ref().unwrap();
txn.clone().lock().await.all_tb_events(opt.ns(), opt.db(), &id.tb).await
}
pub async fn fd(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineFieldStatement]>, Error> {
let id = self.id.as_ref().unwrap();
txn.clone().lock().await.all_tb_fields(opt.ns(), opt.db(), &id.tb).await
}
pub async fn ix(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[DefineIndexStatement]>, Error> {
let id = self.id.as_ref().unwrap();
txn.clone().lock().await.all_tb_indexes(opt.ns(), opt.db(), &id.tb).await
}
pub async fn lv(
&self,
opt: &Options,
txn: &Transaction,
) -> Result<Arc<[LiveStatement]>, Error> {
let id = self.id.as_ref().unwrap();
txn.clone().lock().await.all_tb_lives(opt.ns(), opt.db(), &id.tb).await
}
}