Skip to content

Commit 50f5c3a

Browse files
committed
Redshift: PartiQL AT <index>
1 parent 073df28 commit 50f5c3a

File tree

7 files changed

+50
-2
lines changed

7 files changed

+50
-2
lines changed

src/ast/query.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,8 @@ pub struct TableAlias {
25272527
pub name: Ident,
25282528
/// Optional column aliases declared in parentheses after the table alias.
25292529
pub columns: Vec<TableAliasColumnDef>,
2530+
/// Optional PartiQL index alias declared with `AT`.
2531+
pub at: Option<Ident>,
25302532
}
25312533

25322534
impl fmt::Display for TableAlias {
@@ -2535,6 +2537,9 @@ impl fmt::Display for TableAlias {
25352537
if !self.columns.is_empty() {
25362538
write!(f, " ({})", display_comma_separated(&self.columns))?;
25372539
}
2540+
if let Some(at) = &self.at {
2541+
write!(f, " AT {at}")?;
2542+
}
25382543
Ok(())
25392544
}
25402545
}

src/ast/spans.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2178,8 +2178,13 @@ impl Spanned for TableAlias {
21782178
explicit: _,
21792179
name,
21802180
columns,
2181+
at,
21812182
} = self;
2182-
union_spans(core::iter::once(name.span).chain(columns.iter().map(Spanned::span)))
2183+
union_spans(
2184+
core::iter::once(name.span)
2185+
.chain(columns.iter().map(Spanned::span))
2186+
.chain(at.iter().map(|at| at.span)),
2187+
)
21832188
}
21842189
}
21852190

src/parser/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12809,10 +12809,16 @@ impl<'a> Parser<'a> {
1280912809
match self.parse_optional_alias_inner(None, validator)? {
1281012810
Some(name) => {
1281112811
let columns = self.parse_table_alias_column_defs()?;
12812+
let at = if self.dialect.supports_partiql() && self.parse_keyword(Keyword::AT) {
12813+
Some(self.parse_identifier()?)
12814+
} else {
12815+
None
12816+
};
1281212817
Ok(Some(TableAlias {
1281312818
explicit,
1281412819
name,
1281512820
columns,
12821+
at,
1281612822
}))
1281712823
}
1281812824
None => Ok(None),
@@ -14461,6 +14467,7 @@ impl<'a> Parser<'a> {
1446114467
explicit: false,
1446214468
name,
1446314469
columns: vec![],
14470+
at: None,
1446414471
},
1446514472
query,
1446614473
from: None,
@@ -14505,6 +14512,7 @@ impl<'a> Parser<'a> {
1450514512
explicit: false,
1450614513
name,
1450714514
columns,
14515+
at: None,
1450814516
},
1450914517
query,
1451014518
from: None,

src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ pub fn table_alias(explicit: bool, name: impl Into<String>) -> Option<TableAlias
374374
explicit,
375375
name: Ident::new(name),
376376
columns: vec![],
377+
at: None,
377378
})
378379
}
379380

tests/sqlparser_common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,7 @@ fn parse_select_with_table_alias() {
666666
TableAliasColumnDef::from_name("B"),
667667
TableAliasColumnDef::from_name("C"),
668668
],
669+
at: None,
669670
}),
670671
args: None,
671672
with_hints: vec![],
@@ -7858,6 +7859,7 @@ fn parse_recursive_cte() {
78587859
span: Span::empty(),
78597860
},
78607861
columns: vec![TableAliasColumnDef::from_name("val")],
7862+
at: None,
78617863
},
78627864
query: Box::new(cte_query),
78637865
from: None,
@@ -11343,6 +11345,7 @@ fn parse_pivot_table() {
1134311345
TableAliasColumnDef::from_name("c"),
1134411346
TableAliasColumnDef::from_name("d"),
1134511347
],
11348+
at: None,
1134611349
})
1134711350
}
1134811351
);
@@ -11481,6 +11484,7 @@ fn parse_unpivot_table() {
1148111484
.into_iter()
1148211485
.map(TableAliasColumnDef::from_name)
1148311486
.collect(),
11487+
at: None,
1148411488
}),
1148511489
};
1148611490
pretty_assertions::assert_eq!(verified_only_select(sql).from[0].relation, base_unpivot);

tests/sqlparser_mssql.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ fn parse_mssql_delimited_identifiers() {
106106
&Some(TableAlias {
107107
explicit: false,
108108
name: Ident::with_quote('[', "WHERE"),
109-
columns: vec![]
109+
columns: vec![],
110+
at: None,
110111
})
111112
);
112113
}

tests/sqlparser_redshift.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,3 +517,27 @@ fn test_null_treatment_inside_and_outside_window_function() {
517517
redshift().verified_stmt("SELECT FIRST_VALUE(1 IGNORE NULLS) OVER () FROM (SELECT 1) t");
518518
redshift().verified_stmt("SELECT FIRST_VALUE(1) IGNORE NULLS OVER () FROM (SELECT 1) t");
519519
}
520+
521+
#[test]
522+
fn test_partiql_from_alias_with_at_index() {
523+
redshift().verified_stmt("SELECT * FROM lineitem AS l (a, b, c) AT idx");
524+
525+
let sql =
526+
"SELECT index, val FROM (SELECT array('AAA', 'BBB') AS val) AS b, b.val AS val AT index";
527+
let select = redshift().verified_only_select(sql);
528+
529+
match &select.from[1].relation {
530+
TableFactor::Table { name, alias, .. } => {
531+
assert_eq!(
532+
name,
533+
&ObjectName::from(vec![Ident::new("b"), Ident::new("val")])
534+
);
535+
assert_eq!(alias.as_ref().map(|a| &a.name), Some(&Ident::new("val")));
536+
assert_eq!(
537+
alias.as_ref().and_then(|a| a.at.as_ref()),
538+
Some(&Ident::new("index"))
539+
);
540+
}
541+
_ => panic!("expected table factor"),
542+
}
543+
}

0 commit comments

Comments
 (0)