Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support CREATE TABLE x AS TABLE y #704

Merged
merged 14 commits into from Dec 1, 2022
2 changes: 1 addition & 1 deletion src/ast/mod.rs
Expand Up @@ -32,7 +32,7 @@ pub use self::ddl::{
pub use self::operator::{BinaryOperator, UnaryOperator};
pub use self::query::{
Cte, Fetch, Join, JoinConstraint, JoinOperator, LateralView, LockType, Offset, OffsetRows,
OrderByExpr, Query, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier,
OrderByExpr, Query, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Table,
TableAlias, TableFactor, TableWithJoins, Top, Values, With,
};
pub use self::value::{escape_quoted_string, DateTimeField, TrimWhereField, Value};
Expand Down
18 changes: 17 additions & 1 deletion src/ast/query.rs
Expand Up @@ -84,7 +84,7 @@ pub enum SetExpr {
},
Values(Values),
Insert(Statement),
// TODO: ANSI SQL supports `TABLE` here.
Table(Box<Table>),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

impl fmt::Display for SetExpr {
Expand All @@ -94,6 +94,7 @@ impl fmt::Display for SetExpr {
SetExpr::Query(q) => write!(f, "({})", q),
SetExpr::Values(v) => write!(f, "{}", v),
SetExpr::Insert(v) => write!(f, "{}", v),
SetExpr::Table(t) => write!(f, "{}", t),
SetExpr::SetOperation {
left,
right,
Expand Down Expand Up @@ -152,6 +153,21 @@ impl fmt::Display for SetQuantifier {
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Table {
sarahyurick marked this conversation as resolved.
Show resolved Hide resolved
pub table_name: String,
// pub schema_name: String,
sarahyurick marked this conversation as resolved.
Show resolved Hide resolved
}

impl fmt::Display for Table {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TABLE {}", self.table_name,)?;
Ok(())
}
}

/// A restricted variant of `SELECT` (without CTEs/`ORDER BY`), which may
/// appear either as the only body item of a `Query`, or as an operand
/// to a set operation like `UNION`.
Expand Down
44 changes: 44 additions & 0 deletions src/parser.rs
Expand Up @@ -4180,6 +4180,23 @@ impl<'a> Parser<'a> {
SetExpr::Query(Box::new(subquery))
} else if self.parse_keyword(Keyword::VALUES) {
SetExpr::Values(self.parse_values()?)
} else if self.parse_keyword(Keyword::TABLE) {
self.next_token();
match &self.tokens[0] {
sarahyurick marked this conversation as resolved.
Show resolved Hide resolved
Token::Word(w) => {
if w.keyword == Keyword::CREATE {
SetExpr::Table(Box::new(self.parse_as_table()?))
} else {
return self.expected(
"CREATE statement",
Token::SingleQuotedString(w.value.clone()),
);
}
}
unexpected => {
return self.expected("CREATE TABLE ... AS TABLE ...", unexpected.clone())
}
}
} else {
return self.expected(
"SELECT, VALUES, or a subquery in the query body",
Expand Down Expand Up @@ -4378,6 +4395,33 @@ impl<'a> Parser<'a> {
})
}

/// Parse `CREATE TABLE x AS TABLE y`
pub fn parse_as_table(&mut self) -> Result<Table, ParserError> {
let mut as_flag = false;
let mut table_flag = false;
let mut table_name = "";
// Grab the table name after `AS TABLE ...`
for token in self.tokens.iter() {
if let Token::Word(w) = token {
if w.keyword == Keyword::AS {
as_flag = true;
} else if w.keyword == Keyword::TABLE && as_flag {
table_flag = true;
} else if as_flag && table_flag {
table_name = &w.value;
as_flag = false;
table_flag = false;
} else if w.keyword != Keyword::TABLE && as_flag {
as_flag = false;
}
}
}

Ok(Table {
table_name: table_name.to_string(),
})
}

pub fn parse_set(&mut self) -> Result<Statement, ParserError> {
let modifier =
self.parse_one_of_keywords(&[Keyword::SESSION, Keyword::LOCAL, Keyword::HIVEVAR]);
Expand Down
24 changes: 24 additions & 0 deletions tests/sqlparser_common.rs
Expand Up @@ -2153,6 +2153,30 @@ fn parse_create_table_as() {
}
}

#[test]
fn parse_create_table_as_table() {
let sql = "CREATE TABLE new_table AS TABLE old_table";

let expected_query = Box::new(Query {
with: None,
body: Box::new(SetExpr::Table(Box::new(Table {
table_name: "old_table".to_string(),
}))),
order_by: vec![],
limit: None,
offset: None,
fetch: None,
lock: None,
});

match verified_stmt(sql) {
Statement::CreateTable { query, .. } => {
assert_eq!(query.unwrap(), expected_query);
}
_ => unreachable!(),
}
}

#[test]
fn parse_create_table_on_cluster() {
// Using single-quote literal to define current cluster
Expand Down