Add CREATE TABLE AS support (#206)

We parse it as a regular `CREATE TABLE` statement
followed by an `AS <query>`, which is how BigQuery works:
https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_table_statement


ANSI SQL and PostgreSQL only support a plain list of columns
after the table name in a CTAS
    `CREATE TABLE t (a) AS SELECT a FROM foo`

We currently only allow specifying a full schema with data
types, or omitting it altogether.

https://www.postgresql.org/docs/12/sql-createtableas.html
https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#as-subquery-clause


Finally, when no schema is specified, we print empty parens after a
plain `CREATE TABLE t ();` as required by PostgreSQL, but skip them
in a CTAS: `CREATE TABLE t AS ...`. This affects serialization only,
the parser allows omitting the schema in a regular `CREATE TABLE` too
since the first release of the parser:
7d27abdfb4/src/sqlparser.rs (L325-L332)

Co-authored-by: Nickolay Ponomarev <asqueella@gmail.com>
This commit is contained in:
Daniël Heres 2020-06-23 15:30:22 +02:00 committed by GitHub
parent 26361fd854
commit 15d5f71646
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 26 deletions

View file

@ -43,6 +43,7 @@ fn parse_create_table_with_defaults() {
external: false,
file_format: None,
location: None,
query: _query,
} => {
assert_eq!("public.customer", name.to_string());
assert_eq!(
@ -227,24 +228,46 @@ fn parse_create_table_with_inherit() {
}
#[test]
fn parse_create_table_if_not_exists() {
let sql = "CREATE TABLE IF NOT EXISTS uk_cities ()";
let ast =
pg_and_generic().one_statement_parses_to(sql, "CREATE TABLE IF NOT EXISTS uk_cities ()");
fn parse_create_table_empty() {
// Zero-column tables are weird, but supported by at least PostgreSQL.
// <https://github.com/andygrove/sqlparser-rs/pull/94>
let _ = pg_and_generic().verified_stmt("CREATE TABLE t ()");
}
#[test]
fn parse_create_table_constraints_only() {
// Zero-column tables can also have constraints in PostgreSQL
let sql = "CREATE TABLE t (CONSTRAINT positive CHECK (2 > 1))";
let ast = pg_and_generic().verified_stmt(sql);
match ast {
Statement::CreateTable {
name,
columns: _columns,
columns,
constraints,
with_options,
..
} => {
assert_eq!("t", name.to_string());
assert!(columns.is_empty());
assert_eq!(
only(constraints).to_string(),
"CONSTRAINT positive CHECK (2 > 1)"
);
}
_ => unreachable!(),
};
}
#[test]
fn parse_create_table_if_not_exists() {
let sql = "CREATE TABLE IF NOT EXISTS uk_cities ()";
let ast = pg_and_generic().verified_stmt(sql);
match ast {
Statement::CreateTable {
name,
if_not_exists: true,
external: false,
file_format: None,
location: None,
..
} => {
assert_eq!("uk_cities", name.to_string());
assert!(constraints.is_empty());
assert_eq!(with_options, vec![]);
}
_ => unreachable!(),
}