Merge 'translate/select: prevent multiple identical non-aliased table references ' from Preston Thorpe

closes https://github.com/tursodatabase/turso/issues/3505

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #3761
This commit is contained in:
Preston Thorpe
2025-10-16 19:03:23 -04:00
committed by GitHub
2 changed files with 41 additions and 1 deletions

View File

@@ -986,9 +986,29 @@ fn parse_join(
crate::bail_parse_error!("NATURAL JOIN cannot be combined with ON or USING clause");
}
// this is called once for each join, so we only need to check the rightmost table
// against all previous tables for duplicates
let rightmost_table = table_references.joined_tables().last().unwrap();
let has_duplicate = table_references
.joined_tables()
.iter()
.take(table_references.joined_tables().len() - 1)
.any(|t| t.identifier == rightmost_table.identifier);
if has_duplicate
&& !natural
&& constraint
.as_ref()
.is_none_or(|c| !matches!(c, ast::JoinConstraint::Using(_)))
{
// Duplicate table names are only allowed for NATURAL or USING joins
crate::bail_parse_error!(
"table name {} specified more than once - use an alias to disambiguate",
rightmost_table.identifier
);
}
let constraint = if natural {
assert!(table_references.joined_tables().len() >= 2);
let rightmost_table = table_references.joined_tables().last().unwrap();
// NATURAL JOIN is first transformed into a USING join with the common columns
let mut distinct_names: Vec<ast::Name> = vec![];
// TODO: O(n^2) maybe not great for large tables or big multiway joins

View File

@@ -1074,3 +1074,23 @@ do_execsql_test_on_specific_db {:memory:} rowid-select-from-clause-subquery-expl
SELECT rowid,a FROM (SELECT rowid,a FROM t);
} {1|abc}
# https://github.com/tursodatabase/turso/issues/3505 regression test
do_execsql_test_in_memory_any_error ambiguous-self-join {
CREATE TABLE T(a);
INSERT INTO t VALUES (1), (2), (3);
SELECT * fROM t JOIN t;
}
do_execsql_test_on_specific_db {:memory:} unambiguous-self-join {
CREATE TABLE T(a);
INSERT INTO t VALUES (1), (2), (3);
SELECT * fROM t as ta JOIN t order by ta.a;
} {1|1
1|2
1|3
2|1
2|2
2|3
3|1
3|2
3|3}