Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/ast/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,9 @@ pub struct WildcardAdditionalOptions {
pub opt_replace: Option<ReplaceSelectItem>,
/// `[RENAME ...]`.
pub opt_rename: Option<RenameSelectItem>,
/// `[AS <alias>]`.
/// Redshift syntax: <https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_list.html>
pub opt_alias: Option<Ident>,
}

impl Default for WildcardAdditionalOptions {
Expand All @@ -944,6 +947,7 @@ impl Default for WildcardAdditionalOptions {
opt_except: None,
opt_replace: None,
opt_rename: None,
opt_alias: None,
}
}
}
Expand All @@ -965,6 +969,9 @@ impl fmt::Display for WildcardAdditionalOptions {
if let Some(rename) = &self.opt_rename {
write!(f, " {rename}")?;
}
if let Some(alias) = &self.opt_alias {
write!(f, " AS {alias}")?;
}
Ok(())
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,7 @@ impl Spanned for WildcardAdditionalOptions {
opt_except,
opt_replace,
opt_rename,
opt_alias,
} = self;

union_spans(
Expand All @@ -1832,7 +1833,8 @@ impl Spanned for WildcardAdditionalOptions {
.chain(opt_exclude.as_ref().map(|i| i.span()))
.chain(opt_rename.as_ref().map(|i| i.span()))
.chain(opt_replace.as_ref().map(|i| i.span()))
.chain(opt_except.as_ref().map(|i| i.span())),
.chain(opt_except.as_ref().map(|i| i.span()))
.chain(opt_alias.as_ref().map(|i| i.span)),
)
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,18 @@ pub trait Dialect: Debug + Any {
false
}

/// Returns true if this dialect supports aliasing a wildcard select item.
///
/// Example:
/// ```sql
/// SELECT t.* AS alias FROM t
/// ```
///
/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_SELECT_list.html)
fn supports_select_wildcard_with_alias(&self) -> bool {
false
}

/// Returns true if this dialect supports the `OPTIMIZE TABLE` statement.
///
/// Example:
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/redshift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ impl Dialect for RedshiftSqlDialect {
true
}

fn supports_select_wildcard_with_alias(&self) -> bool {
true
}

fn supports_select_exclude(&self) -> bool {
true
}
Expand Down
11 changes: 11 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17847,13 +17847,24 @@ impl<'a> Parser<'a> {
None
};

let opt_alias = if self.dialect.supports_select_wildcard_with_alias() {
if self.parse_keyword(Keyword::AS) {
Some(self.parse_identifier()?)
} else {
None
}
} else {
None
};

Ok(WildcardAdditionalOptions {
wildcard_token: wildcard_token.into(),
opt_ilike,
opt_exclude,
opt_except,
opt_rename,
opt_replace,
opt_alias,
})
}

Expand Down
20 changes: 20 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,26 @@ fn parse_select_expr_star() {
dialects.verified_only_select("SELECT myfunc().* EXCEPT (foo) FROM T");
}

#[test]
fn parse_select_wildcard_with_alias() {
let dialects = all_dialects_where(|d| d.supports_select_wildcard_with_alias());

// qualified wildcard with alias
dialects
.parse_sql_statements("SELECT t.* AS all_cols FROM t")
.unwrap();

// unqualified wildcard with alias
dialects
.parse_sql_statements("SELECT * AS all_cols FROM t")
.unwrap();

// mixed: regular column + qualified wildcard with alias
dialects
.parse_sql_statements("SELECT a.id, b.* AS b_cols FROM a JOIN b ON (a.id = b.a_id)")
.unwrap();
}

#[test]
fn test_eof_after_as() {
let res = parse_sql_statements("SELECT foo AS");
Expand Down
Loading