mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-01 15:34:19 +01:00
Merge 'Support referring to rowid as _rowid_ or oid' from Jussi Saurio
Closes #3283 Closes #3289
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use crate::function::Func;
|
||||
use crate::incremental::view::IncrementalView;
|
||||
use crate::translate::expr::{bind_and_rewrite_expr, walk_expr, ParamState, WalkControl};
|
||||
use crate::translate::planner::ROWID_STRS;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
/// Simple view structure for non-materialized views
|
||||
@@ -1792,7 +1793,7 @@ impl Index {
|
||||
// Unqualified identifier: must be a column of the target table or ROWID
|
||||
Expr::Id(Name::Ident(n)) | Expr::Id(Name::Quoted(n)) => {
|
||||
let n = n.as_str();
|
||||
if !n.eq_ignore_ascii_case("rowid") && !has_col(n) {
|
||||
if !ROWID_STRS.iter().any(|s| s.eq_ignore_ascii_case(n)) && !has_col(n) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use crate::translate::expr::{
|
||||
ReturningValueRegisters, WalkControl,
|
||||
};
|
||||
use crate::translate::plan::{DeletePlan, JoinedTable, Plan, QueryDestination, Search};
|
||||
use crate::translate::planner::ROWID_STRS;
|
||||
use crate::translate::result_row::try_fold_expr_to_i64;
|
||||
use crate::translate::values::emit_values;
|
||||
use crate::translate::window::{emit_window_results, init_window, WindowMetadata};
|
||||
@@ -1817,7 +1818,10 @@ fn rewrite_where_for_update_registers(
|
||||
}
|
||||
Expr::Id(ast::Name::Ident(name)) | Expr::Id(ast::Name::Quoted(name)) => {
|
||||
let normalized = normalize_ident(name.as_str());
|
||||
if normalized.eq_ignore_ascii_case("rowid") {
|
||||
if ROWID_STRS
|
||||
.iter()
|
||||
.any(|s| s.eq_ignore_ascii_case(&normalized))
|
||||
{
|
||||
*e = Expr::Register(rowid_reg);
|
||||
} else if let Some((idx, c)) = columns.iter().enumerate().find(|(_, c)| {
|
||||
c.name
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::translate::expr::{
|
||||
ParamState, ReturningValueRegisters, WalkControl,
|
||||
};
|
||||
use crate::translate::plan::TableReferences;
|
||||
use crate::translate::planner::ROWID;
|
||||
use crate::translate::planner::ROWID_STRS;
|
||||
use crate::translate::upsert::{
|
||||
collect_set_clauses_for_upsert, emit_upsert, resolve_upsert_target, ResolvedUpsertTarget,
|
||||
};
|
||||
@@ -1038,8 +1038,8 @@ impl InsertionKey<'_> {
|
||||
.as_ref()
|
||||
.expect("rowid alias column must be present")
|
||||
.as_str(),
|
||||
InsertionKey::LiteralRowid { .. } => ROWID,
|
||||
InsertionKey::Autogenerated { .. } => ROWID,
|
||||
InsertionKey::LiteralRowid { .. } => ROWID_STRS[0],
|
||||
InsertionKey::Autogenerated { .. } => ROWID_STRS[0],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1128,7 +1128,10 @@ fn build_insertion<'a>(
|
||||
} else {
|
||||
column_mappings[idx_in_table].value_index = Some(value_index);
|
||||
}
|
||||
} else if column_name == ROWID {
|
||||
} else if ROWID_STRS
|
||||
.iter()
|
||||
.any(|s| s.eq_ignore_ascii_case(&column_name))
|
||||
{
|
||||
// Explicit use of the 'rowid' keyword
|
||||
if let Some(col_in_table) = table.columns().iter().find(|c| c.is_rowid_alias) {
|
||||
insertion_key = InsertionKey::RowidAlias(ColMapping {
|
||||
@@ -1406,7 +1409,7 @@ pub fn rewrite_partial_index_where(
|
||||
insertion: &Insertion,
|
||||
) -> crate::Result<WalkControl> {
|
||||
let col_reg = |name: &str| -> Option<usize> {
|
||||
if name.eq_ignore_ascii_case("rowid") {
|
||||
if ROWID_STRS.iter().any(|s| s.eq_ignore_ascii_case(name)) {
|
||||
Some(insertion.key_register())
|
||||
} else if let Some(c) = insertion.get_col_mapping_by_name(name) {
|
||||
if c.column.is_rowid_alias {
|
||||
|
||||
@@ -30,7 +30,8 @@ use turso_parser::ast::{
|
||||
self, As, Expr, FromClause, JoinType, Materialized, Over, QualifiedName, TableInternalId, With,
|
||||
};
|
||||
|
||||
pub const ROWID: &str = "rowid";
|
||||
/// Valid ways to refer to the rowid of a btree table.
|
||||
pub const ROWID_STRS: [&str; 3] = ["rowid", "_rowid_", "oid"];
|
||||
|
||||
/// This function walks the expression tree and identifies aggregate
|
||||
/// and window functions.
|
||||
@@ -1094,7 +1095,10 @@ pub fn parse_row_id<F>(
|
||||
where
|
||||
F: FnOnce() -> bool,
|
||||
{
|
||||
if column_name.eq_ignore_ascii_case(ROWID) {
|
||||
if ROWID_STRS
|
||||
.iter()
|
||||
.any(|s| s.eq_ignore_ascii_case(column_name))
|
||||
{
|
||||
if fn_check() {
|
||||
crate::bail_parse_error!("ROWID is ambiguous");
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use turso_parser::ast::{self, Upsert};
|
||||
use crate::error::SQLITE_CONSTRAINT_PRIMARYKEY;
|
||||
use crate::translate::expr::{walk_expr, WalkControl};
|
||||
use crate::translate::insert::format_unique_violation_desc;
|
||||
use crate::translate::planner::ROWID_STRS;
|
||||
use crate::vdbe::insn::CmpInsFlags;
|
||||
use crate::{
|
||||
bail_parse_error,
|
||||
@@ -895,7 +896,7 @@ fn rewrite_expr_to_registers(
|
||||
|
||||
// Map a column name to a register within the row image at `base_start`.
|
||||
let col_reg_from_row_image = |name: &str| -> Option<usize> {
|
||||
if name.eq_ignore_ascii_case("rowid") {
|
||||
if ROWID_STRS.iter().any(|s| s.eq_ignore_ascii_case(name)) {
|
||||
return Some(rowid_reg);
|
||||
}
|
||||
let (idx, c) = table.get_column_by_name(name)?;
|
||||
@@ -917,7 +918,7 @@ fn rewrite_expr_to_registers(
|
||||
// Handle EXCLUDED.* if enabled
|
||||
if allow_excluded && ns.eq_ignore_ascii_case("excluded") {
|
||||
if let Some(ins) = insertion {
|
||||
if c.eq_ignore_ascii_case("rowid") {
|
||||
if ROWID_STRS.iter().any(|s| s.eq_ignore_ascii_case(&c)) {
|
||||
*expr = Expr::Register(ins.key_register());
|
||||
} else if let Some(cm) = ins.get_col_mapping_by_name(&c) {
|
||||
*expr = Expr::Register(cm.register);
|
||||
|
||||
@@ -766,4 +766,24 @@ foreach {testname limit ans} {
|
||||
} {
|
||||
do_execsql_test limit-complex-exprs-$testname \
|
||||
"SELECT id FROM users ORDER BY id LIMIT $limit" $ans
|
||||
}
|
||||
}
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} rowid-references {
|
||||
CREATE TABLE test_table (id INTEGER);
|
||||
INSERT INTO test_table VALUES (5),(5);
|
||||
SELECT
|
||||
rowid, "rowid", `rowid`, [rowid], _rowid_, "_rowid_", `_rowid_`, [_rowid_], oid, "oid", `oid`, [oid]
|
||||
FROM test_table
|
||||
WHERE rowid = 2
|
||||
AND "rowid" = 2
|
||||
AND `rowid` = 2
|
||||
AND [rowid] = 2
|
||||
AND _rowid_ = 2
|
||||
AND "_rowid_" = 2
|
||||
AND `_rowid_` = 2
|
||||
AND [_rowid_] = 2
|
||||
AND oid = 2
|
||||
AND "oid" = 2
|
||||
AND `oid` = 2
|
||||
AND [oid] = 2;
|
||||
} {2|2|2|2|2|2|2|2|2|2|2|2}
|
||||
Reference in New Issue
Block a user