Ensure statements are properly escaped when output as a string

This commit is contained in:
Tobie Morgan Hitchcock 2022-05-15 09:34:29 +01:00
parent 75de89d9a1
commit 15fc4a0126
14 changed files with 157 additions and 111 deletions

View file

@ -717,7 +717,7 @@ impl Transaction {
.put( .put(
key, key,
DefineNamespaceStatement { DefineNamespaceStatement {
name: ns.to_owned(), name: ns.into(),
}, },
) )
.await; .await;
@ -730,7 +730,7 @@ impl Transaction {
.put( .put(
key, key,
DefineDatabaseStatement { DefineDatabaseStatement {
name: db.to_owned(), name: db.into(),
}, },
) )
.await; .await;
@ -743,7 +743,7 @@ impl Transaction {
.put( .put(
key, key,
DefineTableStatement { DefineTableStatement {
name: tb.to_owned(), name: tb.into(),
..DefineTableStatement::default() ..DefineTableStatement::default()
}, },
) )

View file

@ -33,16 +33,6 @@ pub fn val_char(chr: char) -> bool {
is_alphanumeric(chr as u8) || chr == '_' is_alphanumeric(chr as u8) || chr == '_'
} }
#[inline]
pub fn escape(s: &str, f: &dyn Fn(char) -> bool, c: &str) -> String {
for x in s.chars() {
if !f(x) {
return format!("{}{}{}", c, s, c);
}
}
s.to_owned()
}
pub fn take_u32(i: &str) -> IResult<&str, u32> { pub fn take_u32(i: &str) -> IResult<&str, u32> {
let (i, v) = take_while(is_digit)(i)?; let (i, v) = take_while(is_digit)(i)?;
match v.parse::<u32>() { match v.parse::<u32>() {

32
lib/src/sql/escape.rs Normal file
View file

@ -0,0 +1,32 @@
use crate::sql::common::val_char;
const DOUBLE: char = '"';
const DOUBLE_ESC: &str = r#"\""#;
const BACKTICK: char = '`';
const BACKTICK_ESC: &str = r#"\`"#;
#[inline]
pub fn escape_strand(s: &str) -> String {
format!("{}{}{}", DOUBLE, s, DOUBLE)
}
#[inline]
pub fn escape_key(s: &str) -> String {
for x in s.chars() {
if !val_char(x) {
return format!("{}{}{}", DOUBLE, s.replace(DOUBLE, DOUBLE_ESC), DOUBLE);
}
}
s.to_owned()
}
#[inline]
pub fn escape_ident(s: &str) -> String {
for x in s.chars() {
if !val_char(x) {
return format!("{}{}{}", BACKTICK, s.replace(BACKTICK, BACKTICK_ESC), BACKTICK);
}
}
s.to_owned()
}

View file

@ -1,7 +1,6 @@
use crate::cnf::ID_CHARS; use crate::cnf::ID_CHARS;
use crate::sql::common::escape;
use crate::sql::common::val_char;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_ident;
use crate::sql::ident::ident_raw; use crate::sql::ident::ident_raw;
use crate::sql::number::{number, Number}; use crate::sql::number::{number, Number};
use nanoid::nanoid; use nanoid::nanoid;
@ -50,7 +49,7 @@ impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Id::Number(v) => write!(f, "{}", v), Id::Number(v) => write!(f, "{}", v),
Id::String(v) => write!(f, "{}", escape(v, &val_char, "`")), Id::String(v) => write!(f, "{}", escape_ident(v)),
} }
} }
} }

View file

