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

View file

@ -33,16 +33,6 @@ pub fn val_char(chr: char) -> bool {
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> {
let (i, v) = take_while(is_digit)(i)?;
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::sql::common::escape;
use crate::sql::common::val_char;
use crate::sql::error::IResult;
use crate::sql::escape::escape_ident;
use crate::sql::ident::ident_raw;
use crate::sql::number::{number, Number};
use nanoid::nanoid;
@ -50,7 +49,7 @@ impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
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::error::IResult;
use crate::sql::escape::escape_ident;
use nom::branch::alt;
use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_while1;
use nom::character::complete::char;
use nom::character::complete::one_of;
use nom::sequence::delimited;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::ops::Deref;
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)]
pub struct Ident(pub String);
@ -41,7 +51,7 @@ impl Deref for Ident {
impl fmt::Display for Ident {
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> {
let (i, v) = delimited(char('`'), is_not("`"), char('`'))(i)?;
Ok((i, String::from(v)))
let (i, _) = char('`')(i)?;
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> {
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)))
}

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ use crate::dbs::Transaction;
use crate::err::Error;
use crate::sql::comment::shouldbespace;
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::value::Value;
use derive::Store;
@ -19,8 +19,8 @@ pub enum InfoStatement {
Kv,
Ns,
Db,
Sc(String),
Tb(String),
Sc(Ident),
Tb(Ident),
}
impl InfoStatement {
@ -45,7 +45,7 @@ impl InfoStatement {
// Process the statement
let mut tmp = Object::default();
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());
// Ok all good
@ -63,19 +63,19 @@ impl InfoStatement {
// Process the databases
let mut tmp = Object::default();
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());
// Process the tokens
let mut tmp = Object::default();
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());
// Process the logins
let mut tmp = Object::default();
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());
// Ok all good
@ -93,27 +93,27 @@ impl InfoStatement {
// Process the tables
let mut tmp = Object::default();
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());
// Process the scopes
let mut tmp = Object::default();
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());
// Process the tokens
let mut tmp = Object::default();
for v in run.all_nt(opt.ns()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into());
for v in run.all_dt(opt.ns(), opt.db()).await? {
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
let mut tmp = Object::default();
for v in run.all_nl(opt.ns()).await? {
tmp.insert(v.name.to_owned(), v.to_string().into());
for v in run.all_dl(opt.ns(), opt.db()).await? {
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
Value::from(res).ok()
}
@ -129,7 +129,7 @@ impl InfoStatement {
// Process the tokens
let mut tmp = Object::default();
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());
// Ok all good
@ -147,7 +147,7 @@ impl InfoStatement {
// Process the events
let mut tmp = Object::default();
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());
// Process the fields
@ -159,13 +159,13 @@ impl InfoStatement {
// Process the indexs
let mut tmp = Object::default();
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());
// Process the tables
let mut tmp = Object::default();
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());
// Ok all good
@ -213,14 +213,14 @@ fn db(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, _) = shouldbespace(i)?;
let (i, scope) = ident_raw(i)?;
let (i, scope) = ident(i)?;
Ok((i, InfoStatement::Sc(scope)))
}
fn tb(i: &str) -> IResult<&str, InfoStatement> {
let (i, _) = alt((tag_no_case("TABLE"), tag_no_case("TB")))(i)?;
let (i, _) = shouldbespace(i)?;
let (i, table) = ident_raw(i)?;
let (i, table) = ident(i)?;
Ok((i, InfoStatement::Tb(table)))
}
@ -255,7 +255,7 @@ mod tests {
let res = info(sql);
assert!(res.is_ok());
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));
}
@ -265,7 +265,7 @@ mod tests {
let res = info(sql);
assert!(res.is_ok());
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));
}
}

View file

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

View file

@ -1,4 +1,5 @@
use crate::sql::error::IResult;
use crate::sql::escape::escape_strand;
use nom::branch::alt;
use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not;
@ -49,7 +50,7 @@ impl Strand {
impl fmt::Display for Strand {
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::escape;
use crate::sql::common::val_char;
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 serde::{Deserialize, Serialize};
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 {
type Target = String;
fn deref(&self) -> &Self::Target {
@ -41,7 +46,7 @@ impl Deref for Table {
impl fmt::Display for Table {
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::escape::escape_ident;
use crate::sql::id::{id, Id};
use crate::sql::ident::ident_raw;
use crate::sql::number::Number;
@ -45,8 +44,7 @@ impl From<(String, Number)> for Thing {
impl fmt::Display for Thing {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let t = escape(&self.tb, &val_char, "`");
write!(f, "{}:{}", t, self.id)
write!(f, "{}:{}", escape_ident(&self.tb), self.id)
}
}