Skip to content

Commit

Permalink
Merge branch 'main' into cte3
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Aug 11, 2022
2 parents 9e38d64 + 4af8546 commit 2d1cff4
Show file tree
Hide file tree
Showing 277 changed files with 7,217 additions and 3,604 deletions.
31 changes: 30 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions common/ast/src/ast/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ pub struct Query<'a> {
pub struct With<'a> {
pub span: &'a [Token<'a>],
pub recursive: bool,
pub ctes: Vec<Cte<'a>>,
pub ctes: Vec<CTE<'a>>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct Cte<'a> {
pub struct CTE<'a> {
pub span: &'a [Token<'a>],
pub alias: TableAlias<'a>,
pub query: Query<'a>,
Expand Down Expand Up @@ -428,7 +428,7 @@ impl<'a> Display for SetExpr<'a> {
}
}

impl<'a> Display for Cte<'a> {
impl<'a> Display for CTE<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} AS ({})", self.alias, self.query)?;
Ok(())
Expand Down
31 changes: 31 additions & 0 deletions common/ast/src/ast/statements/share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::fmt::Formatter;

use common_meta_app::share::ShareGrantObjectName;
use common_meta_app::share::ShareGrantObjectPrivilege;
use itertools::Itertools;

use crate::ast::Identifier;

Expand Down Expand Up @@ -96,3 +97,33 @@ impl Display for RevokeShareObjectStmt<'_> {
Ok(())
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AlterShareTenantsStmt<'a> {
pub share: Identifier<'a>,
pub if_exists: bool,
pub tenants: Vec<Identifier<'a>>,
pub is_add: bool,
}

impl Display for AlterShareTenantsStmt<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "ALTER SHARE ")?;
if self.if_exists {
write!(f, "IF EXISTS ")?;
}
write!(f, "{}", self.share)?;
if self.is_add {
write!(f, " ADD TENANTS = ")?;
} else {
write!(f, " REMOVE TENANTS = ")?;
}
write!(
f,
"{}",
self.tenants.iter().map(|v| v.to_string()).join(",")
)?;

