Implement INSERT and RELATE statements
This commit is contained in:
parent
b37b027b60
commit
01d21e1157
24 changed files with 741 additions and 517 deletions
|
@ -1,204 +1,121 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
|
use crate::dbs::Operable;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::key::thing;
|
use crate::key::thing;
|
||||||
use crate::sql::array::Array;
|
|
||||||
use crate::sql::id::Id;
|
|
||||||
use crate::sql::model::Model;
|
|
||||||
use crate::sql::object::Object;
|
|
||||||
use crate::sql::table::Table;
|
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use async_recursion::async_recursion;
|
|
||||||
use channel::Sender;
|
use channel::Sender;
|
||||||
|
|
||||||
impl Value {
|
impl Iterable {
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
|
||||||
pub(crate) async fn channel(
|
pub(crate) async fn channel(
|
||||||
self,
|
self,
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
opt: &Options,
|
opt: &Options,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
chn: Sender<(Option<Thing>, Value)>,
|
chn: Sender<(Option<Thing>, Operable)>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if ctx.is_ok() {
|
if ctx.is_ok() {
|
||||||
match self {
|
match self {
|
||||||
Value::Object(v) => v.process(ctx, opt, txn, stm, &chn).await?,
|
Iterable::Value(v) => {
|
||||||
Value::Array(v) => v.process(ctx, opt, txn, stm, &chn).await?,
|
// Pass the value through
|
||||||
Value::Model(v) => v.process(ctx, opt, txn, stm, &chn).await?,
|
let val = Operable::Value(v);
|
||||||
Value::Thing(v) => v.process(ctx, opt, txn, stm, &chn).await?,
|
// Process the document record
|
||||||
Value::Table(v) => v.process(ctx, opt, txn, stm, &chn).await?,
|
chn.send((None, val)).await?;
|
||||||
v => chn.send((None, v)).await?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Array {
|
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
|
||||||
pub(crate) async fn process(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
chn: &Sender<(Option<Thing>, Value)>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
for v in self {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
match v {
|
|
||||||
Value::Object(v) => v.process(ctx, opt, txn, stm, chn).await?,
|
|
||||||
Value::Array(v) => v.process(ctx, opt, txn, stm, chn).await?,
|
|
||||||
Value::Model(v) => v.process(ctx, opt, txn, stm, chn).await?,
|
|
||||||
Value::Thing(v) => v.process(ctx, opt, txn, stm, chn).await?,
|
|
||||||
Value::Table(v) => v.process(ctx, opt, txn, stm, chn).await?,
|
|
||||||
v => chn.send((None, v)).await?,
|
|
||||||
}
|
}
|
||||||
}
|
Iterable::Thing(v) => {
|
||||||
}
|
// Fetch the data from the store
|
||||||
Ok(())
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
}
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
}
|
// Parse the data from the store
|
||||||
|
let val = Operable::Value(match val {
|
||||||
impl Object {
|
Some(v) => Value::from(v),
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
None => Value::None,
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
});
|
||||||
pub(crate) async fn process(
|
// Process the document record
|
||||||
self,
|
chn.send((Some(v), val)).await?;
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
chn: &Sender<(Option<Thing>, Value)>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
if let Some(Value::Thing(id)) = self.get("id") {
|
|
||||||
id.clone().process(ctx, opt, txn, stm, chn).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Model {
|
|
||||||
pub(crate) async fn process(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
chn: &Sender<(Option<Thing>, Value)>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
match self {
|
|
||||||
Model::Count(tb, c) => {
|
|
||||||
for _ in 0..c {
|
|
||||||
Thing {
|
|
||||||
tb: tb.to_string(),
|
|
||||||
id: Id::rand(),
|
|
||||||
}
|
|
||||||
.process(ctx, opt, txn, stm, chn)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Model::Range(tb, b, e) => {
|
Iterable::Table(v) => {
|
||||||
for x in b..=e {
|
let beg = thing::prefix(opt.ns(), opt.db(), &v);
|
||||||
Thing {
|
let end = thing::suffix(opt.ns(), opt.db(), &v);
|
||||||
tb: tb.to_string(),
|
let mut nxt: Option<Vec<u8>> = None;
|
||||||
id: Id::from(x),
|
loop {
|
||||||
}
|
if ctx.is_ok() {
|
||||||
.process(ctx, opt, txn, stm, chn)
|
let res = match nxt {
|
||||||
.await?;
|
None => {
|
||||||
}
|
let min = beg.clone();
|
||||||
}
|
let max = end.clone();
|
||||||
}
|
txn.clone().lock().await.scan(min..max, 1000).await?
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Thing {
|
|
||||||
pub(crate) async fn process(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
_stm: &Statement<'_>,
|
|
||||||
chn: &Sender<(Option<Thing>, Value)>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let key = thing::new(opt.ns(), opt.db(), &self.tb, &self.id);
|
|
||||||
let val = txn.clone().lock().await.get(key).await?;
|
|
||||||
let val = match val {
|
|
||||||
Some(v) => Value::from(v),
|
|
||||||
None => Value::None,
|
|
||||||
};
|
|
||||||
chn.send((Some(self), val)).await?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Table {
|
|
||||||
pub(crate) async fn process(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
_stm: &Statement<'_>,
|
|
||||||
chn: &Sender<(Option<Thing>, Value)>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let beg = thing::prefix(opt.ns(), opt.db(), &self);
|
|
||||||
let end = thing::suffix(opt.ns(), opt.db(), &self);
|
|
||||||
let mut nxt: Option<Vec<u8>> = None;
|
|
||||||
loop {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let res = match nxt {
|
|
||||||
None => {
|
|
||||||
let min = beg.clone();
|
|
||||||
let max = end.clone();
|
|
||||||
txn.clone().lock().await.scan(min..max, 1000).await?
|
|
||||||
}
|
|
||||||
Some(ref mut beg) => {
|
|
||||||
beg.push(0x00);
|
|
||||||
let min = beg.clone();
|
|
||||||
let max = end.clone();
|
|
||||||
txn.clone().lock().await.scan(min..max, 1000).await?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !res.is_empty() {
|
|
||||||
// Get total results
|
|
||||||
let n = res.len();
|
|
||||||
// Exit when settled
|
|
||||||
if n == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Loop over results
|
|
||||||
for (i, (k, v)) in res.into_iter().enumerate() {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
// Ready the next
|
|
||||||
if n == i + 1 {
|
|
||||||
nxt = Some(k.clone());
|
|
||||||
}
|
}
|
||||||
// Parse the key-value
|
Some(ref mut beg) => {
|
||||||
let k: crate::key::thing::Thing = (&k).into();
|
beg.push(0x00);
|
||||||
let v: crate::sql::value::Value = (&v).into();
|
let min = beg.clone();
|
||||||
let t = Thing::from((k.tb, k.id));
|
let max = end.clone();
|
||||||
// Process the record
|
txn.clone().lock().await.scan(min..max, 1000).await?
|
||||||
chn.send((Some(t), v)).await?;
|
}
|
||||||
|
};
|
||||||
|
if !res.is_empty() {
|
||||||
|
// Get total results
|
||||||
|
let n = res.len();
|
||||||
|
// Exit when settled
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Loop over results
|
||||||
|
for (i, (k, v)) in res.into_iter().enumerate() {
|
||||||
|
if ctx.is_ok() {
|
||||||
|
// Ready the next
|
||||||
|
if n == i + 1 {
|
||||||
|
nxt = Some(k.clone());
|
||||||
|
}
|
||||||
|
// Parse the data from the store
|
||||||
|
let key: crate::key::thing::Thing = (&k).into();
|
||||||
|
let val: crate::sql::value::Value = (&v).into();
|
||||||
|
let rid = Thing::from((key.tb, key.id));
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Value(val);
|
||||||
|
// Process the record
|
||||||
|
chn.send((Some(rid), val)).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
Iterable::Mergeable(v, o) => {
|
||||||
|
// Fetch the data from the store
|
||||||
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
|
// Parse the data from the store
|
||||||
|
let x = match val {
|
||||||
|
Some(v) => Value::from(v),
|
||||||
|
None => Value::None,
|
||||||
|
};
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Mergeable(x, o);
|
||||||
|
// Process the document record
|
||||||
|
chn.send((Some(v), val)).await?;
|
||||||
|
}
|
||||||
|
Iterable::Relatable(f, v, w) => {
|
||||||
|
// Fetch the data from the store
|
||||||
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
|
// Parse the data from the store
|
||||||
|
let x = match val {
|
||||||
|
Some(v) => Value::from(v),
|
||||||
|
None => Value::None,
|
||||||
|
};
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Relatable(f, x, w);
|
||||||
|
// Process the document record
|
||||||
|
chn.send((Some(v), val)).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
|
use crate::dbs::Operable;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::key::thing;
|
use crate::key::thing;
|
||||||
use crate::sql::array::Array;
|
|
||||||
use crate::sql::id::Id;
|
|
||||||
use crate::sql::model::Model;
|
|
||||||
use crate::sql::object::Object;
|
|
||||||
use crate::sql::table::Table;
|
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use async_recursion::async_recursion;
|
|
||||||
|
|
||||||
impl Value {
|
impl Iterable {
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
|
||||||
pub(crate) async fn iterate(
|
pub(crate) async fn iterate(
|
||||||
self,
|
self,
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
|
@ -27,178 +21,101 @@ impl Value {
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if ctx.is_ok() {
|
if ctx.is_ok() {
|
||||||
match self {
|
match self {
|
||||||
Value::Object(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
Iterable::Value(v) => {
|
||||||
Value::Array(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
// Pass the value through
|
||||||
Value::Model(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
let val = Operable::Value(v);
|
||||||
Value::Thing(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
// Process the document record
|
||||||
Value::Table(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
ite.process(ctx, opt, txn, stm, None, val).await;
|
||||||
v => ite.process(ctx, opt, txn, stm, None, v).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Array {
|
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
|
||||||
pub(crate) async fn iterate(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
ite: &mut Iterator,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
for v in self.into_iter() {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
match v {
|
|
||||||
Value::Object(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
|
||||||
Value::Array(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
|
||||||
Value::Model(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
|
||||||
Value::Thing(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
|
||||||
Value::Table(v) => v.iterate(ctx, opt, txn, stm, ite).await?,
|
|
||||||
v => ite.process(ctx, opt, txn, stm, None, v).await,
|
|
||||||
}
|
}
|
||||||
}
|
Iterable::Thing(v) => {
|
||||||
}
|
// Fetch the data from the store
|
||||||
Ok(())
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
}
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
}
|
// Parse the data from the store
|
||||||
|
let val = Operable::Value(match val {
|
||||||
impl Object {
|
Some(v) => Value::from(v),
|
||||||
#[cfg_attr(feature = "parallel", async_recursion)]
|
None => Value::None,
|
||||||
#[cfg_attr(not(feature = "parallel"), async_recursion(?Send))]
|
});
|
||||||
pub(crate) async fn iterate(
|
// Process the document record
|
||||||
self,
|
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
ite: &mut Iterator,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
if let Some(Value::Thing(id)) = self.get("id") {
|
|
||||||
id.clone().iterate(ctx, opt, txn, stm, ite).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Model {
|
|
||||||
pub(crate) async fn iterate(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
ite: &mut Iterator,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
match self {
|
|
||||||
Model::Count(tb, c) => {
|
|
||||||
for _ in 0..c {
|
|
||||||
Thing {
|
|
||||||
tb: tb.to_string(),
|
|
||||||
id: Id::rand(),
|
|
||||||
}
|
|
||||||
.iterate(ctx, opt, txn, stm, ite)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Model::Range(tb, b, e) => {
|
Iterable::Table(v) => {
|
||||||
for x in b..=e {
|
let beg = thing::prefix(opt.ns(), opt.db(), &v);
|
||||||
Thing {
|
let end = thing::suffix(opt.ns(), opt.db(), &v);
|
||||||
tb: tb.to_string(),
|
let mut nxt: Option<Vec<u8>> = None;
|
||||||
id: Id::from(x),
|
loop {
|
||||||
}
|
if ctx.is_ok() {
|
||||||
.iterate(ctx, opt, txn, stm, ite)
|
let res = match nxt {
|
||||||
.await?;
|
None => {
|
||||||
}
|
let min = beg.clone();
|
||||||
}
|
let max = end.clone();
|
||||||
}
|
txn.clone().lock().await.scan(min..max, 1000).await?
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Thing {
|
|
||||||
pub(crate) async fn iterate(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
ite: &mut Iterator,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let key = thing::new(opt.ns(), opt.db(), &self.tb, &self.id);
|
|
||||||
let val = txn.clone().lock().await.get(key).await?;
|
|
||||||
let val = match val {
|
|
||||||
Some(v) => Value::from(v),
|
|
||||||
None => Value::None,
|
|
||||||
};
|
|
||||||
ite.process(ctx, opt, txn, stm, Some(self), val).await;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Table {
|
|
||||||
pub(crate) async fn iterate(
|
|
||||||
self,
|
|
||||||
ctx: &Context<'_>,
|
|
||||||
opt: &Options,
|
|
||||||
txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
ite: &mut Iterator,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let beg = thing::prefix(opt.ns(), opt.db(), &self);
|
|
||||||
let end = thing::suffix(opt.ns(), opt.db(), &self);
|
|
||||||
let mut nxt: Option<Vec<u8>> = None;
|
|
||||||
loop {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
let res = match nxt {
|
|
||||||
None => {
|
|
||||||
let min = beg.clone();
|
|
||||||
let max = end.clone();
|
|
||||||
txn.clone().lock().await.scan(min..max, 1000).await?
|
|
||||||
}
|
|
||||||
Some(ref mut beg) => {
|
|
||||||
beg.push(0x00);
|
|
||||||
let min = beg.clone();
|
|
||||||
let max = end.clone();
|
|
||||||
txn.clone().lock().await.scan(min..max, 1000).await?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !res.is_empty() {
|
|
||||||
// Get total results
|
|
||||||
let n = res.len();
|
|
||||||
// Exit when settled
|
|
||||||
if n == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Loop over results
|
|
||||||
for (i, (k, v)) in res.into_iter().enumerate() {
|
|
||||||
if ctx.is_ok() {
|
|
||||||
// Ready the next
|
|
||||||
if n == i + 1 {
|
|
||||||
nxt = Some(k.clone());
|
|
||||||
}
|
}
|
||||||
// Parse the key-value
|
Some(ref mut beg) => {
|
||||||
let k: crate::key::thing::Thing = (&k).into();
|
beg.push(0x00);
|
||||||
let v: crate::sql::value::Value = (&v).into();
|
let min = beg.clone();
|
||||||
let t = Thing::from((k.tb, k.id));
|
let max = end.clone();
|
||||||
// Process the record
|
txn.clone().lock().await.scan(min..max, 1000).await?
|
||||||
ite.process(ctx, opt, txn, stm, Some(t), v).await;
|
}
|
||||||
|
};
|
||||||
|
if !res.is_empty() {
|
||||||
|
// Get total results
|
||||||
|
let n = res.len();
|
||||||
|
// Exit when settled
|
||||||
|
if n == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Loop over results
|
||||||
|
for (i, (k, v)) in res.into_iter().enumerate() {
|
||||||
|
if ctx.is_ok() {
|
||||||
|
// Ready the next
|
||||||
|
if n == i + 1 {
|
||||||
|
nxt = Some(k.clone());
|
||||||
|
}
|
||||||
|
// Parse the data from the store
|
||||||
|
let key: crate::key::thing::Thing = (&k).into();
|
||||||
|
let val: crate::sql::value::Value = (&v).into();
|
||||||
|
let rid = Thing::from((key.tb, key.id));
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Value(val);
|
||||||
|
// Process the record
|
||||||
|
ite.process(ctx, opt, txn, stm, Some(rid), val).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
Iterable::Mergeable(v, o) => {
|
||||||
|
// Fetch the data from the store
|
||||||
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
|
// Parse the data from the store
|
||||||
|
let x = match val {
|
||||||
|
Some(v) => Value::from(v),
|
||||||
|
None => Value::None,
|
||||||
|
};
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Mergeable(x, o);
|
||||||
|
// Process the document record
|
||||||
|
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||||
|
}
|
||||||
|
Iterable::Relatable(f, v, w) => {
|
||||||
|
// Fetch the data from the store
|
||||||
|
let key = thing::new(opt.ns(), opt.db(), &v.tb, &v.id);
|
||||||
|
let val = txn.clone().lock().await.get(key).await?;
|
||||||
|
// Parse the data from the store
|
||||||
|
let x = match val {
|
||||||
|
Some(v) => Value::from(v),
|
||||||
|
None => Value::None,
|
||||||
|
};
|
||||||
|
// Create a new operable value
|
||||||
|
let val = Operable::Relatable(f, x, w);
|
||||||
|
// Process the document record
|
||||||
|
ite.process(ctx, opt, txn, stm, Some(v), val).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -7,7 +7,6 @@ use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::array::Array;
|
use crate::sql::array::Array;
|
||||||
use crate::sql::field::Field;
|
use crate::sql::field::Field;
|
||||||
use crate::sql::id::Id;
|
|
||||||
use crate::sql::part::Part;
|
use crate::sql::part::Part;
|
||||||
use crate::sql::table::Table;
|
use crate::sql::table::Table;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
|
@ -16,16 +15,36 @@ use std::cmp::Ordering;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
pub enum Iterable {
|
||||||
|
Value(Value),
|
||||||
|
Table(Table),
|
||||||
|
Thing(Thing),
|
||||||
|
Mergeable(Thing, Value),
|
||||||
|
Relatable(Thing, Thing, Thing),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Operable {
|
||||||
|
Value(Value),
|
||||||
|
Mergeable(Value, Value),
|
||||||
|
Relatable(Thing, Value, Thing),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Workable {
|
||||||
|
Normal,
|
||||||
|
Insert(Value),
|
||||||
|
Relate(Thing, Thing),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Iterator {
|
pub struct Iterator {
|
||||||
// Iterator status
|
// Iterator status
|
||||||
run: Canceller,
|
run: Canceller,
|
||||||
// Iterator runtime error
|
// Iterator runtime error
|
||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
// Iterator input values
|
|
||||||
readies: Vec<Value>,
|
|
||||||
// Iterator output results
|
// Iterator output results
|
||||||
results: Vec<Value>,
|
results: Vec<Value>,
|
||||||
|
// Iterator input values
|
||||||
|
entries: Vec<Iterable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator {
|
impl Iterator {
|
||||||
|
@ -35,16 +54,8 @@ impl Iterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepares a value for processing
|
// Prepares a value for processing
|
||||||
pub fn prepare(&mut self, val: Value) {
|
pub fn ingest(&mut self, val: Iterable) {
|
||||||
self.readies.push(val)
|
self.entries.push(val)
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new record for processing
|
|
||||||
pub fn produce(&mut self, val: Table) {
|
|
||||||
self.prepare(Value::Thing(Thing {
|
|
||||||
tb: val.0,
|
|
||||||
id: Id::rand(),
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the records and output
|
// Process the records and output
|
||||||
|
@ -324,7 +335,7 @@ impl Iterator {
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Process all prepared values
|
// Process all prepared values
|
||||||
for v in mem::take(&mut self.readies) {
|
for v in mem::take(&mut self.entries) {
|
||||||
v.iterate(ctx, opt, txn, stm, self).await?;
|
v.iterate(ctx, opt, txn, stm, self).await?;
|
||||||
}
|
}
|
||||||
// Everything processed ok
|
// Everything processed ok
|
||||||
|
@ -343,7 +354,7 @@ impl Iterator {
|
||||||
// Run statements sequentially
|
// Run statements sequentially
|
||||||
false => {
|
false => {
|
||||||
// Process all prepared values
|
// Process all prepared values
|
||||||
for v in mem::take(&mut self.readies) {
|
for v in mem::take(&mut self.entries) {
|
||||||
v.iterate(ctx, opt, txn, stm, self).await?;
|
v.iterate(ctx, opt, txn, stm, self).await?;
|
||||||
}
|
}
|
||||||
// Everything processed ok
|
// Everything processed ok
|
||||||
|
@ -354,7 +365,7 @@ impl Iterator {
|
||||||
// Create a new executor
|
// Create a new executor
|
||||||
let exe = executor::Executor::new();
|
let exe = executor::Executor::new();
|
||||||
// Take all of the iterator values
|
// Take all of the iterator values
|
||||||
let vals = mem::take(&mut self.readies);
|
let vals = mem::take(&mut self.entries);
|
||||||
// Create a channel to shutdown
|
// Create a channel to shutdown
|
||||||
let (end, exit) = channel::bounded::<()>(1);
|
let (end, exit) = channel::bounded::<()>(1);
|
||||||
// Create an unbounded channel
|
// Create an unbounded channel
|
||||||
|
@ -412,14 +423,20 @@ impl Iterator {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
thg: Option<Thing>,
|
thg: Option<Thing>,
|
||||||
val: Value,
|
val: Operable,
|
||||||
) {
|
) {
|
||||||
// Check current context
|
// Check current context
|
||||||
if ctx.is_done() {
|
if ctx.is_done() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Setup a new workable
|
||||||
|
let val = match val {
|
||||||
|
Operable::Value(v) => (v, Workable::Normal),
|
||||||
|
Operable::Mergeable(v, o) => (v, Workable::Insert(o)),
|
||||||
|
Operable::Relatable(f, v, w) => (v, Workable::Relate(f, w)),
|
||||||
|
};
|
||||||
// Setup a new document
|
// Setup a new document
|
||||||
let mut doc = Document::new(thg, &val);
|
let mut doc = Document::new(thg, &val.0, val.1);
|
||||||
// Process the document
|
// Process the document
|
||||||
let res = match stm {
|
let res = match stm {
|
||||||
Statement::Select(_) => doc.select(ctx, opt, txn, stm).await,
|
Statement::Select(_) => doc.select(ctx, opt, txn, stm).await,
|
||||||
|
|
|
@ -96,6 +96,8 @@ impl<'a> Statement<'a> {
|
||||||
match self {
|
match self {
|
||||||
Statement::Create(v) => v.data.as_ref(),
|
Statement::Create(v) => v.data.as_ref(),
|
||||||
Statement::Update(v) => v.data.as_ref(),
|
Statement::Update(v) => v.data.as_ref(),
|
||||||
|
Statement::Relate(v) => v.data.as_ref(),
|
||||||
|
Statement::Insert(v) => v.update.as_ref(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +159,14 @@ impl<'a> Statement<'a> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Returns any VERSION clause if specified
|
||||||
|
#[inline]
|
||||||
|
pub fn version(&self) -> Option<&Version> {
|
||||||
|
match self {
|
||||||
|
Statement::Select(v) => v.version.as_ref(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
// Returns any RETURN clause if specified
|
// Returns any RETURN clause if specified
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn output(&self) -> Option<&Output> {
|
pub fn output(&self) -> Option<&Output> {
|
||||||
|
@ -169,14 +179,6 @@ impl<'a> Statement<'a> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Returns any VERSION clause if specified
|
|
||||||
#[inline]
|
|
||||||
pub fn version(&self) -> Option<&Version> {
|
|
||||||
match self {
|
|
||||||
Statement::Select(v) => v.version.as_ref(),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Returns any RETURN clause if specified
|
// Returns any RETURN clause if specified
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn parallel(&self) -> bool {
|
pub fn parallel(&self) -> bool {
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
use crate::ctx::Context;
|
|
||||||
use crate::dbs::Options;
|
|
||||||
use crate::dbs::Statement;
|
|
||||||
use crate::dbs::Transaction;
|
|
||||||
use crate::doc::Document;
|
|
||||||
use crate::err::Error;
|
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
|
||||||
pub async fn admit(
|
|
||||||
&self,
|
|
||||||
_ctx: &Context<'_>,
|
|
||||||
_opt: &Options,
|
|
||||||
_txn: &Transaction,
|
|
||||||
stm: &Statement<'_>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
// Check that we are altering a record
|
|
||||||
if self.id.is_none() {
|
|
||||||
return match stm {
|
|
||||||
Statement::Create(_) => Err(Error::CreateStatement {
|
|
||||||
value: self.initial.to_string(),
|
|
||||||
}),
|
|
||||||
Statement::Update(_) => Err(Error::UpdateStatement {
|
|
||||||
value: self.initial.to_string(),
|
|
||||||
}),
|
|
||||||
Statement::Relate(_) => Err(Error::RelateStatement {
|
|
||||||
value: self.initial.to_string(),
|
|
||||||
}),
|
|
||||||
Statement::Delete(_) => Err(Error::DeleteStatement {
|
|
||||||
value: self.initial.to_string(),
|
|
||||||
}),
|
|
||||||
Statement::Insert(_) => Err(Error::InsertStatement {
|
|
||||||
value: self.initial.to_string(),
|
|
||||||
}),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Carry on
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
86
lib/src/doc/alter.rs
Normal file
86
lib/src/doc/alter.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Options;
|
||||||
|
use crate::dbs::Statement;
|
||||||
|
use crate::dbs::Transaction;
|
||||||
|
use crate::doc::Document;
|
||||||
|
use crate::err::Error;
|
||||||
|
use crate::sql::data::Data;
|
||||||
|
use crate::sql::operator::Operator;
|
||||||
|
use crate::sql::value::Value;
|
||||||
|
|
||||||
|
impl<'a> Document<'a> {
|
||||||
|
pub async fn alter(
|
||||||
|
&mut self,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
opt: &Options,
|
||||||
|
txn: &Transaction,
|
||||||
|
stm: &Statement<'_>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// Get the record id
|
||||||
|
let rid = self.id.as_ref().unwrap();
|
||||||
|
// Set default field values
|
||||||
|
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
||||||
|
// The statement has a data clause
|
||||||
|
if let Some(v) = stm.data() {
|
||||||
|
match v {
|
||||||
|
Data::SetExpression(x) => {
|
||||||
|
for x in x.iter() {
|
||||||
|
let v = x.2.compute(ctx, opt, txn, Some(&self.current)).await?;
|
||||||
|
match x.1 {
|
||||||
|
Operator::Equal => match v {
|
||||||
|
Value::Void => {
|
||||||
|
self.current.to_mut().del(ctx, opt, txn, &x.0).await?
|
||||||
|
}
|
||||||
|
_ => self.current.to_mut().set(ctx, opt, txn, &x.0, v).await?,
|
||||||
|
},
|
||||||
|
Operator::Inc => {
|
||||||
|
self.current.to_mut().increment(ctx, opt, txn, &x.0, v).await?
|
||||||
|
}
|
||||||
|
Operator::Dec => {
|
||||||
|
self.current.to_mut().decrement(ctx, opt, txn, &x.0, v).await?
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::UpdateExpression(x) => {
|
||||||
|
for x in x.iter() {
|
||||||
|
let v = x.2.compute(ctx, opt, txn, Some(&self.current)).await?;
|
||||||
|
match x.1 {
|
||||||
|
Operator::Equal => match v {
|
||||||
|
Value::Void => {
|
||||||
|
self.current.to_mut().del(ctx, opt, txn, &x.0).await?
|
||||||
|
}
|
||||||
|
_ => self.current.to_mut().set(ctx, opt, txn, &x.0, v).await?,
|
||||||
|
},
|
||||||
|
Operator::Inc => {
|
||||||
|
self.current.to_mut().increment(ctx, opt, txn, &x.0, v).await?
|
||||||
|
}
|
||||||
|
Operator::Dec => {
|
||||||
|
self.current.to_mut().decrement(ctx, opt, txn, &x.0, v).await?
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::PatchExpression(data) => {
|
||||||
|
self.current.to_mut().patch(ctx, opt, txn, data).await?
|
||||||
|
}
|
||||||
|
Data::MergeExpression(data) => {
|
||||||
|
self.current.to_mut().merge(ctx, opt, txn, data).await?
|
||||||
|
}
|
||||||
|
Data::ReplaceExpression(data) => {
|
||||||
|
self.current.to_mut().replace(ctx, opt, txn, data).await?
|
||||||
|
}
|
||||||
|
Data::ContentExpression(data) => {
|
||||||
|
self.current.to_mut().replace(ctx, opt, txn, data).await?
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Set default field values
|
||||||
|
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
||||||
|
// Carry on
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Operable;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
|
use crate::dbs::Workable;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
|
@ -16,10 +18,16 @@ impl<'a> Document<'a> {
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
chn: Sender<Result<Value, Error>>,
|
chn: Sender<Result<Value, Error>>,
|
||||||
thg: Option<Thing>,
|
thg: Option<Thing>,
|
||||||
val: Value,
|
val: Operable,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
// Setup a new workable
|
||||||
|
let ins = match val {
|
||||||
|
Operable::Value(v) => (v, Workable::Normal),
|
||||||
|
Operable::Mergeable(v, o) => (v, Workable::Insert(o)),
|
||||||
|
Operable::Relatable(f, v, w) => (v, Workable::Relate(f, w)),
|
||||||
|
};
|
||||||
// Setup a new document
|
// Setup a new document
|
||||||
let mut doc = Document::new(thg, &val);
|
let mut doc = Document::new(thg, &ins.0, ins.1);
|
||||||
// Process the statement
|
// Process the statement
|
||||||
let res = match stm {
|
let res = match stm {
|
||||||
Statement::Select(_) => doc.select(ctx, opt, txn, stm).await,
|
Statement::Select(_) => doc.select(ctx, opt, txn, stm).await,
|
||||||
|
|
|
@ -14,12 +14,10 @@ impl<'a> Document<'a> {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Check value type
|
|
||||||
self.admit(ctx, opt, txn, stm).await?;
|
|
||||||
// Check if exists
|
// Check if exists
|
||||||
self.exist(ctx, opt, txn, stm).await?;
|
self.exist(ctx, opt, txn, stm).await?;
|
||||||
// Merge record data
|
// Alter record data
|
||||||
self.merge(ctx, opt, txn, stm).await?;
|
self.alter(ctx, opt, txn, stm).await?;
|
||||||
// Merge fields data
|
// Merge fields data
|
||||||
self.field(ctx, opt, txn, stm).await?;
|
self.field(ctx, opt, txn, stm).await?;
|
||||||
// Check if allowed
|
// Check if allowed
|
||||||
|
|
|
@ -14,8 +14,6 @@ impl<'a> Document<'a> {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Check value type
|
|
||||||
self.admit(ctx, opt, txn, stm).await?;
|
|
||||||
// Check where clause
|
// Check where clause
|
||||||
self.check(ctx, opt, txn, stm).await?;
|
self.check(ctx, opt, txn, stm).await?;
|
||||||
// Erase document
|
// Erase document
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
|
use crate::dbs::Workable;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::statements::define::DefineEventStatement;
|
use crate::sql::statements::define::DefineEventStatement;
|
||||||
use crate::sql::statements::define::DefineFieldStatement;
|
use crate::sql::statements::define::DefineFieldStatement;
|
||||||
|
@ -9,9 +10,9 @@ use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
||||||
pub struct Document<'a> {
|
pub struct Document<'a> {
|
||||||
pub(super) id: Option<Thing>,
|
pub(super) id: Option<Thing>,
|
||||||
|
pub(super) extras: Workable,
|
||||||
pub(super) current: Cow<'a, Value>,
|
pub(super) current: Cow<'a, Value>,
|
||||||
pub(super) initial: Cow<'a, Value>,
|
pub(super) initial: Cow<'a, Value>,
|
||||||
}
|
}
|
||||||
|
@ -23,9 +24,10 @@ impl<'a> From<&Document<'a>> for Vec<u8> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
impl<'a> Document<'a> {
|
||||||
pub fn new(id: Option<Thing>, val: &'a Value) -> Self {
|
pub fn new(id: Option<Thing>, val: &'a Value, ext: Workable) -> Self {
|
||||||
Document {
|
Document {
|
||||||
id,
|
id,
|
||||||
|
extras: ext,
|
||||||
current: Cow::Borrowed(val),
|
current: Cow::Borrowed(val),
|
||||||
initial: Cow::Borrowed(val),
|
initial: Cow::Borrowed(val),
|
||||||
}
|
}
|
||||||
|
|
46
lib/src/doc/edges.rs
Normal file
46
lib/src/doc/edges.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Options;
|
||||||
|
use crate::dbs::Statement;
|
||||||
|
use crate::dbs::Transaction;
|
||||||
|
use crate::dbs::Workable;
|
||||||
|
use crate::doc::Document;
|
||||||
|
use crate::err::Error;
|
||||||
|
use crate::sql::graph::Dir;
|
||||||
|
|
||||||
|
impl<'a> Document<'a> {
|
||||||
|
pub async fn edges(
|
||||||
|
&self,
|
||||||
|
_ctx: &Context<'_>,
|
||||||
|
opt: &Options,
|
||||||
|
txn: &Transaction,
|
||||||
|
_stm: &Statement<'_>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
// Check if the table is a view
|
||||||
|
if self.tb(opt, txn).await?.drop {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// Clone transaction
|
||||||
|
let run = txn.clone();
|
||||||
|
// Claim transaction
|
||||||
|
let mut run = run.lock().await;
|
||||||
|
// Get the record id
|
||||||
|
let rid = self.id.as_ref().unwrap();
|
||||||
|
// Store the record edges
|
||||||
|
if let Workable::Relate(l, r) = &self.extras {
|
||||||
|
// Store the left pointer edge
|
||||||
|
let key = crate::key::graph::new(opt.ns(), opt.db(), &l.tb, &l.id, &Dir::Out, rid);
|
||||||
|
run.set(key, self).await?;
|
||||||
|
// Store the left inner edge
|
||||||
|
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, &Dir::In, l);
|
||||||
|
run.set(key, self).await?;
|
||||||
|
// Store the right inner edge
|
||||||
|
let key = crate::key::graph::new(opt.ns(), opt.db(), &rid.tb, &rid.id, &Dir::Out, r);
|
||||||
|
run.set(key, self).await?;
|
||||||
|
// Store the right pointer edge
|
||||||
|
let key = crate::key::graph::new(opt.ns(), opt.db(), &r.tb, &r.id, &Dir::In, rid);
|
||||||
|
run.set(key, self).await?;
|
||||||
|
}
|
||||||
|
// Carry on
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,59 @@ use crate::sql::value::Value;
|
||||||
impl<'a> Document<'a> {
|
impl<'a> Document<'a> {
|
||||||
pub async fn insert(
|
pub async fn insert(
|
||||||
&mut self,
|
&mut self,
|
||||||
_ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
_opt: &Options,
|
opt: &Options,
|
||||||
_txn: &Transaction,
|
txn: &Transaction,
|
||||||
_stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
todo!()
|
// Check current record
|
||||||
|
match self.current.is_some() {
|
||||||
|
// Run INSERT clause
|
||||||
|
false => {
|
||||||
|
// Check if allowed
|
||||||
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
|
// Merge record data
|
||||||
|
self.merge(ctx, opt, txn, stm).await?;
|
||||||
|
// Merge fields data
|
||||||
|
self.field(ctx, opt, txn, stm).await?;
|
||||||
|
// Check if allowed
|
||||||
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
|
// Store index data
|
||||||
|
self.index(ctx, opt, txn, stm).await?;
|
||||||
|
// Store record data
|
||||||
|
self.store(ctx, opt, txn, stm).await?;
|
||||||
|
// Run table queries
|
||||||
|
self.table(ctx, opt, txn, stm).await?;
|
||||||
|
// Run lives queries
|
||||||
|
self.lives(ctx, opt, txn, stm).await?;
|
||||||
|
// Run event queries
|
||||||
|
self.event(ctx, opt, txn, stm).await?;
|
||||||
|
// Yield document
|
||||||
|
self.pluck(ctx, opt, txn, stm).await
|
||||||
|
}
|
||||||
|
// Run UPDATE clause
|
||||||
|
true => {
|
||||||
|
// Check if allowed
|
||||||
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
|
// Alter record data
|
||||||
|
self.alter(ctx, opt, txn, stm).await?;
|
||||||
|
// Merge fields data
|
||||||
|
self.field(ctx, opt, txn, stm).await?;
|
||||||
|
// Check if allowed
|
||||||
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
|
// Store index data
|
||||||
|
self.index(ctx, opt, txn, stm).await?;
|
||||||
|
// Store record data
|
||||||
|
self.store(ctx, opt, txn, stm).await?;
|
||||||
|
// Run table queries
|
||||||
|
self.table(ctx, opt, txn, stm).await?;
|
||||||
|
// Run lives queries
|
||||||
|
self.lives(ctx, opt, txn, stm).await?;
|
||||||
|
// Run event queries
|
||||||
|
self.event(ctx, opt, txn, stm).await?;
|
||||||
|
// Yield document
|
||||||
|
self.pluck(ctx, opt, txn, stm).await
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@ use crate::ctx::Context;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
|
use crate::dbs::Workable;
|
||||||
use crate::doc::Document;
|
use crate::doc::Document;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::data::Data;
|
|
||||||
use crate::sql::operator::Operator;
|
|
||||||
use crate::sql::value::Value;
|
|
||||||
|
|
||||||
impl<'a> Document<'a> {
|
impl<'a> Document<'a> {
|
||||||
pub async fn merge(
|
pub async fn merge(
|
||||||
|
@ -14,50 +12,16 @@ impl<'a> Document<'a> {
|
||||||
ctx: &Context<'_>,
|
ctx: &Context<'_>,
|
||||||
opt: &Options,
|
opt: &Options,
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
_stm: &Statement<'_>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Get the record id
|
// Get the record id
|
||||||
let rid = self.id.as_ref().unwrap();
|
let rid = self.id.as_ref().unwrap();
|
||||||
// Set default field values
|
// Set default field values
|
||||||
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
||||||
// The statement has a data clause
|
// This is an INSERT statement
|
||||||
if let Some(v) = stm.data() {
|
if let Workable::Insert(v) = &self.extras {
|
||||||
match v {
|
self.current.to_mut().merge(ctx, opt, txn, v).await?;
|
||||||
Data::SetExpression(x) => {
|
}
|
||||||
for x in x.iter() {
|
|
||||||
let v = x.2.compute(ctx, opt, txn, Some(&self.current)).await?;
|
|
||||||
match x.1 {
|
|
||||||
Operator::Equal => match v {
|
|
||||||
Value::Void => {
|
|
||||||
self.current.to_mut().del(ctx, opt, txn, &x.0).await?
|
|
||||||
}
|
|
||||||
_ => self.current.to_mut().set(ctx, opt, txn, &x.0, v).await?,
|
|
||||||
},
|
|
||||||
Operator::Inc => {
|
|
||||||
self.current.to_mut().increment(ctx, opt, txn, &x.0, v).await?
|
|
||||||
}
|
|
||||||
Operator::Dec => {
|
|
||||||
self.current.to_mut().decrement(ctx, opt, txn, &x.0, v).await?
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Data::PatchExpression(data) => {
|
|
||||||
self.current.to_mut().patch(ctx, opt, txn, data).await?
|
|
||||||
}
|
|
||||||
Data::MergeExpression(data) => {
|
|
||||||
self.current.to_mut().merge(ctx, opt, txn, data).await?
|
|
||||||
}
|
|
||||||
Data::ReplaceExpression(data) => {
|
|
||||||
self.current.to_mut().replace(ctx, opt, txn, data).await?
|
|
||||||
}
|
|
||||||
Data::ContentExpression(data) => {
|
|
||||||
self.current.to_mut().replace(ctx, opt, txn, data).await?
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
// Set default field values
|
// Set default field values
|
||||||
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
self.current.to_mut().def(ctx, opt, txn, rid).await?;
|
||||||
// Carry on
|
// Carry on
|
||||||
|
|
|
@ -3,12 +3,13 @@ pub use self::document::*;
|
||||||
#[cfg(feature = "parallel")]
|
#[cfg(feature = "parallel")]
|
||||||
mod compute;
|
mod compute;
|
||||||
|
|
||||||
mod admit;
|
|
||||||
mod allow;
|
mod allow;
|
||||||
|
mod alter;
|
||||||
mod check;
|
mod check;
|
||||||
mod create;
|
mod create;
|
||||||
mod delete;
|
mod delete;
|
||||||
mod document;
|
mod document;
|
||||||
|
mod edges;
|
||||||
mod empty;
|
mod empty;
|
||||||
mod erase;
|
mod erase;
|
||||||
mod event;
|
mod event;
|
||||||
|
|
|
@ -14,18 +14,18 @@ impl<'a> Document<'a> {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Check value type
|
|
||||||
self.admit(ctx, opt, txn, stm).await?;
|
|
||||||
// Check if allowed
|
// Check if allowed
|
||||||
self.allow(ctx, opt, txn, stm).await?;
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
// Merge record data
|
// Alter record data
|
||||||
self.merge(ctx, opt, txn, stm).await?;
|
self.alter(ctx, opt, txn, stm).await?;
|
||||||
// Merge fields data
|
// Merge fields data
|
||||||
self.field(ctx, opt, txn, stm).await?;
|
self.field(ctx, opt, txn, stm).await?;
|
||||||
// Check if allowed
|
// Check if allowed
|
||||||
self.allow(ctx, opt, txn, stm).await?;
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
// Store index data
|
// Store index data
|
||||||
self.index(ctx, opt, txn, stm).await?;
|
self.index(ctx, opt, txn, stm).await?;
|
||||||
|
// Store record edges
|
||||||
|
self.edges(ctx, opt, txn, stm).await?;
|
||||||
// Store record data
|
// Store record data
|
||||||
self.store(ctx, opt, txn, stm).await?;
|
self.store(ctx, opt, txn, stm).await?;
|
||||||
// Run table queries
|
// Run table queries
|
||||||
|
|
|
@ -14,14 +14,12 @@ impl<'a> Document<'a> {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
stm: &Statement<'_>,
|
stm: &Statement<'_>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Check value type
|
|
||||||
self.admit(ctx, opt, txn, stm).await?;
|
|
||||||
// Check where clause
|
// Check where clause
|
||||||
self.check(ctx, opt, txn, stm).await?;
|
self.check(ctx, opt, txn, stm).await?;
|
||||||
// Check if allowed
|
// Check if allowed
|
||||||
self.allow(ctx, opt, txn, stm).await?;
|
self.allow(ctx, opt, txn, stm).await?;
|
||||||
// Merge record data
|
// Alter record data
|
||||||
self.merge(ctx, opt, txn, stm).await?;
|
self.alter(ctx, opt, txn, stm).await?;
|
||||||
// Merge fields data
|
// Merge fields data
|
||||||
self.field(ctx, opt, txn, stm).await?;
|
self.field(ctx, opt, txn, stm).await?;
|
||||||
// Check if allowed
|
// Check if allowed
|
||||||
|
|
|
@ -8,6 +8,7 @@ use crate::sql::error::IResult;
|
||||||
use crate::sql::escape::escape_key;
|
use crate::sql::escape::escape_key;
|
||||||
use crate::sql::operation::{Op, Operation};
|
use crate::sql::operation::{Op, Operation};
|
||||||
use crate::sql::serde::is_internal_serialization;
|
use crate::sql::serde::is_internal_serialization;
|
||||||
|
use crate::sql::thing::Thing;
|
||||||
use crate::sql::value::{value, Value};
|
use crate::sql::value::{value, Value};
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
|
@ -77,6 +78,14 @@ impl IntoIterator for Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Object {
|
impl Object {
|
||||||
|
// Fetch the record id if there is one
|
||||||
|
pub fn rid(&self) -> Option<Thing> {
|
||||||
|
match self.get("id") {
|
||||||
|
Some(Value::Thing(v)) => Some(v.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Convert this object to a diff-match-patch operation
|
||||||
pub fn to_operation(&self) -> Result<Operation, Error> {
|
pub fn to_operation(&self) -> Result<Operation, Error> {
|
||||||
match self.get("op") {
|
match self.get("op") {
|
||||||
Some(o) => match self.get("path") {
|
Some(o) => match self.get("path") {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -49,10 +50,47 @@ impl CreateStatement {
|
||||||
for w in self.what.0.iter() {
|
for w in self.what.0.iter() {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
match v {
|
match v {
|
||||||
Value::Table(v) => i.produce(v),
|
Value::Table(v) => i.ingest(Iterable::Thing(v.generate())),
|
||||||
Value::Thing(_) => i.prepare(v),
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
Value::Model(_) => i.prepare(v),
|
Value::Model(v) => {
|
||||||
Value::Array(_) => i.prepare(v),
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(v) => {
|
||||||
|
for v in v {
|
||||||
|
match v {
|
||||||
|
Value::Table(v) => i.ingest(Iterable::Thing(v.generate())),
|
||||||
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
Value::Model(v) => {
|
||||||
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::CreateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::CreateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::CreateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
v => {
|
v => {
|
||||||
return Err(Error::CreateStatement {
|
return Err(Error::CreateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -50,10 +51,47 @@ impl DeleteStatement {
|
||||||
for w in self.what.0.iter() {
|
for w in self.what.0.iter() {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
match v {
|
match v {
|
||||||
Value::Table(_) => i.prepare(v),
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
Value::Thing(_) => i.prepare(v),
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
Value::Model(_) => i.prepare(v),
|
Value::Model(v) => {
|
||||||
Value::Array(_) => i.prepare(v),
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(v) => {
|
||||||
|
for v in v {
|
||||||
|
match v {
|
||||||
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
Value::Model(v) => {
|
||||||
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::DeleteStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::DeleteStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::DeleteStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
v => {
|
v => {
|
||||||
return Err(Error::DeleteStatement {
|
return Err(Error::DeleteStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -51,14 +52,40 @@ impl InsertStatement {
|
||||||
let opt = &opt.futures(false);
|
let opt = &opt.futures(false);
|
||||||
// Parse the expression
|
// Parse the expression
|
||||||
match &self.data {
|
match &self.data {
|
||||||
Data::ValuesExpression(_) => {
|
// Check if this is a traditional statement
|
||||||
todo!() // TODO: loop over each
|
Data::ValuesExpression(v) => {
|
||||||
|
for v in v {
|
||||||
|
// Create a new empty base object
|
||||||
|
let mut o = Value::base();
|
||||||
|
// Set each field from the expression
|
||||||
|
for (k, v) in v.iter() {
|
||||||
|
let v = v.compute(ctx, opt, txn, None).await?;
|
||||||
|
o.set(ctx, opt, txn, k, v).await?;
|
||||||
|
}
|
||||||
|
// Specify the new table record id
|
||||||
|
let id = o.retable(&self.into)?;
|
||||||
|
// Pass the mergeable to the iterator
|
||||||
|
i.ingest(Iterable::Mergeable(id, o));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// Check if this is a modern statement
|
||||||
Data::SingleExpression(v) => {
|
Data::SingleExpression(v) => {
|
||||||
let v = v.compute(ctx, opt, txn, doc).await?;
|
let v = v.compute(ctx, opt, txn, doc).await?;
|
||||||
match v {
|
match v {
|
||||||
Value::Array(v) => v.into_iter().for_each(|v| i.prepare(v)),
|
Value::Array(v) => {
|
||||||
Value::Object(_) => i.prepare(v),
|
for v in v {
|
||||||
|
// Specify the new table record id
|
||||||
|
let id = v.retable(&self.into)?;
|
||||||
|
// Pass the mergeable to the iterator
|
||||||
|
i.ingest(Iterable::Mergeable(id, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(_) => {
|
||||||
|
// Specify the new table record id
|
||||||
|
let id = v.retable(&self.into)?;
|
||||||
|
// Pass the mergeable to the iterator
|
||||||
|
i.ingest(Iterable::Mergeable(id, v));
|
||||||
|
}
|
||||||
v => {
|
v => {
|
||||||
return Err(Error::InsertStatement {
|
return Err(Error::InsertStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -52,20 +53,102 @@ impl RelateStatement {
|
||||||
let mut i = Iterator::new();
|
let mut i = Iterator::new();
|
||||||
// Ensure futures are stored
|
// Ensure futures are stored
|
||||||
let opt = &opt.futures(false);
|
let opt = &opt.futures(false);
|
||||||
// Loop over the select targets
|
// Loop over the from targets
|
||||||
for w in self.from.0.iter() {
|
let from = {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
let mut out = Vec::new();
|
||||||
match v {
|
for w in self.from.0.iter() {
|
||||||
Value::Table(_) => i.prepare(v),
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
Value::Thing(_) => i.prepare(v),
|
match v {
|
||||||
Value::Model(_) => i.prepare(v),
|
Value::Thing(v) => out.push(v),
|
||||||
Value::Array(_) => i.prepare(v),
|
Value::Array(v) => {
|
||||||
v => {
|
for v in v {
|
||||||
return Err(Error::RelateStatement {
|
match v {
|
||||||
value: v.to_string(),
|
Value::Thing(v) => out.push(v),
|
||||||
})
|
Value::Object(v) => match v.rid() {
|
||||||
}
|
Some(v) => out.push(v),
|
||||||
};
|
_ => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => out.push(v),
|
||||||
|
None => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
out
|
||||||
|
};
|
||||||
|
// Loop over the with targets
|
||||||
|
let with = {
|
||||||
|
let mut out = Vec::new();
|
||||||
|
for w in self.with.0.iter() {
|
||||||
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
|
match v {
|
||||||
|
Value::Thing(v) => out.push(v),
|
||||||
|
Value::Array(v) => {
|
||||||
|
for v in v {
|
||||||
|
match v {
|
||||||
|
Value::Thing(v) => out.push(v),
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => out.push(v),
|
||||||
|
None => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => out.push(v),
|
||||||
|
None => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
out
|
||||||
|
};
|
||||||
|
//
|
||||||
|
for f in from.iter() {
|
||||||
|
for w in with.iter() {
|
||||||
|
let f = f.clone();
|
||||||
|
let w = w.clone();
|
||||||
|
let t = self.kind.generate();
|
||||||
|
i.ingest(Iterable::Relatable(f, t, w));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Assign the statement
|
// Assign the statement
|
||||||
let stm = Statement::from(self);
|
let stm = Statement::from(self);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -89,11 +90,28 @@ impl SelectStatement {
|
||||||
for w in self.what.0.iter() {
|
for w in self.what.0.iter() {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
match v {
|
match v {
|
||||||
Value::Table(_) => i.prepare(v),
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
Value::Thing(_) => i.prepare(v),
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
Value::Model(_) => i.prepare(v),
|
Value::Model(v) => {
|
||||||
Value::Array(_) => i.prepare(v),
|
for v in v {
|
||||||
v => i.prepare(v),
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(v) => {
|
||||||
|
for v in v {
|
||||||
|
match v {
|
||||||
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
Value::Model(v) => {
|
||||||
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => i.ingest(Iterable::Value(v)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v => i.ingest(Iterable::Value(v)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Assign the statement
|
// Assign the statement
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::ctx::Context;
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Iterable;
|
||||||
use crate::dbs::Iterator;
|
use crate::dbs::Iterator;
|
||||||
use crate::dbs::Level;
|
use crate::dbs::Level;
|
||||||
use crate::dbs::Options;
|
use crate::dbs::Options;
|
||||||
|
@ -51,10 +52,47 @@ impl UpdateStatement {
|
||||||
for w in self.what.0.iter() {
|
for w in self.what.0.iter() {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
let v = w.compute(ctx, opt, txn, doc).await?;
|
||||||
match v {
|
match v {
|
||||||
Value::Table(_) => i.prepare(v),
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
Value::Thing(_) => i.prepare(v),
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
Value::Model(_) => i.prepare(v),
|
Value::Model(v) => {
|
||||||
Value::Array(_) => i.prepare(v),
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(v) => {
|
||||||
|
for v in v {
|
||||||
|
match v {
|
||||||
|
Value::Table(v) => i.ingest(Iterable::Table(v)),
|
||||||
|
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
Value::Model(v) => {
|
||||||
|
for v in v {
|
||||||
|
i.ingest(Iterable::Thing(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::UpdateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::UpdateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(v) => match v.rid() {
|
||||||
|
Some(v) => i.ingest(Iterable::Thing(v)),
|
||||||
|
None => {
|
||||||
|
return Err(Error::UpdateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
v => {
|
v => {
|
||||||
return Err(Error::UpdateStatement {
|
return Err(Error::UpdateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::sql::common::commas;
|
use crate::sql::common::commas;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::escape::escape_ident;
|
use crate::sql::escape::escape_ident;
|
||||||
|
use crate::sql::id::Id;
|
||||||
use crate::sql::ident::{ident_raw, Ident};
|
use crate::sql::ident::{ident_raw, Ident};
|
||||||
|
use crate::sql::thing::Thing;
|
||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -50,6 +52,15 @@ impl Deref for Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Table {
|
||||||
|
pub fn generate(&self) -> Thing {
|
||||||
|
Thing {
|
||||||
|
tb: self.0.to_owned(),
|
||||||
|
id: Id::rand(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Table {
|
impl fmt::Display for Table {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", escape_ident(&self.0))
|
write!(f, "{}", escape_ident(&self.0))
|
||||||
|
|
Loading…
Reference in a new issue