diff --git a/server/src/engine/ql/schema.rs b/server/src/engine/ql/schema.rs index ae46de13..7104b925 100644 --- a/server/src/engine/ql/schema.rs +++ b/server/src/engine/ql/schema.rs @@ -46,11 +46,11 @@ use { super::{ ast::{Compiler, Statement}, - lexer::{DdlMiscKeyword, Keyword, Lit, Symbol, Token, Type}, + lexer::{DdlKeyword, DdlMiscKeyword, Keyword, Lit, MiscKeyword, Symbol, Token, Type}, LangResult, RawSlice, }, std::{ - collections::HashMap, + collections::{HashMap, HashSet}, mem::{transmute, MaybeUninit}, }, }; @@ -76,6 +76,8 @@ macro_rules! states { } } +type StaticStr = &'static str; + const HIBIT: u64 = 1 << 63; const TRAIL_COMMA: bool = true; @@ -111,6 +113,21 @@ impl Layer { } } +#[derive(Debug, Default, PartialEq, Eq)] +pub struct FieldProperties { + pub(super) propeties: HashSet, +} + +impl FieldProperties { + const NULL: StaticStr = "null"; + const PRIMARY: StaticStr = "primary"; + pub fn new() -> Self { + Self { + propeties: HashSet::new(), + } + } +} + /* Context-free dict */ @@ -457,6 +474,31 @@ pub(super) fn fold_layers(tok: &[Token]) -> (Vec, usize, bool) { (l, (r & !HIBIT) as _, r & HIBIT == HIBIT) } +pub(super) fn collect_field_properties(tok: &[Token]) -> (FieldProperties, usize, bool) { + let mut props = FieldProperties::default(); + let mut i = 0; + let mut okay = true; + while i < tok.len() { + match &tok[i] { + Token::Keyword(Keyword::Ddl(DdlKeyword::Primary)) => { + okay &= props.propeties.insert(FieldProperties::PRIMARY) + } + Token::Keyword(Keyword::Misc(MiscKeyword::Null)) => { + okay &= props.propeties.insert(FieldProperties::NULL) + } + Token::Ident(_) => break, + _ => { + // we could pass this over to the caller, but it's better if we do it since we're doing + // a linear scan anyways + okay = false; + break; + } + } + i += 1; + } + (props, i, okay) +} + pub(crate) fn parse_schema(_c: &mut Compiler, _m: RawSlice) -> LangResult { todo!() } diff --git a/server/src/engine/ql/tests.rs b/server/src/engine/ql/tests.rs index 53ea4eb7..adbac2ef 100644 --- a/server/src/engine/ql/tests.rs +++ b/server/src/engine/ql/tests.rs @@ -678,4 +678,30 @@ mod schema_tests { }); } } + mod field_properties { + use {super::*, crate::engine::ql::schema::FieldProperties}; + + #[test] + fn field_properties_empty() { + let tok = lex(b"myfield:").unwrap(); + let (props, c, okay) = schema::collect_field_properties(&tok); + assert!(okay); + assert_eq!(c, 0); + assert_eq!(props, FieldProperties::default()); + } + #[test] + fn field_properties_full() { + let tok = lex(b"primary null myfield:").unwrap(); + let (props, c, okay) = schema::collect_field_properties(&tok); + assert_eq!(c, 2); + assert_eq!(tok[c], Token::Ident("myfield".into())); + assert!(okay); + assert_eq!( + props, + FieldProperties { + propeties: ["primary", "null"].into_iter().collect() + } + ) + } + } }