diff --git a/core/translate/expr.rs b/core/translate/expr.rs index 6a536fff3..393f93d9f 100644 --- a/core/translate/expr.rs +++ b/core/translate/expr.rs @@ -674,11 +674,29 @@ pub fn resolve_ident_qualified( .columns .iter() .enumerate() - .find(|(_, col)| col.name == *ident); + .find(|(_, col)| col.name == *ident) + .map(|(idx, col)| (idx, col.ty, col.primary_key)); + let mut idx; + let mut col_type; + let mut is_primary_key; if res.is_some() { - let (idx, col) = res.unwrap(); + (idx, col_type, is_primary_key) = res.unwrap(); + // overwrite if cursor hint is provided + if let Some(cursor_hint) = cursor_hint { + let cols = &program.cursor_ref[cursor_hint].1; + if let Some(res) = cols.as_ref().and_then(|res| { + res.columns() + .iter() + .enumerate() + .find(|x| x.1.name == format!("{}.{}", table_name, ident)) + }) { + idx = res.0; + col_type = res.1.ty; + is_primary_key = res.1.primary_key; + } + } let cursor_id = program.resolve_cursor_id(&join.identifier, cursor_hint); - return Ok((idx, col.ty, cursor_id, col.primary_key)); + return Ok((idx, col_type, cursor_id, is_primary_key)); } } } diff --git a/core/translate/mod.rs b/core/translate/mod.rs index 148e0d922..70ea5600d 100644 --- a/core/translate/mod.rs +++ b/core/translate/mod.rs @@ -244,8 +244,15 @@ fn translate_sorter( ty: crate::schema::Type::Null, }); } - _ => { - todo!(); + ast::Expr::Qualified(table_name, ident) => { + pseudo_columns.push(Column { + name: normalize_ident(format!("{}.{}", table_name.0, ident.0).as_str()), + primary_key: false, + ty: crate::schema::Type::Null, + }); + } + other => { + todo!("translate_sorter: {:?}", other); } }, ast::ResultColumn::Star => {} diff --git a/core/types.rs b/core/types.rs index 4eabbb10a..256aa1475 100644 --- a/core/types.rs +++ b/core/types.rs @@ -88,6 +88,8 @@ impl std::cmp::PartialOrd for OwnedValue { blob_left.partial_cmp(blob_right) } (OwnedValue::Null, OwnedValue::Null) => Some(std::cmp::Ordering::Equal), + (OwnedValue::Null, _) => Some(std::cmp::Ordering::Less), + (_, OwnedValue::Null) => Some(std::cmp::Ordering::Greater), _ => None, } } diff --git a/testing/join.test b/testing/join.test index 7e361e9cc..4c2f4358d 100755 --- a/testing/join.test +++ b/testing/join.test @@ -124,6 +124,15 @@ do_execsql_test left-join-no-join-conditions-but-multiple-where { } {Jamie|hat Cindy|cap} +do_execsql_test left-join-order-by-qualified { + select users.first_name, products.name from users left join products on users.id = products.id where users.first_name like 'Jam%' order by null limit 2; +} {Jamie|hat +James|} + +do_execsql_test left-join-order-by-qualified-nullable-sorting-col { + select users.first_name, products.name from users left join products on users.id = products.id order by products.name limit 1; +} {Alan|} + do_execsql_test four-way-inner-join { select u1.first_name, u2.first_name, u3.first_name, u4.first_name from users u1 join users u2 on u1.id = u2.id join users u3 on u2.id = u3.id + 1 join users u4 on u3.id = u4.id + 1 limit 1; } {Tommy|Tommy|Cindy|Jamie} diff --git a/testing/orderby.test b/testing/orderby.test index d9dcc6874..e5da7072b 100644 --- a/testing/orderby.test +++ b/testing/orderby.test @@ -41,3 +41,7 @@ do_execsql_test basic-order-by-and-limit-3 { 78.0|jeans 82.0|sneakers 74.0|sweatshirt} + +do_execsql_test order-by-qualified { + select u.first_name from users u order by u.first_name limit 1; +} {Aaron}