Support views with explicit column names

A `CREATE VIEW` statement may provide names for its columns that
override the names of the columns derived from the view's query.
This commit is contained in:
Nikhil Benesch 2019-05-30 17:06:06 -04:00
parent 2f4cd8f6c8
commit 73ed685879
No known key found for this signature in database
GPG key ID: F7386C5DEADABA7F
3 changed files with 37 additions and 3 deletions

View file

@ -377,6 +377,7 @@ pub enum SQLStatement {
SQLCreateView {
/// View name
name: SQLObjectName,
columns: Vec<SQLIdent>,
query: Box<SQLQuery>,
materialized: bool,
with_options: Vec<SQLOption>,
@ -474,6 +475,7 @@ impl ToString for SQLStatement {
}
SQLStatement::SQLCreateView {
name,
columns,
query,
materialized,
with_options,
@ -484,12 +486,18 @@ impl ToString for SQLStatement {
} else {
"".into()
};
let columns = if !columns.is_empty() {
format!(" ({})", comma_separated_string(columns))
} else {
"".into()
};
format!(
"CREATE{} VIEW {}{} AS {}",
"CREATE{} VIEW {}{}{} AS {}",
modifier,
name.to_string(),
with_options,
query.to_string()
columns,
query.to_string(),
)
}
SQLStatement::SQLCreateTable {

View file

@ -775,7 +775,7 @@ impl Parser {
// Many dialects support `OR REPLACE` | `OR ALTER` right after `CREATE`, but we don't (yet).
// ANSI SQL and Postgres support RECURSIVE here, but we don't support it either.
let name = self.parse_object_name()?;
// Parenthesized "output" columns list could be handled here.
let columns = self.parse_parenthesized_column_list(Optional)?;
let with_options = if self.parse_keyword("WITH") {
self.parse_with_options()?
} else {
@ -786,6 +786,7 @@ impl Parser {
// Optional `WITH [ CASCADED | LOCAL ] CHECK OPTION` is widely supported here.
Ok(SQLStatement::SQLCreateView {
name,
columns,
query,
materialized,
with_options,

View file

@ -1589,11 +1589,13 @@ fn parse_create_view() {
match verified_stmt(sql) {
SQLStatement::SQLCreateView {
name,
columns,
query,
materialized,
with_options,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::<SQLIdent>::new(), columns);
assert_eq!("SELECT foo FROM bar", query.to_string());
assert!(!materialized);
assert_eq!(with_options, vec![]);
@ -1625,17 +1627,40 @@ fn parse_create_view_with_options() {
}
}
#[test]
fn parse_create_view_with_columns() {
let sql = "CREATE VIEW v (has, cols) AS SELECT 1, 2";
match verified_stmt(sql) {
SQLStatement::SQLCreateView {
name,
columns,
with_options,
query,
materialized,
} => {
assert_eq!("v", name.to_string());
assert_eq!(columns, vec!["has".to_string(), "cols".to_string()]);
assert_eq!(with_options, vec![]);
assert_eq!("SELECT 1, 2", query.to_string());
assert!(!materialized);
}
_ => unreachable!(),
}
}
#[test]
fn parse_create_materialized_view() {
let sql = "CREATE MATERIALIZED VIEW myschema.myview AS SELECT foo FROM bar";
match verified_stmt(sql) {
SQLStatement::SQLCreateView {
name,
columns,
query,
materialized,
with_options,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::<SQLIdent>::new(), columns);
assert_eq!("SELECT foo FROM bar", query.to_string());
assert!(materialized);
assert_eq!(with_options, vec![]);