Basic DCL impls
parent
597a49a91b
commit
6a01d9d513
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Created on Thu Sep 21 2023
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::engine::{
|
||||
data::{
|
||||
tag::{DataTag, TagClass},
|
||||
DictGeneric,
|
||||
},
|
||||
error::{Error, QueryResult},
|
||||
ql::{
|
||||
ast::{traits, QueryData, State},
|
||||
ddl::syn,
|
||||
},
|
||||
};
|
||||
|
||||
fn parse<'a, Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> QueryResult<UserMeta<'a>> {
|
||||
/*
|
||||
user add [username] with { password: [password], ... }
|
||||
^cursor
|
||||
7 tokens
|
||||
*/
|
||||
if state.remaining() < 7 {
|
||||
return Err(Error::QLInvalidSyntax);
|
||||
}
|
||||
let token_buffer = state.current();
|
||||
// initial sig
|
||||
let signature_okay = token_buffer[0].is_lit()
|
||||
& token_buffer[1].eq(&Token![with])
|
||||
& token_buffer[2].eq(&Token![open {}]);
|
||||
// get props
|
||||
state.poison_if_not(signature_okay);
|
||||
state.cursor_ahead_by(2);
|
||||
let Some(dict) = syn::parse_dict(state) else {
|
||||
return Err(Error::QLInvalidCollectionSyntax);
|
||||
};
|
||||
let maybe_username = unsafe {
|
||||
// UNSAFE(@ohsayan): the dict parse ensures state correctness
|
||||
token_buffer[0].uck_read_lit()
|
||||
};
|
||||
state.poison_if_not(maybe_username.kind().tag_class() == TagClass::Str);
|
||||
if state.not_exhausted() & !state.okay() {
|
||||
// we shouldn't have more tokens
|
||||
return Err(Error::QLInvalidSyntax);
|
||||
}
|
||||
Ok(UserMeta {
|
||||
username: unsafe {
|
||||
// UNSAFE(@ohsayan): +tagck in state
|
||||
maybe_username.str()
|
||||
},
|
||||
options: dict,
|
||||
})
|
||||
}
|
||||
|
||||
struct UserMeta<'a> {
|
||||
username: &'a str,
|
||||
options: DictGeneric,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct UserAdd<'a> {
|
||||
username: &'a str,
|
||||
options: DictGeneric,
|
||||
}
|
||||
|
||||
impl<'a> UserAdd<'a> {
|
||||
pub(in crate::engine::ql) fn new(username: &'a str, options: DictGeneric) -> Self {
|
||||
Self { username, options }
|
||||
}
|
||||
/// Parse a `user add` DCL command
|
||||
///
|
||||
/// MUSTENDSTREAM: YES
|
||||
pub fn parse<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> QueryResult<Self> {
|
||||
parse(state).map(|UserMeta { username, options }: UserMeta| Self::new(username, options))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> traits::ASTNode<'a> for UserAdd<'a> {
|
||||
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> QueryResult<Self> {
|
||||
Self::parse(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct UserDel<'a> {
|
||||
username: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> UserDel<'a> {
|
||||
pub(in crate::engine::ql) fn new(username: &'a str) -> Self {
|
||||
Self { username }
|
||||
}
|
||||
/// Parse a `user del` DCL command
|
||||
///
|
||||
/// MUSTENDSTREAM: YES
|
||||
pub fn parse<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> QueryResult<Self> {
|
||||
if state.can_read_lit_rounded() & (state.remaining() == 1) {
|
||||
let lit = unsafe {
|
||||
// UNSAFE(@ohsayan): +boundck
|
||||
state.read_cursor_lit_unchecked()
|
||||
};
|
||||
state.cursor_ahead();
|
||||
if lit.kind().tag_class() == TagClass::Str {
|
||||
return Ok(Self::new(unsafe {
|
||||
// UNSAFE(@ohsayan): +tagck
|
||||
lit.str()
|
||||
}));
|
||||
}
|
||||
}
|
||||
Err(Error::QLInvalidSyntax)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> traits::ASTNode<'a> for UserDel<'a> {
|
||||
fn _from_state<Qd: QueryData<'a>>(state: &mut State<'a, Qd>) -> QueryResult<Self> {
|
||||
Self::parse(state)
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Created on Fri Sep 22 2023
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::engine::ql::{ast, dcl, tests::lex_insecure};
|
||||
|
||||
#[test]
|
||||
fn create_user_simple() {
|
||||
let query = lex_insecure(b"create user 'sayan' with { password: 'mypass123' }").unwrap();
|
||||
let q = ast::parse_ast_node_full::<dcl::UserAdd>(&query[2..]).unwrap();
|
||||
assert_eq!(
|
||||
q,
|
||||
dcl::UserAdd::new("sayan", into_dict!("password" => lit!("mypass123")))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delete_user_simple() {
|
||||
let query = lex_insecure(b"delete user 'monster'").unwrap();
|
||||
let q = ast::parse_ast_node_full::<dcl::UserDel>(&query[2..]).unwrap();
|
||||
assert_eq!(q, dcl::UserDel::new("monster"))
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Created on Fri Sep 22 2023
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2023, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use crate::engine::{
|
||||
data::{cell::Datacell, DictEntryGeneric, DictGeneric},
|
||||
fractal::SysConfig,
|
||||
storage::v1::{
|
||||
header_meta::{FileScope, FileSpecifier, FileSpecifierVersion},
|
||||
RawFSInterface, SDSSError, SDSSFileIO, SDSSResult,
|
||||
},
|
||||
};
|
||||
|
||||
const SYSDB_PATH: &str = "sys.db";
|
||||
const SYSDB_COW_PATH: &str = "sys.db.cow";
|
||||
|
||||
pub fn sync_system_database<Fs: RawFSInterface>(cfg: &SysConfig) -> SDSSResult<()> {
|
||||
// get auth data
|
||||
let auth_data = cfg.auth_data().read();
|
||||
// prepare our flat file
|
||||
let mut map: DictGeneric = into_dict!(
|
||||
"host" => DictEntryGeneric::Map(into_dict!(
|
||||
"settings_version" => Datacell::new_uint(cfg.host_data().settings_version() as _),
|
||||
"startup_counter" => Datacell::new_uint(cfg.host_data().startup_counter() as _),
|
||||
)),
|
||||
"auth" => DictGeneric::new(),
|
||||
);
|
||||
let auth_key = map.get_mut("auth").unwrap();
|
||||
match &*auth_data {
|
||||
None => *auth_key = Datacell::null().into(),
|
||||
Some(auth) => {
|
||||
let auth_key = auth_key.as_dict_mut().unwrap();
|
||||
auth_key.insert(
|
||||
"root".into(),
|
||||
DictEntryGeneric::Data(Datacell::new_bin(auth.root_key().into())),
|
||||
);
|
||||
auth_key.insert(
|
||||
"users".into(),
|
||||
DictEntryGeneric::Map(
|
||||
auth.users()
|
||||
.iter()
|
||||
.map(|(username, user)| {
|
||||
(
|
||||
username.to_owned(),
|
||||
DictEntryGeneric::Data(Datacell::new_list(vec![
|
||||
Datacell::new_bin(user.key().into()),
|
||||
])),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// open file
|
||||
let mut file = SDSSFileIO::<Fs>::open_or_create_perm_rw::<false>(
|
||||
SYSDB_COW_PATH,
|
||||
FileScope::FlatmapData,
|
||||
FileSpecifier::SysDB,
|
||||
FileSpecifierVersion::__new(0),
|
||||
cfg.host_data().settings_version(),
|
||||
cfg.host_data().run_mode(),
|
||||
cfg.host_data().startup_counter(),
|
||||
)?
|
||||
.into_created()
|
||||
.ok_or(SDSSError::OtherError(
|
||||
"sys.db.cow already exists. please remove this file.",
|
||||
))?;
|
||||
// write
|
||||
let buf = super::inf::enc::enc_dict_full::<super::inf::map::GenericDictSpec>(&map);
|
||||
file.fsynced_write(&buf)?;
|
||||
// replace
|
||||
Fs::fs_rename_file(SYSDB_COW_PATH, SYSDB_PATH)
|
||||
}
|
Loading…
Reference in New Issue