Ok(())
}
}
2 changes: 2 additions & 0 deletions common/ast/src/ast/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub enum Statement<'a> {
DropShare(DropShareStmt<'a>),
GrantShareObject(GrantShareObjectStmt<'a>),
RevokeShareObject(RevokeShareObjectStmt<'a>),
AlterShareTenants(AlterShareTenantsStmt<'a>),
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -368,6 +369,7 @@ impl<'a> Display for Statement<'a> {
Statement::DropShare(stmt) => write!(f, "{stmt}")?,
Statement::GrantShareObject(stmt) => write!(f, "{stmt}")?,
Statement::RevokeShareObject(stmt) => write!(f, "{stmt}")?,
Statement::AlterShareTenants(stmt) => write!(f, "{stmt}")?,
}
Ok(())
}
Expand Down
6 changes: 3 additions & 3 deletions common/ast/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl<'a> nom::error::ParseError<Input<'a>> for Error<'a> {
span: i[0].clone(),
errors: vec![],
contexts: vec![],
backtrace: i.1,
backtrace: i.2,
}
}

Expand Down Expand Up @@ -122,7 +122,7 @@ impl<'a> nom::error::ContextError<Input<'a>> for Error<'a> {

impl<'a> Error<'a> {
pub fn from_error_kind(input: Input<'a>, kind: ErrorKind) -> Self {
let mut inner = input.1.inner.borrow_mut();
let mut inner = input.2.inner.borrow_mut();
if let Some(ref mut inner) = *inner {
match input.0[0].span.start.cmp(&inner.span.span.start) {
Ordering::Equal => {
Expand All @@ -147,7 +147,7 @@ impl<'a> Error<'a> {
span: input.0[0].clone(),
errors: vec![kind],
contexts: vec![],
backtrace: input.1,
backtrace: input.2,
}
}
}
Expand Down
32 changes: 28 additions & 4 deletions common/ast/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::Backtrace;
/// Input tokens slice with a backtrace that records all errors including
/// the optional branch.
#[derive(Debug, Clone, Copy)]
pub struct Input<'a>(pub &'a [Token<'a>], pub &'a Backtrace<'a>);
pub struct Input<'a>(pub &'a [Token<'a>], pub Dialect, pub &'a Backtrace<'a>);

impl<'a> std::ops::Deref for Input<'a> {
type Target = [Token<'a>];
Expand All @@ -50,19 +50,19 @@ impl<'a> nom::Offset for Input<'a> {

impl<'a> nom::Slice<Range<usize>> for Input<'a> {
fn slice(&self, range: Range<usize>) -> Self {
Input(&self.0[range], self.1)
Input(&self.0[range], self.1, self.2)
}
}

impl<'a> nom::Slice<RangeTo<usize>> for Input<'a> {
fn slice(&self, range: RangeTo<usize>) -> Self {
Input(&self.0[range], self.1)
Input(&self.0[range], self.1, self.2)
}
}

impl<'a> nom::Slice<RangeFrom<usize>> for Input<'a> {
fn slice(&self, range: RangeFrom<usize>) -> Self {
Input(&self.0[range], self.1)
Input(&self.0[range], self.1, self.2)
}
}

Expand All @@ -77,3 +77,27 @@ pub struct WithSpan<'a, T> {
pub(crate) span: Input<'a>,
pub(crate) elem: T,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Dialect {
#[default]
PostgreSQL,
MySQL,
}

impl Dialect {
pub fn is_ident_quote(&self, c: char) -> bool {
match self {
Dialect::MySQL => c == '`',
// TODO: remove '`' quote support once mysql handler correctly set mysql dialect.
Dialect::PostgreSQL => c == '"' || c == '`',
}
}

pub fn is_string_quote(&self, c: char) -> bool {
match self {
Dialect::MySQL => c == '\'' || c == '"',
Dialect::PostgreSQL => c == '\'',
}
}
}
9 changes: 9 additions & 0 deletions common/ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,16 @@ pub use error::DisplayError;
pub use error::Error;
pub use error::ErrorKind;

mod visitors;
pub use visitors::walk_expr;
pub use visitors::walk_expr_mut;
pub use visitors::walk_query;
pub use visitors::walk_query_mut;
pub use visitors::Visitor;
pub use visitors::VisitorMut;

mod input;
pub use input::Dialect;
pub use input::Input;

mod util;
Expand Down
8 changes: 7 additions & 1 deletion common/ast/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,13 @@ pub fn literal_string(i: Input) -> IResult<String> {
QuotedString
},
|token| {
if token.text().starts_with('\'') {
if token
.text()
.chars()
.next()
.filter(|c| i.1.is_string_quote(*c))
.is_some()
{
let str = &token.text()[1..token.text().len() - 1];
let unescaped =
unescape(str, '\'').ok_or(ErrorKind::Other("invalid escape or unicode"))?;
Expand Down
10 changes: 7 additions & 3 deletions common/ast/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use common_exception::Result;
use self::expr::subexpr;
use crate::ast::Expr;
use crate::ast::Statement;
use crate::input::Dialect;
use crate::input::Input;
use crate::parser::statement::statement;
use crate::parser::token::Token;
Expand All @@ -40,9 +41,10 @@ pub fn tokenize_sql(sql: &str) -> Result<Vec<Token>> {
/// Parse a SQL string into `Statement`s.
pub fn parse_sql<'a>(
sql_tokens: &'a [Token<'a>],
dialect: Dialect,
backtrace: &'a Backtrace<'a>,
) -> Result<(Statement<'a>, Option<String>)> {
match statement(Input(sql_tokens, backtrace)) {
match statement(Input(sql_tokens, dialect, backtrace)) {
Ok((rest, stmts)) if rest[0].kind == TokenKind::EOI => Ok((stmts.stmt, stmts.format)),
Ok((rest, _)) => Err(ErrorCode::SyntaxException(
rest[0].display_error("unable to parse rest of the sql".to_string()),
Expand All @@ -57,9 +59,10 @@ pub fn parse_sql<'a>(
/// Parse udf function into Expr
pub fn parse_expr<'a>(
sql_tokens: &'a [Token<'a>],
dialect: Dialect,
backtrace: &'a Backtrace<'a>,
) -> Result<Expr<'a>> {
match expr::expr(Input(sql_tokens, backtrace)) {
match expr::expr(Input(sql_tokens, dialect, backtrace)) {
Ok((rest, expr)) if rest[0].kind == TokenKind::EOI => Ok(expr),
Ok((rest, _)) => Err(ErrorCode::SyntaxException(
rest[0].display_error("unable to parse rest of the sql".to_string()),
Expand All @@ -73,10 +76,11 @@ pub fn parse_expr<'a>(

pub fn parse_comma_separated_exprs<'a>(
sql_tokens: &'a [Token<'a>],
dialect: Dialect,
backtrace: &'a Backtrace<'a>,
) -> Result<Vec<Expr<'a>>> {
let mut comma_separated_exprs_parser = comma_separated_list0(subexpr(0));
match comma_separated_exprs_parser(Input(sql_tokens, backtrace)) {
match comma_separated_exprs_parser(Input(sql_tokens, dialect, backtrace)) {
Ok((_rest, exprs)) => Ok(exprs),
Err(nom::Err::Error(err) | nom::Err::Failure(err)) => {
Err(ErrorCode::SyntaxException(err.display_error(())))
Expand Down
2 changes: 1 addition & 1 deletion common/ast/src/parser/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn with(i: Input) -> IResult<With> {
consumed(rule! {
#table_alias ~ AS ~ "(" ~ #query ~ ")"
}),
|(span, (table_alias, _, _, query, _))| Cte {
|(span, (table_alias, _, _, query, _))| CTE {
span: span.0,
alias: table_alias,
query,
Expand Down
18 changes: 18 additions & 0 deletions common/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,19 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
})
},
);
let alter_share_tenants = map(
rule! {
ALTER ~ SHARE ~ (IF ~ EXISTS )? ~ #ident ~ #alter_add_share_accounts ~ TENANTS ~ Eq ~ #comma_separated_list1(ident)
},
|(_, _, opt_if_exists, share, is_add, _, _, tenants)| {
Statement::AlterShareTenants(AlterShareTenantsStmt {
share,
if_exists: opt_if_exists.is_some(),
is_add,
tenants,
})
},
);

let statement_body = alt((
rule!(
Expand Down Expand Up @@ -886,6 +899,7 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
| #drop_share: "`DROP SHARE [IF EXISTS] <share_name>`"
| #grant_share_object: "`GRANT { USAGE | SELECT | REFERENCE_USAGE } ON { DATABASE db | TABLE db.table } TO SHARE <share_name>`"
| #revoke_share_object: "`REVOKE { USAGE | SELECT | REFERENCE_USAGE } ON { DATABASE db | TABLE db.table } FROM SHARE <share_name>`"
| #alter_share_tenants: "`ALTER SHARE [IF EXISTS] <share_name> { ADD | REMOVE } TENANTS = tenant [, tenant, ...]`"
),
));

Expand Down Expand Up @@ -1054,6 +1068,10 @@ pub fn priv_share_type(i: Input) -> IResult<ShareGrantObjectPrivilege> {
))(i)
}

pub fn alter_add_share_accounts(i: Input) -> IResult<bool> {
alt((value(true, rule! { ADD }), value(false, rule! { REMOVE })))(i)
}

pub fn grant_share_object_name(i: Input) -> IResult<ShareGrantObjectName> {
let database = map(
rule! {
Expand Down
4 changes: 4 additions & 0 deletions common/ast/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ pub enum TokenKind {
// reserved list.
#[token("ALL", ignore(ascii_case))]
ALL,
#[token("ADD", ignore(ascii_case))]
ADD,
#[token("ANY", ignore(ascii_case))]
ANY,
#[token("SOME", ignore(ascii_case))]
Expand Down Expand Up @@ -625,6 +627,8 @@ pub enum TokenKind {
TEXT,
#[token("TENANTSETTING", ignore(ascii_case))]
TENANTSETTING,
#[token("TENANTS", ignore(ascii_case))]
TENANTS,
#[token("THEN", ignore(ascii_case))]
THEN,
#[token("TIMESTAMP", ignore(ascii_case))]
Expand Down
Loading

0 comments on commit 2d1cff4

Please sign in to comment.