@ -1,16 +1,26 @@
use crate::sql::common::escape;
use crate::sql::common::val_char; use crate::sql::common::val_char;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_ident;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not; use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_while1; use nom::bytes::complete::take_while1;
use nom::character::complete::char; use nom::character::complete::char;
use nom::character::complete::one_of;
use nom::sequence::delimited; use nom::sequence::delimited;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::str; use std::str;
const BRACKET_L: char = '⟨';
const BRACKET_R: char = '⟩';
const BRACKET_END: &str = r#"⟩"#;
const BACKTICK: &str = r#"`"#;
const BACKTICK_ESC: &str = r#"\`"#;
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Ident(pub String); pub struct Ident(pub String);
@ -41,7 +51,7 @@ impl Deref for Ident {
impl fmt::Display for Ident { impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", escape(&self.0, &val_char, "`")) write!(f, "{}", escape_ident(&self.0))
} }
} }
@ -61,12 +71,14 @@ fn ident_default(i: &str) -> IResult<&str, String> {
} }
fn ident_backtick(i: &str) -> IResult<&str, String> { fn ident_backtick(i: &str) -> IResult<&str, String> {
let (i, v) = delimited(char('`'), is_not("`"), char('`'))(i)?; let (i, _) = char('`')(i)?;
Ok((i, String::from(v))) let (i, v) = alt((escaped(is_not(BACKTICK_ESC), '\\', one_of(BACKTICK)), tag("")))(i)?;
let (i, _) = char('`')(i)?;
Ok((i, String::from(v).replace(BACKTICK_ESC, BACKTICK)))
} }
fn ident_brackets(i: &str) -> IResult<&str, String> { fn ident_brackets(i: &str) -> IResult<&str, String> {
let (i, v) = delimited(char('⟨'), is_not(""), char('⟩'))(i)?; let (i, v) = delimited(char(BRACKET_L), is_not(BRACKET_END), char(BRACKET_R))(i)?;
Ok((i, String::from(v))) Ok((i, String::from(v)))
} }

View file

@ -8,6 +8,7 @@ pub(crate) mod data;
pub(crate) mod datetime; pub(crate) mod datetime;
pub(crate) mod duration; pub(crate) mod duration;
pub(crate) mod error; pub(crate) mod error;
pub(crate) mod escape;
pub(crate) mod expression; pub(crate) mod expression;
pub(crate) mod fetch; pub(crate) mod fetch;
pub(crate) mod field; pub(crate) mod field;

View file

@ -1,7 +1,6 @@
use crate::sql::common::escape;
use crate::sql::common::take_u64; use crate::sql::common::take_u64;
use crate::sql::common::val_char;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_ident;
use crate::sql::ident::ident_raw; use crate::sql::ident::ident_raw;
use nom::branch::alt; use nom::branch::alt;
use nom::character::complete::char; use nom::character::complete::char;
@ -18,12 +17,10 @@ impl fmt::Display for Model {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Model::Count(tb, c) => { Model::Count(tb, c) => {
let t = escape(tb, &val_char, "`"); write!(f, "|{}:{}|", escape_ident(tb), c)
write!(f, "|{}:{}|", t, c)
} }
Model::Range(tb, b, e) => { Model::Range(tb, b, e) => {
let t = escape(tb, &val_char, "`"); write!(f, "|{}:{}..{}|", escape_ident(tb), b, e)
write!(f, "|{}:{}..{}|", t, b, e)
} }
} }
} }

View file

@ -3,8 +3,9 @@ use crate::dbs::Options;
use crate::dbs::Transaction; use crate::dbs::Transaction;
use crate::err::Error; use crate::err::Error;
use crate::sql::comment::mightbespace; use crate::sql::comment::mightbespace;
use crate::sql::common::{commas, escape, val_char}; use crate::sql::common::{commas, val_char};
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_key;
use crate::sql::operation::{Op, Operation}; use crate::sql::operation::{Op, Operation};
use crate::sql::value::{value, Value}; use crate::sql::value::{value, Value};
use nom::branch::alt; use nom::branch::alt;
@ -122,7 +123,7 @@ impl fmt::Display for Object {
f, f,
"{{ {} }}", "{{ {} }}",
self.iter() self.iter()
.map(|(k, v)| format!("{}: {}", escape(k, &val_char, "\""), v)) .map(|(k, v)| format!("{}: {}", escape_key(k), v))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
) )

View file

