Skip to content

Commit 210a51e

Browse files
committed
sql-passes: Fix star_expansion with table aliases
Previously the star-expansion pass was trying to resolve the schema for the *alias* of an aliased table expr rather than the table itself, which obviously failed to resolve in the schema. This fixes that, by looking up the table itself in the schema, while still using the alias to qualify the fields that we're adding to the select list themselves Fixes: REA-3512 Change-Id: Id91d2533f63b30e3f91b03a297b5222203b12af3 Reviewed-on: https://gerrit.readyset.name/c/readyset/+/6063 Tested-by: Buildkite CI Reviewed-by: Ethan Donowitz <[email protected]>
1 parent 847c0cd commit 210a51e

File tree

1 file changed

+71
-7
lines changed

1 file changed

+71
-7
lines changed

readyset-sql-passes/src/star_expansion.rs

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use nom_sql::{
88
};
99
use readyset_errors::{ReadySetError, ReadySetResult};
1010

11-
use crate::util::{self, outermost_named_tables};
11+
use crate::{outermost_table_exprs, util};
1212

1313
pub trait StarExpansion: Sized {
1414
/// Expand all `*` column references in the query given a map from tables to the lists of
@@ -41,7 +41,7 @@ impl<'ast, 'schema> VisitorMut<'ast> for ExpandStarsVisitor<'schema> {
4141
&select_statement.join,
4242
);
4343

44-
let expand_table = |table: Relation| -> ReadySetResult<_> {
44+
let expand_table = |table: Relation, alias: Option<SqlIdentifier>| -> ReadySetResult<_> {
4545
Ok(if table.schema.is_none() {
4646
// Can only reference subqueries with tables that don't have a schema
4747
subquery_schemas.get(&table.name).cloned()
@@ -69,7 +69,12 @@ impl<'ast, 'schema> VisitorMut<'ast> for ExpandStarsVisitor<'schema> {
6969
.into_iter()
7070
.map(move |f| FieldDefinitionExpr::Expr {
7171
expr: Expr::Column(Column {
72-
table: Some(table.clone()),
72+
table: Some(
73+
alias
74+
.clone()
75+
.map(Relation::from)
76+
.unwrap_or_else(|| table.clone()),
77+
),
7378
name: f.clone(),
7479
}),
7580
alias: None,
@@ -79,14 +84,46 @@ impl<'ast, 'schema> VisitorMut<'ast> for ExpandStarsVisitor<'schema> {
7984
for field in fields {
8085
match field {
8186
FieldDefinitionExpr::All => {
82-
for name in outermost_named_tables(select_statement).collect::<Vec<_>>() {
83-
for field in expand_table(name)? {
84-
select_statement.fields.push(field);
87+
for expr in outermost_table_exprs(select_statement)
88+
.cloned()
89+
.collect::<Vec<_>>()
90+
{
91+
if let Some(tbl) = expr
92+
.inner
93+
.as_table()
94+
.cloned()
95+
.or_else(|| expr.alias.clone().map(Into::into))
96+
{
97+
for field in expand_table(tbl, expr.alias.clone())? {
98+
select_statement.fields.push(field);
99+
}
100+
continue;
85101
}
86102
}
87103
}
88104
FieldDefinitionExpr::AllInTable(t) => {
89-
for field in expand_table(t)? {
105+
let alias = if t.schema.is_none() {
106+
Some(t.name.clone())
107+
} else {
108+
None
109+
};
110+
111+
let tbl = t
112+
.schema
113+
.is_none()
114+
.then(|| {
115+
outermost_table_exprs(select_statement).find_map(|expr| {
116+
if expr.alias.is_some() && expr.alias == alias {
117+
expr.inner.as_table().cloned()
118+
} else {
119+
None
120+
}
121+
})
122+
})
123+
.flatten()
124+
.unwrap_or(t);
125+
126+
for field in expand_table(tbl, alias)? {
90127
select_statement.fields.push(field);
91128
}
92129
}
@@ -159,6 +196,24 @@ mod tests {
159196
);
160197
}
161198

199+
#[test]
200+
fn aliased() {
201+
expands_stars(
202+
"SELECT * FROM PaperTag AS t",
203+
"SELECT t.paper_id, t.tag_id FROM PaperTag AS t",
204+
HashMap::from([("PaperTag".into(), vec!["paper_id".into(), "tag_id".into()])]),
205+
);
206+
}
207+
208+
#[test]
209+
fn referencing_alias() {
210+
expands_stars(
211+
"SELECT t.* FROM PaperTag AS t",
212+
"SELECT t.paper_id, t.tag_id FROM PaperTag AS t",
213+
HashMap::from([("PaperTag".into(), vec!["paper_id".into(), "tag_id".into()])]),
214+
);
215+
}
216+
162217
#[test]
163218
fn multiple_tables() {
164219
expands_stars(
@@ -236,6 +291,15 @@ mod tests {
236291
);
237292
}
238293

294+
#[test]
295+
fn star_with_subquery() {
296+
expands_stars(
297+
"SELECT * FROM (SELECT t1.x FROM t1) sq",
298+
"SELECT sq.x FROM (SELECT t1.x FROM t1) sq",
299+
HashMap::from([("t1".into(), vec!["x".into()])]),
300+
)
301+
}
302+
239303
#[test]
240304
fn simple_join() {
241305
expands_stars(

0 commit comments

Comments
 (0)