Use `State` for all other DDL statements

next
Sayan Nandan 2 years ago
parent 763007a98c
commit fd22b51183
No known key found for this signature in database
GPG Key ID: 8BC07A0A4D41DD52

@ -30,7 +30,10 @@ use {
lexer::{LitIR, Slice, Token},
schema, LangError, LangResult,
},
crate::{engine::memory::DataType, util::compiler},
crate::{
engine::memory::DataType,
util::{compiler, MaybeInit},
},
core::cmp,
};
@ -230,6 +233,10 @@ impl<'a, Qd: QueryData<'a>> State<'a, Qd> {
pub(crate) fn cursor(&self) -> usize {
self.i
}
#[inline(always)]
pub(crate) fn cursor_is_ident(&self) -> bool {
self.read().is_ident()
}
}
pub trait QueryData<'a> {
@ -428,6 +435,58 @@ impl<'a> Entity<'a> {
};
Ok(r)
}
#[inline(always)]
pub fn attempt_process_entity_result<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
) -> LangResult<Self> {
let mut e = MaybeInit::uninit();
Self::attempt_process_entity(state, &mut e);
if state.okay() {
unsafe {
// UNSAFE(@ohsayan): just checked if okay
Ok(e.assume_init())
}
} else {
Err(LangError::UnexpectedToken)
}
}
#[inline(always)]
pub fn attempt_process_entity<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
d: &mut MaybeInit<Entity<'a>>,
) {
let tok = state.current();
let is_full = Entity::tokens_with_full(tok);
let is_single = Entity::tokens_with_single(tok);
unsafe {
if is_full {
state.cursor_ahead_by(3);
*d = MaybeInit::new(Entity::full_entity_from_slice(tok));
} else if is_single {
state.cursor_ahead();
*d = MaybeInit::new(Entity::single_entity_from_slice(tok));
}
}
state.poison_if_not(is_full | is_single);
}
pub fn parse_entity<Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
d: &mut MaybeInit<Entity<'a>>,
) {
let tok = state.current();
let is_full = tok[0].is_ident() && tok[1] == Token![.] && tok[2].is_ident();
let is_single = tok[0].is_ident();
unsafe {
if is_full {
state.cursor_ahead_by(3);
*d = MaybeInit::new(Entity::full_entity_from_slice(tok));
} else if is_single {
state.cursor_ahead();
*d = MaybeInit::new(Entity::single_entity_from_slice(tok));
}
}
state.poison_if_not(is_full | is_single);
}
}
#[cfg_attr(test, derive(Debug, PartialEq))]
@ -473,54 +532,46 @@ pub enum Statement<'a> {
}
pub fn compile<'a, Qd: QueryData<'a>>(tok: &'a [Token], d: Qd) -> LangResult<Statement<'a>> {
let mut i = 0;
if compiler::unlikely(tok.len() < 2) {
return Err(LangError::UnexpectedEndofStatement);
}
match tok[0] {
let mut state = State::new(tok, d);
match state.fw_read() {
// DDL
Token![use] => Entity::parse_from_tokens(&tok[1..], &mut i).map(Statement::Use),
Token![drop] if tok.len() >= 3 => ddl::parse_drop(&tok[1..], &mut i),
Token::Ident(id) if id.eq_ignore_ascii_case(b"inspect") => {
ddl::parse_inspect(&tok[1..], &mut i)
}
ref stmt => {
let mut state = State::new(&tok[1..], d);
match stmt {
// DDL
Token![create] => {
match tok[1] {
Token![model] => schema::parse_model_from_tokens(&mut state)
.map(Statement::CreateModel),
Token![space] => schema::parse_space_from_tokens(&mut state)
.map(Statement::CreateSpace),
_ => compiler::cold_rerr(LangError::UnknownCreateStatement),
}
}
Token![alter] => match tok[1] {
Token![model] => {
schema::parse_alter_kind_from_tokens(&mut state).map(Statement::AlterModel)
}
Token![space] => {
schema::parse_alter_space_from_tokens(&mut state).map(Statement::AlterSpace)
}
_ => compiler::cold_rerr(LangError::UnknownAlterStatement),
},
// DML
Token![insert] => {
dml::insert::InsertStatement::parse_insert(&mut state).map(Statement::Insert)
}
Token![select] => {
dml::select::SelectStatement::parse_select(&mut state).map(Statement::Select)
}
Token![update] => {
dml::update::UpdateStatement::parse_update(&mut state).map(Statement::Update)
}
Token![delete] => {
dml::delete::DeleteStatement::parse_delete(&mut state).map(Statement::Delete)
}
_ => compiler::cold_rerr(LangError::ExpectedStatement),
Token![use] => Entity::attempt_process_entity_result(&mut state).map(Statement::Use),
Token![create] => match state.fw_read() {
Token![model] => {
schema::parse_model_from_tokens(&mut state).map(Statement::CreateModel)
}
Token![space] => {
schema::parse_space_from_tokens(&mut state).map(Statement::CreateSpace)
}
_ => compiler::cold_rerr(LangError::UnknownCreateStatement),
},
Token![alter] => match state.fw_read() {
Token![model] => {
schema::parse_alter_kind_from_tokens(&mut state).map(Statement::AlterModel)
}
Token![space] => {
schema::parse_alter_space_from_tokens(&mut state).map(Statement::AlterSpace)
}
_ => compiler::cold_rerr(LangError::UnknownAlterStatement),
},
Token![drop] if state.remaining() >= 2 => ddl::parse_drop(&mut state),
Token::Ident(id) if id.eq_ignore_ascii_case(b"inspect") => ddl::parse_inspect(&mut state),
// DML
Token![insert] => {
dml::insert::InsertStatement::parse_insert(&mut state).map(Statement::Insert)
}
Token![select] => {
dml::select::SelectStatement::parse_select(&mut state).map(Statement::Select)
}
Token![update] => {
dml::update::UpdateStatement::parse_update(&mut state).map(Statement::Update)
}
Token![delete] => {
dml::delete::DeleteStatement::parse_delete(&mut state).map(Statement::Delete)
}
_ => compiler::cold_rerr(LangError::ExpectedStatement),
}
}

@ -24,10 +24,15 @@
*
*/
use super::{
ast::{Entity, Statement},
lexer::{Slice, Token},
LangError, LangResult,
#[cfg(test)]
use super::ast::InplaceData;
use {
super::{
ast::{Entity, QueryData, State, Statement},
lexer::{Slice, Token},
LangError, LangResult,
},
crate::util::compiler,
};
#[derive(Debug, PartialEq)]
@ -62,32 +67,31 @@ impl<'a> DropModel<'a> {
/// ## Panic
///
/// If token stream length is < 2
pub(super) fn parse_drop<'a>(tok: &'a [Token], counter: &mut usize) -> LangResult<Statement<'a>> {
match tok[0] {
pub(super) fn parse_drop<'a, Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
) -> LangResult<Statement<'a>> {
match state.fw_read() {
Token![model] => {
// we have a model. now parse entity and see if we should force deletion
let mut i = 1;
let e = Entity::parse_from_tokens(&tok[1..], &mut i)?;
let force = i < tok.len() && tok[i] == Token::Ident(b"force");
i += force as usize;
*counter += i;
let e = Entity::attempt_process_entity_result(state)?;
let force = state.cursor_rounded_eq(Token::Ident(b"force"));
state.cursor_ahead_if(force);
// if we've exhausted the stream, we're good to go (either `force`, or nothing)
if tok.len() == i {
if state.exhausted() {
return Ok(Statement::DropModel(DropModel::new(e, force)));
}
}
Token![space] if tok[1].is_ident() => {
let mut i = 2; // (`space` and space name)
// should we force drop?
let force = i < tok.len() && tok[i] == Token::Ident(b"force");
i += force as usize;
*counter += i;
Token![space] if state.cursor_is_ident() => {
let ident = state.fw_read();
// should we force drop?
let force = state.cursor_rounded_eq(Token::Ident(b"force"));
state.cursor_ahead_if(force);
// either `force` or nothing
if tok.len() == i {
if state.exhausted() {
return Ok(Statement::DropSpace(DropSpace::new(
unsafe {
// UNSAFE(@ohsayan): Safe because the match predicate ensures that tok[1] is indeed an ident
extract!(tok[1], Token::Ident(ref space) => *space)
extract!(ident, Token::Ident(ref space) => *space)
},
force,
)));
@ -100,41 +104,49 @@ pub(super) fn parse_drop<'a>(tok: &'a [Token], counter: &mut usize) -> LangResul
#[cfg(test)]
pub(super) fn parse_drop_full<'a>(tok: &'a [Token]) -> LangResult<Statement<'a>> {
let mut i = 0;
let r = self::parse_drop(tok, &mut i);
assert_full_tt!(i, tok.len());
let mut state = State::new(tok, InplaceData::new());
let r = self::parse_drop(&mut state);
assert_full_tt!(state);
r
}
pub(super) fn parse_inspect<'a>(tok: &'a [Token], c: &mut usize) -> LangResult<Statement<'a>> {
pub(super) fn parse_inspect<'a, Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
) -> LangResult<Statement<'a>> {
/*
inpsect model <entity>
inspect space <entity>
inspect spaces
min length -> (<model> | <space>) <model> = 2
*/
let nxt = tok.get(0);
*c += nxt.is_some() as usize;
match nxt {
Some(Token![model]) => Entity::parse_from_tokens(&tok[1..], c).map(Statement::InspectModel),
Some(Token![space]) if tok.len() == 2 && tok[1].is_ident() => {
*c += 1;
if compiler::unlikely(state.remaining() < 1) {
return compiler::cold_rerr(LangError::UnexpectedEndofStatement);
}
match state.fw_read() {
Token![model] => Entity::attempt_process_entity_result(state).map(Statement::InspectModel),
Token![space] if state.cursor_has_ident_rounded() => {
Ok(Statement::InspectSpace(unsafe {
// UNSAFE(@ohsayan): Safe because of the match predicate
extract!(tok[1], Token::Ident(ref space) => space)
extract!(state.fw_read(), Token::Ident(ref space) => space)
}))
}
Some(Token::Ident(id)) if id.eq_ignore_ascii_case(b"spaces") && tok.len() == 1 => {
Token::Ident(id) if id.eq_ignore_ascii_case(b"spaces") && state.exhausted() => {
Ok(Statement::InspectSpaces)
}
_ => Err(LangError::ExpectedStatement),
_ => {
state.cursor_back();
Err(LangError::ExpectedStatement)
}
}
}
#[cfg(test)]
pub(super) fn parse_inspect_full<'a>(tok: &'a [Token]) -> LangResult<Statement<'a>> {
let mut i = 0;
let r = self::parse_inspect(tok, &mut i);
assert_full_tt!(i, tok.len());
let mut state = State::new(tok, InplaceData::new());
let r = self::parse_inspect(&mut state);
assert_full_tt!(state);
r
}

@ -24,13 +24,8 @@
*
*/
#[cfg(test)]
use {
super::WhereClauseCollection,
crate::engine::ql::{ast::InplaceData, lexer::Token},
};
use {
super::{parse_entity, WhereClause},
super::WhereClause,
crate::{
engine::ql::{
ast::{Entity, QueryData, State},
@ -39,6 +34,11 @@ use {
util::{compiler, MaybeInit},
},
};
#[cfg(test)]
use {
super::WhereClauseCollection,
crate::engine::ql::{ast::InplaceData, lexer::Token},
};
/*
Impls for delete
@ -78,7 +78,7 @@ impl<'a> DeleteStatement<'a> {
state.poison_if_not(state.cursor_eq(Token![from]));
state.cursor_ahead(); // ignore errors (if any)
let mut entity = MaybeInit::uninit();
parse_entity(state, &mut entity);
Entity::parse_entity(state, &mut entity);
// where + clauses
state.poison_if_not(state.cursor_eq(Token![where]));
state.cursor_ahead(); // ignore errors

@ -27,7 +27,7 @@
#[cfg(test)]
use crate::engine::ql::ast::InplaceData;
use {
super::{parse_entity, read_ident},
super::read_ident,
crate::{
engine::{
memory::DataType,
@ -392,7 +392,7 @@ impl<'a> InsertStatement<'a> {
// entity
let mut entity = MaybeInit::uninit();
parse_entity(state, &mut entity);
Entity::parse_entity(state, &mut entity);
let mut data = None;
match state.fw_read() {
Token![() open] if state.not_exhausted() => {

@ -38,10 +38,10 @@ pub mod update;
use super::ast::InplaceData;
use {
super::{
ast::{Entity, QueryData, State},
ast::{QueryData, State},
lexer::{LitIR, Token},
},
crate::util::{compiler, MaybeInit},
crate::util::compiler,
std::collections::HashMap,
};
@ -59,42 +59,6 @@ fn u(b: bool) -> u8 {
Misc
*/
#[inline(always)]
fn attempt_process_entity<'a, Qd: QueryData<'a>>(
state: &mut State<'a, Qd>,
d: &mut MaybeInit<Entity<'a>>,
) {
let tok = state.current();
let is_full = Entity::tokens_with_full(tok);
let is_single = Entity::tokens_with_single(tok);
unsafe {
if is_full {
state.cursor_ahead_by(3);
*d = MaybeInit::new(Entity::full_entity_from_slice(tok));
} else if is_single {
state.cursor_ahead();
*d = MaybeInit::new(Entity::single_entity_from_slice(tok));
}
}
state.poison_if_not(is_full | is_single);
}
fn parse_entity<'a, Qd: QueryData<'a>>(state: &mut State<'a, Qd>, d: &mut MaybeInit<Entity<'a>>) {
let tok = state.current();
let is_full = tok[0].is_ident() && tok[1] == Token![.] && tok[2].is_ident();
let is_single = tok[0].is_ident();
unsafe {
if is_full {
state.cursor_ahead_by(3);
*d = MaybeInit::new(Entity::full_entity_from_slice(tok));
} else if is_single {
state.cursor_ahead();
*d = MaybeInit::new(Entity::single_entity_from_slice(tok));
}
}
state.poison_if_not(is_full | is_single);
}
/*
Contexts
*/

@ -27,7 +27,7 @@
#[cfg(test)]
use crate::engine::ql::ast::InplaceData;
use {
super::{attempt_process_entity, WhereClause, WhereClauseCollection},
super::{WhereClause, WhereClauseCollection},
crate::{
engine::ql::{
ast::{Entity, QueryData, State},
@ -122,7 +122,7 @@ impl<'a> SelectStatement<'a> {
state.poison_if_not(state.cursor_eq(Token![from]));
state.cursor_ahead(); // ignore errors
let mut entity = MaybeInit::uninit();
attempt_process_entity(state, &mut entity);
Entity::attempt_process_entity(state, &mut entity);
let mut clauses = <_ as Default>::default();
if state.cursor_rounded_eq(Token![where]) {
state.cursor_ahead();

@ -30,7 +30,7 @@ use {
crate::engine::ql::{ast::InplaceData, lexer::Token},
};
use {
super::{parse_entity, read_ident, u, WhereClause},
super::{read_ident, u, WhereClause},
crate::{
engine::ql::{
ast::{Entity, QueryData, State},
@ -188,7 +188,7 @@ impl<'a> UpdateStatement<'a> {
}
// parse entity
let mut entity = MaybeInit::uninit();
parse_entity(state, &mut entity);
Entity::parse_entity(state, &mut entity);
if !(state.has_remaining(6)) {
unsafe {
// UNSAFE(@ohsayan): Obvious from above, max 3 fw

Loading…
Cancel
Save