@ -8,7 +8,8 @@ use crate::sql::base::{base, Base};
use crate::sql::comment::shouldbespace; use crate::sql::comment::shouldbespace;
use crate::sql::duration::{duration, Duration}; use crate::sql::duration::{duration, Duration};
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::ident::ident_raw; use crate::sql::escape::escape_strand;
use crate::sql::ident::{ident, Ident};
use crate::sql::idiom; use crate::sql::idiom;
use crate::sql::idiom::{Idiom, Idioms}; use crate::sql::idiom::{Idiom, Idioms};
use crate::sql::kind::{kind, Kind}; use crate::sql::kind::{kind, Kind};
@ -103,7 +104,7 @@ pub fn define(i: &str) -> IResult<&str, DefineStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineNamespaceStatement { pub struct DefineNamespaceStatement {
pub name: String, pub name: Ident,
} }
impl DefineNamespaceStatement { impl DefineNamespaceStatement {
@ -135,7 +136,7 @@ fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?; let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
DefineNamespaceStatement { DefineNamespaceStatement {
@ -150,7 +151,7 @@ fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineDatabaseStatement { pub struct DefineDatabaseStatement {
pub name: String, pub name: Ident,
} }
impl DefineDatabaseStatement { impl DefineDatabaseStatement {
@ -187,7 +188,7 @@ fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?; let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
DefineDatabaseStatement { DefineDatabaseStatement {
@ -202,7 +203,7 @@ fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineLoginStatement { pub struct DefineLoginStatement {
pub name: String, pub name: Ident,
pub base: Base, pub base: Base,
pub hash: String, pub hash: String,
pub code: String, pub code: String,
@ -253,7 +254,13 @@ impl DefineLoginStatement {
impl fmt::Display for DefineLoginStatement { impl fmt::Display for DefineLoginStatement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DEFINE LOGIN {} ON {} PASSHASH {}", self.name, self.base, self.hash) write!(
f,
"DEFINE LOGIN {} ON {} PASSHASH {}",
self.name,
self.base,
escape_strand(&self.hash)
)
} }
} }
@ -262,7 +269,7 @@ fn login(i: &str) -> IResult<&str, DefineLoginStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("LOGIN")(i)?; let (i, _) = tag_no_case("LOGIN")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -321,7 +328,7 @@ fn login_hash(i: &str) -> IResult<&str, DefineLoginOption> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineTokenStatement { pub struct DefineTokenStatement {
pub name: String, pub name: Ident,
pub base: Base, pub base: Base,
pub kind: Algorithm, pub kind: Algorithm,
pub code: String, pub code: String,
@ -375,7 +382,10 @@ impl fmt::Display for DefineTokenStatement {
write!( write!(
f, f,
"DEFINE TOKEN {} ON {} TYPE {} VALUE {}", "DEFINE TOKEN {} ON {} TYPE {} VALUE {}",
self.name, self.base, self.kind, self.code self.name,
self.base,
self.kind,
escape_strand(&self.code)
) )
} }
} }
@ -385,7 +395,7 @@ fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("TOKEN")(i)?; let (i, _) = tag_no_case("TOKEN")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -415,7 +425,7 @@ fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineScopeStatement { pub struct DefineScopeStatement {
pub name: String, pub name: Ident,
pub code: String, pub code: String,
pub session: Option<Duration>, pub session: Option<Duration>,
pub signup: Option<Value>, pub signup: Option<Value>,
@ -471,7 +481,7 @@ fn scope(i: &str) -> IResult<&str, DefineScopeStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("SCOPE")(i)?; let (i, _) = tag_no_case("SCOPE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, opts) = many0(scope_opts)(i)?; let (i, opts) = many0(scope_opts)(i)?;
Ok(( Ok((
i, i,
@ -552,7 +562,7 @@ fn scope_connect(i: &str) -> IResult<&str, DefineScopeOption> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineTableStatement { pub struct DefineTableStatement {
pub name: String, pub name: Ident,
pub drop: bool, pub drop: bool,
pub full: bool, pub full: bool,
pub view: Option<View>, pub view: Option<View>,
@ -633,7 +643,7 @@ fn table(i: &str) -> IResult<&str, DefineTableStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("TABLE")(i)?; let (i, _) = tag_no_case("TABLE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, opts) = many0(table_opts)(i)?; let (i, opts) = many0(table_opts)(i)?;
Ok(( Ok((
i, i,
@ -718,8 +728,8 @@ fn table_permissions(i: &str) -> IResult<&str, DefineTableOption> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineEventStatement { pub struct DefineEventStatement {
pub name: String, pub name: Ident,
pub what: String, pub what: Ident,
pub when: Value, pub when: Value,
pub then: Values, pub then: Values,
} }
@ -764,12 +774,12 @@ fn event(i: &str) -> IResult<&str, DefineEventStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("EVENT")(i)?; let (i, _) = tag_no_case("EVENT")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("WHEN")(i)?; let (i, _) = tag_no_case("WHEN")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -796,7 +806,7 @@ fn event(i: &str) -> IResult<&str, DefineEventStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineFieldStatement { pub struct DefineFieldStatement {
pub name: Idiom, pub name: Idiom,
pub what: String, pub what: Ident,
pub kind: Option<Kind>, pub kind: Option<Kind>,
pub value: Option<Value>, pub value: Option<Value>,
pub assert: Option<Value>, pub assert: Option<Value>,
@ -857,7 +867,7 @@ fn field(i: &str) -> IResult<&str, DefineFieldStatement> {
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
let (i, opts) = many0(field_opts)(i)?; let (i, opts) = many0(field_opts)(i)?;
Ok(( Ok((
i, i,
@ -935,8 +945,8 @@ fn field_permissions(i: &str) -> IResult<&str, DefineFieldOption> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct DefineIndexStatement { pub struct DefineIndexStatement {
pub name: String, pub name: Ident,
pub what: String, pub what: Ident,
pub cols: Idioms, pub cols: Idioms,
pub uniq: bool, pub uniq: bool,
} }
@ -992,12 +1002,12 @@ fn index(i: &str) -> IResult<&str, DefineIndexStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("INDEX")(i)?; let (i, _) = tag_no_case("INDEX")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = alt((tag_no_case("COLUMNS"), tag_no_case("FIELDS")))(i)?; let (i, _) = alt((tag_no_case("COLUMNS"), tag_no_case("FIELDS")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;

View file

@ -5,7 +5,7 @@ use crate::dbs::Transaction;
use crate::err::Error; use crate::err::Error;
use crate::sql::comment::shouldbespace; use crate::sql::comment::shouldbespace;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::ident::ident_raw; use crate::sql::ident::{ident, Ident};
use crate::sql::object::Object; use crate::sql::object::Object;
use crate::sql::value::Value; use crate::sql::value::Value;
use derive::Store; use derive::Store;
@ -19,8 +19,8 @@ pub enum InfoStatement {
Kv, Kv,
Ns, Ns,
Db, Db,
Sc(String), Sc(Ident),
Tb(String), Tb(Ident),
} }
impl InfoStatement { impl InfoStatement {
@ -45,7 +45,7 @@ impl InfoStatement {
// Process the statement // Process the statement
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_ns().await? { for v in run.all_ns().await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("ns".to_owned(), tmp.into()); res.insert("ns".to_owned(), tmp.into());
// Ok all good // Ok all good
@ -63,19 +63,19 @@ impl InfoStatement {
// Process the databases // Process the databases
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_db(opt.ns()).await? { for v in run.all_db(opt.ns()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("db".to_owned(), tmp.into()); res.insert("db".to_owned(), tmp.into());
// Process the tokens // Process the tokens
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_nt(opt.ns()).await? { for v in run.all_nt(opt.ns()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("nt".to_owned(), tmp.into()); res.insert("nt".to_owned(), tmp.into());
// Process the logins // Process the logins
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_nl(opt.ns()).await? { for v in run.all_nl(opt.ns()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("nl".to_owned(), tmp.into()); res.insert("nl".to_owned(), tmp.into());
// Ok all good // Ok all good
@ -93,27 +93,27 @@ impl InfoStatement {
// Process the tables // Process the tables
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_tb(opt.ns(), opt.db()).await? { for v in run.all_tb(opt.ns(), opt.db()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("tb".to_owned(), tmp.into()); res.insert("tb".to_owned(), tmp.into());
// Process the scopes // Process the scopes
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_sc(opt.ns(), opt.db()).await? { for v in run.all_sc(opt.ns(), opt.db()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("sc".to_owned(), tmp.into()); res.insert("sc".to_owned(), tmp.into());
// Process the tokens // Process the tokens
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_nt(opt.ns()).await? { for v in run.all_dt(opt.ns(), opt.db()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("nt".to_owned(), tmp.into()); res.insert("dt".to_owned(), tmp.into());
// Process the logins // Process the logins
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_nl(opt.ns()).await? { for v in run.all_dl(opt.ns(), opt.db()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("nl".to_owned(), tmp.into()); res.insert("dl".to_owned(), tmp.into());
// Ok all good // Ok all good
Value::from(res).ok() Value::from(res).ok()
} }
@ -129,7 +129,7 @@ impl InfoStatement {
// Process the tokens // Process the tokens
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_st(opt.ns(), opt.db(), sc).await? { for v in run.all_st(opt.ns(), opt.db(), sc).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("st".to_owned(), tmp.into()); res.insert("st".to_owned(), tmp.into());
// Ok all good // Ok all good
@ -147,7 +147,7 @@ impl InfoStatement {
// Process the events // Process the events
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_ev(opt.ns(), opt.db(), tb).await? { for v in run.all_ev(opt.ns(), opt.db(), tb).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("ev".to_owned(), tmp.into()); res.insert("ev".to_owned(), tmp.into());
// Process the fields // Process the fields
@ -159,13 +159,13 @@ impl InfoStatement {
// Process the indexs // Process the indexs
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_ix(opt.ns(), opt.db(), tb).await? { for v in run.all_ix(opt.ns(), opt.db(), tb).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("ix".to_owned(), tmp.into()); res.insert("ix".to_owned(), tmp.into());
// Process the tables // Process the tables
let mut tmp = Object::default(); let mut tmp = Object::default();
for v in run.all_ft(opt.ns(), opt.db(), tb).await? { for v in run.all_ft(opt.ns(), opt.db(), tb).await? {
tmp.insert(v.name.to_owned(), v.to_string().into()); tmp.insert(v.name.to_string(), v.to_string().into());
} }
res.insert("ft".to_owned(), tmp.into()); res.insert("ft".to_owned(), tmp.into());
// Ok all good // Ok all good
@ -213,14 +213,14 @@ fn db(i: &str) -> IResult<&str, InfoStatement> {
fn sc(i: &str) -> IResult<&str, InfoStatement> { fn sc(i: &str) -> IResult<&str, InfoStatement> {
let (i, _) = alt((tag_no_case("SCOPE"), tag_no_case("SC")))(i)?; let (i, _) = alt((tag_no_case("SCOPE"), tag_no_case("SC")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, scope) = ident_raw(i)?; let (i, scope) = ident(i)?;
Ok((i, InfoStatement::Sc(scope))) Ok((i, InfoStatement::Sc(scope)))
} }
fn tb(i: &str) -> IResult<&str, InfoStatement> { fn tb(i: &str) -> IResult<&str, InfoStatement> {
let (i, _) = alt((tag_no_case("TABLE"), tag_no_case("TB")))(i)?; let (i, _) = alt((tag_no_case("TABLE"), tag_no_case("TB")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, table) = ident_raw(i)?; let (i, table) = ident(i)?;
Ok((i, InfoStatement::Tb(table))) Ok((i, InfoStatement::Tb(table)))
} }
@ -255,7 +255,7 @@ mod tests {
let res = info(sql); let res = info(sql);
assert!(res.is_ok()); assert!(res.is_ok());
let out = res.unwrap().1; let out = res.unwrap().1;
assert_eq!(out, InfoStatement::Sc(String::from("test"))); assert_eq!(out, InfoStatement::Sc(Ident::from("test")));
assert_eq!("INFO FOR SCOPE test", format!("{}", out)); assert_eq!("INFO FOR SCOPE test", format!("{}", out));
} }
@ -265,7 +265,7 @@ mod tests {
let res = info(sql); let res = info(sql);
assert!(res.is_ok()); assert!(res.is_ok());
let out = res.unwrap().1; let out = res.unwrap().1;
assert_eq!(out, InfoStatement::Tb(String::from("test"))); assert_eq!(out, InfoStatement::Tb(Ident::from("test")));
assert_eq!("INFO FOR TABLE test", format!("{}", out)); assert_eq!("INFO FOR TABLE test", format!("{}", out));
} }
} }

View file

@ -6,7 +6,7 @@ use crate::err::Error;
use crate::sql::base::{base, Base}; use crate::sql::base::{base, Base};
use crate::sql::comment::shouldbespace; use crate::sql::comment::shouldbespace;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::ident::ident_raw; use crate::sql::ident::{ident, Ident};
use crate::sql::value::Value; use crate::sql::value::Value;
use derive::Store; use derive::Store;
use nom::branch::alt; use nom::branch::alt;
@ -87,7 +87,7 @@ pub fn remove(i: &str) -> IResult<&str, RemoveStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveNamespaceStatement { pub struct RemoveNamespaceStatement {
pub name: String, pub name: Ident,
} }
impl RemoveNamespaceStatement { impl RemoveNamespaceStatement {
@ -126,7 +126,7 @@ fn namespace(i: &str) -> IResult<&str, RemoveNamespaceStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?; let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
RemoveNamespaceStatement { RemoveNamespaceStatement {
@ -141,7 +141,7 @@ fn namespace(i: &str) -> IResult<&str, RemoveNamespaceStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveDatabaseStatement { pub struct RemoveDatabaseStatement {
pub name: String, pub name: Ident,
} }
impl RemoveDatabaseStatement { impl RemoveDatabaseStatement {
@ -180,7 +180,7 @@ fn database(i: &str) -> IResult<&str, RemoveDatabaseStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?; let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
RemoveDatabaseStatement { RemoveDatabaseStatement {
@ -195,7 +195,7 @@ fn database(i: &str) -> IResult<&str, RemoveDatabaseStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveLoginStatement { pub struct RemoveLoginStatement {
pub name: String, pub name: Ident,
pub base: Base, pub base: Base,
} }
@ -250,7 +250,7 @@ fn login(i: &str) -> IResult<&str, RemoveLoginStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("LOGIN")(i)?; let (i, _) = tag_no_case("LOGIN")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -270,7 +270,7 @@ fn login(i: &str) -> IResult<&str, RemoveLoginStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveTokenStatement { pub struct RemoveTokenStatement {
pub name: String, pub name: Ident,
pub base: Base, pub base: Base,
} }
@ -325,7 +325,7 @@ fn token(i: &str) -> IResult<&str, RemoveTokenStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("TOKEN")(i)?; let (i, _) = tag_no_case("TOKEN")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
@ -345,7 +345,7 @@ fn token(i: &str) -> IResult<&str, RemoveTokenStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveScopeStatement { pub struct RemoveScopeStatement {
pub name: String, pub name: Ident,
} }
impl RemoveScopeStatement { impl RemoveScopeStatement {
@ -381,7 +381,7 @@ fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("SCOPE")(i)?; let (i, _) = tag_no_case("SCOPE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
RemoveScopeStatement { RemoveScopeStatement {
@ -396,7 +396,7 @@ fn scope(i: &str) -> IResult<&str, RemoveScopeStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveTableStatement { pub struct RemoveTableStatement {
pub name: String, pub name: Ident,
} }
impl RemoveTableStatement { impl RemoveTableStatement {
@ -435,7 +435,7 @@ fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("TABLE")(i)?; let (i, _) = tag_no_case("TABLE")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
Ok(( Ok((
i, i,
RemoveTableStatement { RemoveTableStatement {
@ -450,8 +450,8 @@ fn table(i: &str) -> IResult<&str, RemoveTableStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveEventStatement { pub struct RemoveEventStatement {
pub name: String, pub name: Ident,
pub what: String, pub what: Ident,
} }
impl RemoveEventStatement { impl RemoveEventStatement {
@ -487,12 +487,12 @@ fn event(i: &str) -> IResult<&str, RemoveEventStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("EVENT")(i)?; let (i, _) = tag_no_case("EVENT")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
Ok(( Ok((
i, i,
RemoveEventStatement { RemoveEventStatement {
@ -508,8 +508,8 @@ fn event(i: &str) -> IResult<&str, RemoveEventStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveFieldStatement { pub struct RemoveFieldStatement {
pub name: String, pub name: Ident,
pub what: String, pub what: Ident,
} }
impl RemoveFieldStatement { impl RemoveFieldStatement {
@ -545,12 +545,12 @@ fn field(i: &str) -> IResult<&str, RemoveFieldStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("FIELD")(i)?; let (i, _) = tag_no_case("FIELD")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
Ok(( Ok((
i, i,
RemoveFieldStatement { RemoveFieldStatement {
@ -566,8 +566,8 @@ fn field(i: &str) -> IResult<&str, RemoveFieldStatement> {
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)] #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
pub struct RemoveIndexStatement { pub struct RemoveIndexStatement {
pub name: String, pub name: Ident,
pub what: String, pub what: Ident,
} }
impl RemoveIndexStatement { impl RemoveIndexStatement {
@ -606,12 +606,12 @@ fn index(i: &str) -> IResult<&str, RemoveIndexStatement> {
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("INDEX")(i)?; let (i, _) = tag_no_case("INDEX")(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, name) = ident_raw(i)?; let (i, name) = ident(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, _) = tag_no_case("ON")(i)?; let (i, _) = tag_no_case("ON")(i)?;
let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?; let (i, _) = opt(tuple((shouldbespace, tag_no_case("TABLE"))))(i)?;
let (i, _) = shouldbespace(i)?; let (i, _) = shouldbespace(i)?;
let (i, what) = ident_raw(i)?; let (i, what) = ident(i)?;
Ok(( Ok((
i, i,
RemoveIndexStatement { RemoveIndexStatement {

View file

@ -1,4 +1,5 @@
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_strand;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::escaped; use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not; use nom::bytes::complete::is_not;
@ -49,7 +50,7 @@ impl Strand {
impl fmt::Display for Strand { impl fmt::Display for Strand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\"{}\"", self.0) write!(f, "{}", escape_strand(&self.0))
} }
} }

View file

@ -1,8 +1,7 @@
use crate::sql::common::commas; use crate::sql::common::commas;
use crate::sql::common::escape;
use crate::sql::common::val_char;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::ident::ident_raw; use crate::sql::escape::escape_ident;
use crate::sql::ident::{ident_raw, Ident};
use nom::multi::separated_list1; use nom::multi::separated_list1;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -32,6 +31,12 @@ impl From<String> for Table {
} }
} }
impl From<Ident> for Table {
fn from(v: Ident) -> Self {
Table(v.0)
}
}
impl Deref for Table { impl Deref for Table {
type Target = String; type Target = String;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
@ -41,7 +46,7 @@ impl Deref for Table {
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(&self.0, &val_char, "`")) write!(f, "{}", escape_ident(&self.0))
} }
} }

View file

@ -1,6 +1,5 @@
use crate::sql::common::escape;
use crate::sql::common::val_char;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_ident;
use crate::sql::id::{id, Id}; use crate::sql::id::{id, Id};
use crate::sql::ident::ident_raw; use crate::sql::ident::ident_raw;
use crate::sql::number::Number; use crate::sql::number::Number;
@ -45,8 +44,7 @@ impl From<(String, Number)> for Thing {
impl fmt::Display for Thing { impl fmt::Display for Thing {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let t = escape(&self.tb, &val_char, "`"); write!(f, "{}:{}", escape_ident(&self.tb), self.id)
write!(f, "{}:{}", t, self.id)
} }
} }