mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-06 09:44:21 +01:00
support NATURAL JOIN
This commit is contained in:
@@ -62,6 +62,7 @@ This document describes the SQLite compatibility status of Limbo:
|
||||
| SELECT ... INNER JOIN | Partial | |
|
||||
| SELECT ... OUTER JOIN | Partial | |
|
||||
| SELECT ... JOIN USING | Yes | |
|
||||
| SELECT ... NATURAL JOIN | Yes | |
|
||||
| UPDATE | No | |
|
||||
| UPSERT | No | |
|
||||
| VACUUM | No | |
|
||||
|
||||
@@ -582,19 +582,54 @@ fn parse_join(
|
||||
|
||||
tables.push(table.clone());
|
||||
|
||||
let outer = match operator {
|
||||
let (outer, natural) = match operator {
|
||||
ast::JoinOperator::TypedJoin(Some(join_type)) => {
|
||||
if join_type == JoinType::LEFT | JoinType::OUTER {
|
||||
true
|
||||
} else {
|
||||
join_type == JoinType::RIGHT | JoinType::OUTER
|
||||
}
|
||||
let is_outer = join_type.contains(JoinType::OUTER);
|
||||
let is_natural = join_type.contains(JoinType::NATURAL);
|
||||
(is_outer, is_natural)
|
||||
}
|
||||
_ => false,
|
||||
_ => (false, false),
|
||||
};
|
||||
|
||||
let mut using = None;
|
||||
let mut predicates = None;
|
||||
|
||||
if natural && constraint.is_some() {
|
||||
crate::bail_parse_error!("NATURAL JOIN cannot be combined with ON or USING clause");
|
||||
}
|
||||
|
||||
let constraint = if natural {
|
||||
// NATURAL JOIN is first transformed into a USING join with the common columns
|
||||
let left_table = &tables[table_index - 1];
|
||||
let right_table = &tables[table_index];
|
||||
let left_cols = &left_table.table.columns;
|
||||
let right_cols = &right_table.table.columns;
|
||||
let mut distinct_names = None;
|
||||
// TODO: O(n^2) maybe not great for large tables
|
||||
for left_col in left_cols.iter() {
|
||||
for right_col in right_cols.iter() {
|
||||
if left_col.name == right_col.name {
|
||||
if distinct_names.is_none() {
|
||||
distinct_names =
|
||||
Some(ast::DistinctNames::new(ast::Name(left_col.name.clone())));
|
||||
} else {
|
||||
distinct_names
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.insert(ast::Name(left_col.name.clone()))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if distinct_names.is_none() {
|
||||
crate::bail_parse_error!("No columns found to NATURAL join on");
|
||||
}
|
||||
Some(ast::JoinConstraint::Using(distinct_names.unwrap()))
|
||||
} else {
|
||||
constraint
|
||||
};
|
||||
|
||||
if let Some(constraint) = constraint {
|
||||
match constraint {
|
||||
ast::JoinConstraint::On(expr) => {
|
||||
|
||||
@@ -220,4 +220,11 @@ do_execsql_test join-using {
|
||||
select * from users join products using (id) limit 3;
|
||||
} {"1|Jamie|Foster|dylan00@example.com|496-522-9493|62375 Johnson Rest Suite 322|West Lauriestad|IL|35865|94|hat|79.0
|
||||
2|Cindy|Salazar|williamsrebecca@example.com|287-934-1135|75615 Stacey Shore|South Stephanie|NC|85181|37|cap|82.0
|
||||
3|Tommy|Perry|warechristopher@example.org|001-288-554-8139x0276|2896 Paul Fall Apt. 972|Michaelborough|VA|15691|18|shirt|18.0"}
|
||||
|
||||
# NATURAL JOIN desugars to JOIN USING (common_column1, common_column2...)
|
||||
do_execsql_test join-using {
|
||||
select * from users natural join products limit 3;
|
||||
} {"1|Jamie|Foster|dylan00@example.com|496-522-9493|62375 Johnson Rest Suite 322|West Lauriestad|IL|35865|94|hat|79.0
|
||||
2|Cindy|Salazar|williamsrebecca@example.com|287-934-1135|75615 Stacey Shore|South Stephanie|NC|85181|37|cap|82.0
|
||||
3|Tommy|Perry|warechristopher@example.org|001-288-554-8139x0276|2896 Paul Fall Apt. 972|Michaelborough|VA|15691|18|shirt|18.0"}
|
||||
Reference in New Issue
Block a user