Add initial iterator blueprint implementation
This commit is contained in:
parent
c51e60e706
commit
9e62e8f367
1 changed files with 266 additions and 13 deletions
|
@ -1,21 +1,274 @@
|
||||||
use crate::dbs::Executor;
|
use crate::dbs::Executor;
|
||||||
use crate::dbs::Runtime;
|
use crate::dbs::Runtime;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::literal::Literal;
|
use crate::sql::array::Array;
|
||||||
|
use crate::sql::cond::Cond;
|
||||||
|
use crate::sql::data::Data;
|
||||||
|
use crate::sql::field::Fields;
|
||||||
|
use crate::sql::group::Groups;
|
||||||
|
use crate::sql::limit::Limit;
|
||||||
|
use crate::sql::model::Model;
|
||||||
|
use crate::sql::object::Object;
|
||||||
|
use crate::sql::order::Orders;
|
||||||
|
use crate::sql::split::Splits;
|
||||||
|
use crate::sql::start::Start;
|
||||||
|
use crate::sql::table::Table;
|
||||||
|
use crate::sql::thing::Thing;
|
||||||
|
use crate::sql::value::Value;
|
||||||
|
use crate::sql::version::Version;
|
||||||
|
use std::mem;
|
||||||
|
use xid;
|
||||||
|
|
||||||
pub struct Iterator {}
|
#[derive(Default)]
|
||||||
|
pub struct Iterator<'a> {
|
||||||
|
ok: bool,
|
||||||
|
// Iterator options
|
||||||
|
pub into: Option<&'a Table>,
|
||||||
|
pub expr: Option<&'a Fields>,
|
||||||
|
pub data: Option<&'a Data>,
|
||||||
|
pub cond: Option<&'a Cond>,
|
||||||
|
pub split: Option<&'a Splits>,
|
||||||
|
pub group: Option<&'a Groups>,
|
||||||
|
pub order: Option<&'a Orders>,
|
||||||
|
pub limit: Option<&'a Limit>,
|
||||||
|
pub start: Option<&'a Start>,
|
||||||
|
pub version: Option<&'a Version>,
|
||||||
|
// Iterator runtime error
|
||||||
|
error: Option<Error>,
|
||||||
|
// Iterator output results
|
||||||
|
results: Vec<Value>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Iterator {
|
impl<'a> Iterator<'a> {
|
||||||
pub fn new() -> Iterator {
|
pub fn new() -> Iterator<'a> {
|
||||||
Iterator {}
|
Iterator {
|
||||||
|
ok: true,
|
||||||
|
..Iterator::default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub fn process_query(&self, ctx: &Runtime, exe: &Executor) {}
|
|
||||||
pub fn process_table(&self, ctx: &Runtime, exe: &Executor) {}
|
fn check(&self, ctx: &Runtime) -> bool {
|
||||||
pub fn process_thing(&self, ctx: &Runtime, exe: &Executor) {}
|
self.ok && ctx.is_ok()
|
||||||
pub fn process_model(&self, ctx: &Runtime, exe: &Executor) {}
|
}
|
||||||
pub fn process_array(&self, ctx: &Runtime, exe: &Executor) {}
|
|
||||||
pub fn process_object(&self, ctx: &Runtime, exe: &Executor) {}
|
pub fn process_table(&mut self, ctx: &Runtime, exe: &mut Executor, val: Table) {
|
||||||
pub fn output(&self, ctx: &Runtime, exe: &Executor) -> Result<Literal, Error> {
|
// Check basic permissions
|
||||||
Ok(Literal::Null)
|
self.process_perms(ctx, exe);
|
||||||
|
// Loop over all table keys
|
||||||
|
// - Process record
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_thing(&mut self, ctx: &Runtime, exe: &mut Executor, val: Thing) {
|
||||||
|
// Check basic permissions
|
||||||
|
self.process_perms(ctx, exe);
|
||||||
|
// Check current context
|
||||||
|
if self.check(ctx) {
|
||||||
|
// Process record
|
||||||
|
// self.process(ctx, exe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_model(&mut self, ctx: &Runtime, exe: &mut Executor, val: Model) {
|
||||||
|
// Check basic permissions
|
||||||
|
self.process_perms(ctx, exe);
|
||||||
|
// Process count based model
|
||||||
|
if val.count.is_some() {
|
||||||
|
let c = val.count.unwrap();
|
||||||
|
for _ in 0..c {
|
||||||
|
// Check current context
|
||||||
|
if self.check(ctx) {
|
||||||
|
// Process record
|
||||||
|
self.process(
|
||||||
|
ctx,
|
||||||
|
exe,
|
||||||
|
Value::from(Thing {
|
||||||
|
tb: val.table.to_string(),
|
||||||
|
id: xid::new().to_string(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Process range based model
|
||||||
|
if val.range.is_some() {
|
||||||
|
let r = val.range.unwrap();
|
||||||
|
for x in r.0..r.1 {
|
||||||
|
// Check current context
|
||||||
|
if self.check(ctx) {
|
||||||
|
// Process record
|
||||||
|
self.process(
|
||||||
|
ctx,
|
||||||
|
exe,
|
||||||
|
Value::from(Thing {
|
||||||
|
tb: val.table.to_string(),
|
||||||
|
id: x.to_string(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_array(&mut self, ctx: &Runtime, exe: &mut Executor, val: Array) {
|
||||||
|
// Check basic permissions
|
||||||
|
self.process_perms(ctx, exe);
|
||||||
|
// Loop over query result array
|
||||||
|
for v in val.value.into_iter() {
|
||||||
|
// Check current context
|
||||||
|
if self.check(ctx) {
|
||||||
|
// Process item
|
||||||
|
match v {
|
||||||
|
Value::Thing(v) => self.process_thing(ctx, exe, v),
|
||||||
|
Value::Object(v) => self.process_object(ctx, exe, v),
|
||||||
|
v => self.process(ctx, exe, v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_object(&mut self, ctx: &Runtime, exe: &mut Executor, val: Object) {
|
||||||
|
// Check basic permissions
|
||||||
|
self.process_perms(ctx, exe);
|
||||||
|
// Check current context
|
||||||
|
if self.check(ctx) {
|
||||||
|
// Loop over query result array
|
||||||
|
self.process(ctx, exe, val.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_value(&mut self, ctx: &Runtime, exe: &mut Executor, val: Value) {
|
||||||
|
// Check basic permissions
|
||||||
|
self.process_perms(ctx, exe);
|
||||||
|
// Loop over query result array
|
||||||
|
// self.process(ctx, exe, val)
|
||||||
|
// - IF value is THING then process record
|
||||||
|
// - IF value.id is THING then process record
|
||||||
|
// - ELSE process as object
|
||||||
|
match val {
|
||||||
|
Value::Thing(v) => self.process_thing(ctx, exe, v),
|
||||||
|
Value::Object(v) => self.process_object(ctx, exe, v),
|
||||||
|
v => self.process(ctx, exe, v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(&mut self, ctx: &Runtime, exe: &mut Executor, val: Value) {
|
||||||
|
// 1. Setup a new document
|
||||||
|
// 2. Check for any errors
|
||||||
|
// 3. Append the result
|
||||||
|
|
||||||
|
let res = Some(val);
|
||||||
|
|
||||||
|
// If an error was received from the
|
||||||
|
// worker, then set the error if no
|
||||||
|
// previous iterator error has occured.
|
||||||
|
|
||||||
|
if self.check(ctx) == false {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise add the received result
|
||||||
|
// to the iterator result slice so
|
||||||
|
// that it is ready for processing.
|
||||||
|
|
||||||
|
if let Some(r) = res {
|
||||||
|
self.results.push(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The statement does not have a limit
|
||||||
|
// expression specified, so therefore
|
||||||
|
// we need to load all data before
|
||||||
|
// stopping the iterator.
|
||||||
|
|
||||||
|
if self.limit.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the statement specified a GROUP
|
||||||
|
// BY expression, then we need to load
|
||||||
|
// all data from all sources before
|
||||||
|
// stopping the iterator.
|
||||||
|
|
||||||
|
if self.group.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the statement specified an ORDER
|
||||||
|
// BY expression, then we need to load
|
||||||
|
// all data from all sources before
|
||||||
|
// stopping the iterator.
|
||||||
|
|
||||||
|
if self.order.is_some() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we can stop the iterator
|
||||||
|
// early, if we have the necessary
|
||||||
|
// number of records specified in the
|
||||||
|
// query statement.
|
||||||
|
|
||||||
|
if let Some(l) = self.limit {
|
||||||
|
if let Some(s) = self.start {
|
||||||
|
if self.results.len() as u64 == l.0 + s.0 {
|
||||||
|
self.ok = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.results.len() as u64 == l.0 {
|
||||||
|
self.ok = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_perms(&self, ctx: &Runtime, exe: &Executor) {}
|
||||||
|
|
||||||
|
fn process_split(&mut self, ctx: &Runtime, exe: &Executor) {
|
||||||
|
if self.split.is_some() {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_group(&mut self, ctx: &Runtime, exe: &Executor) {
|
||||||
|
if self.group.is_some() {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_order(&mut self, ctx: &Runtime, exe: &Executor) {
|
||||||
|
if self.order.is_some() {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_start(&mut self, ctx: &Runtime, exe: &Executor) {
|
||||||
|
if let Some(v) = self.start {
|
||||||
|
let s = v.0 as usize;
|
||||||
|
self.results = mem::take(&mut self.results).into_iter().skip(s).collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_limit(&mut self, ctx: &Runtime, exe: &Executor) {
|
||||||
|
if let Some(v) = self.limit {
|
||||||
|
let l = v.0 as usize;
|
||||||
|
self.results = mem::take(&mut self.results).into_iter().take(l).collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn output(&mut self, ctx: &Runtime, exe: &Executor) -> Result<Value, Error> {
|
||||||
|
// Return any errors
|
||||||
|
if let Some(e) = self.error.take() {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
// Process SPLIT clause
|
||||||
|
self.process_split(ctx, exe);
|
||||||
|
// Process GROUP clause
|
||||||
|
self.process_group(ctx, exe);
|
||||||
|
// Process ORDER clause
|
||||||
|
self.process_order(ctx, exe);
|
||||||
|
// Process START clause
|
||||||
|
self.process_start(ctx, exe);
|
||||||
|
// Process LIMIT clause
|
||||||
|
self.process_limit(ctx, exe);
|
||||||
|
// Output the results
|
||||||
|
Ok(mem::take(&mut self.results).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue