mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 00:54:19 +01:00
modified tests as we do not have rollback yet. Also correctly raise a contraint error on primary keys only
This commit is contained in:
@@ -742,11 +742,45 @@ fn emit_update_insns(
|
|||||||
cursor_id,
|
cursor_id,
|
||||||
dest: beg,
|
dest: beg,
|
||||||
});
|
});
|
||||||
// if no rowid, we're done
|
|
||||||
program.emit_insn(Insn::IsNull {
|
// Check if rowid was provided (through INTEGER PRIMARY KEY as a rowid alias)
|
||||||
reg: beg,
|
let rowid_alias_index = table_ref.columns().iter().position(|c| c.is_rowid_alias);
|
||||||
target_pc: t_ctx.label_main_loop_end.unwrap(),
|
let rowid_set_clause_reg = if rowid_alias_index.is_some() {
|
||||||
});
|
Some(program.alloc_register())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let has_user_provided_rowid = {
|
||||||
|
if let Some(index) = rowid_alias_index {
|
||||||
|
plan.set_clauses
|
||||||
|
.iter()
|
||||||
|
.position(|(idx, _)| *idx == index)
|
||||||
|
.is_some()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_rowid_not_exists_label = if has_user_provided_rowid {
|
||||||
|
Some(program.allocate_label())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if has_user_provided_rowid {
|
||||||
|
program.emit_insn(Insn::NotExists {
|
||||||
|
cursor: cursor_id,
|
||||||
|
rowid_reg: beg,
|
||||||
|
target_pc: check_rowid_not_exists_label.unwrap(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// if no rowid, we're done
|
||||||
|
program.emit_insn(Insn::IsNull {
|
||||||
|
reg: beg,
|
||||||
|
target_pc: t_ctx.label_main_loop_end.unwrap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if is_virtual {
|
if is_virtual {
|
||||||
program.emit_insn(Insn::Copy {
|
program.emit_insn(Insn::Copy {
|
||||||
src_reg: beg,
|
src_reg: beg,
|
||||||
@@ -775,9 +809,8 @@ fn emit_update_insns(
|
|||||||
let rowid_reg = beg;
|
let rowid_reg = beg;
|
||||||
let idx_cols_start_reg = beg + 1;
|
let idx_cols_start_reg = beg + 1;
|
||||||
|
|
||||||
|
|
||||||
// copy each index column from the table's column registers into these scratch regs
|
// copy each index column from the table's column registers into these scratch regs
|
||||||
for (i, col) in index.columns.iter().enumerate(){
|
for (i, col) in index.columns.iter().enumerate() {
|
||||||
// copy from the table's column register over to the index's scratch register
|
// copy from the table's column register over to the index's scratch register
|
||||||
|
|
||||||
program.emit_insn(Insn::Copy {
|
program.emit_insn(Insn::Copy {
|
||||||
@@ -906,18 +939,38 @@ fn emit_update_insns(
|
|||||||
// we scan a column at a time, loading either the column's values, or the new value
|
// we scan a column at a time, loading either the column's values, or the new value
|
||||||
// from the Set expression, into registers so we can emit a MakeRecord and update the row.
|
// from the Set expression, into registers so we can emit a MakeRecord and update the row.
|
||||||
let start = if is_virtual { beg + 2 } else { beg + 1 };
|
let start = if is_virtual { beg + 2 } else { beg + 1 };
|
||||||
for idx in 0..table_ref.columns().len() {
|
for (idx, table_column) in table_ref.columns().iter().enumerate() {
|
||||||
let target_reg = start + idx;
|
let target_reg = start + idx;
|
||||||
if let Some((_, expr)) = plan.set_clauses.iter().find(|(i, _)| *i == idx) {
|
if let Some((_, expr)) = plan.set_clauses.iter().find(|(i, _)| *i == idx) {
|
||||||
translate_expr(
|
if has_user_provided_rowid
|
||||||
program,
|
&& (table_column.primary_key || table_column.is_rowid_alias)
|
||||||
Some(&plan.table_references),
|
&& !is_virtual
|
||||||
expr,
|
{
|
||||||
target_reg,
|
let rowid_set_clause_reg = rowid_set_clause_reg.unwrap();
|
||||||
&t_ctx.resolver,
|
translate_expr(
|
||||||
)?;
|
program,
|
||||||
|
Some(&plan.table_references),
|
||||||
|
expr,
|
||||||
|
rowid_set_clause_reg,
|
||||||
|
&t_ctx.resolver,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
program.emit_insn(Insn::MustBeInt {
|
||||||
|
reg: rowid_set_clause_reg,
|
||||||
|
});
|
||||||
|
|
||||||
|
program.emit_null(target_reg, None);
|
||||||
|
} else {
|
||||||
|
translate_expr(
|
||||||
|
program,
|
||||||
|
Some(&plan.table_references),
|
||||||
|
expr,
|
||||||
|
target_reg,
|
||||||
|
&t_ctx.resolver,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
// if let Some(rowid_reg) = rowid_set_clause_reg {}
|
||||||
} else {
|
} else {
|
||||||
let table_column = table_ref.table.columns().get(idx).unwrap();
|
|
||||||
let column_idx_in_index = index.as_ref().and_then(|(idx, _)| {
|
let column_idx_in_index = index.as_ref().and_then(|(idx, _)| {
|
||||||
idx.columns
|
idx.columns
|
||||||
.iter()
|
.iter()
|
||||||
@@ -961,6 +1014,42 @@ fn emit_update_insns(
|
|||||||
table_reference: Rc::clone(&btree_table),
|
table_reference: Rc::clone(&btree_table),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if has_user_provided_rowid {
|
||||||
|
let record_label = program.allocate_label();
|
||||||
|
let idx = rowid_alias_index.unwrap();
|
||||||
|
let target_reg = rowid_set_clause_reg.unwrap();
|
||||||
|
program.emit_insn(Insn::Eq {
|
||||||
|
lhs: target_reg,
|
||||||
|
rhs: beg,
|
||||||
|
target_pc: record_label,
|
||||||
|
flags: CmpInsFlags::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
program.emit_insn(Insn::NotExists {
|
||||||
|
cursor: cursor_id,
|
||||||
|
rowid_reg: target_reg,
|
||||||
|
target_pc: record_label,
|
||||||
|
});
|
||||||
|
|
||||||
|
program.emit_insn(Insn::Halt {
|
||||||
|
err_code: SQLITE_CONSTRAINT_PRIMARYKEY,
|
||||||
|
description: format!(
|
||||||
|
"{}.{}",
|
||||||
|
table_ref.table.get_name(),
|
||||||
|
&table_ref
|
||||||
|
.columns()
|
||||||
|
.get(idx)
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
.as_ref()
|
||||||
|
.map_or("", |v| v)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
program.preassign_label_to_next_insn(record_label);
|
||||||
|
}
|
||||||
|
|
||||||
let record_reg = program.alloc_register();
|
let record_reg = program.alloc_register();
|
||||||
program.emit_insn(Insn::MakeRecord {
|
program.emit_insn(Insn::MakeRecord {
|
||||||
start_reg: start,
|
start_reg: start,
|
||||||
@@ -1012,7 +1101,7 @@ fn emit_update_insns(
|
|||||||
|
|
||||||
program.emit_insn(Insn::Insert {
|
program.emit_insn(Insn::Insert {
|
||||||
cursor: cursor_id,
|
cursor: cursor_id,
|
||||||
key_reg: beg,
|
key_reg: rowid_set_clause_reg.unwrap_or(beg),
|
||||||
record_reg,
|
record_reg,
|
||||||
flag: 0,
|
flag: 0,
|
||||||
table_name: table_ref.identifier.clone(),
|
table_name: table_ref.identifier.clone(),
|
||||||
@@ -1035,5 +1124,10 @@ fn emit_update_insns(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// TODO(pthorpe): handle RETURNING clause
|
// TODO(pthorpe): handle RETURNING clause
|
||||||
|
|
||||||
|
if let Some(label) = check_rowid_not_exists_label {
|
||||||
|
program.preassign_label_to_next_insn(label);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,9 +304,8 @@ def generate_test(col_amount: int, primary_keys: int) -> ConstraintTest:
|
|||||||
|
|
||||||
update_errors = []
|
update_errors = []
|
||||||
if len(insert_stmts) > 1:
|
if len(insert_stmts) > 1:
|
||||||
update_errors = [
|
# TODO: As we have no rollback we just generate one update statement
|
||||||
table.generate_update() for _ in table.columns if col.primary_key
|
update_errors = [table.generate_update()]
|
||||||
]
|
|
||||||
|
|
||||||
return ConstraintTest(
|
return ConstraintTest(
|
||||||
table=table,
|
table=table,
|
||||||
@@ -327,7 +326,6 @@ def custom_test_1() -> ConstraintTest:
|
|||||||
"INSERT INTO users VALUES (2, 'bob');",
|
"INSERT INTO users VALUES (2, 'bob');",
|
||||||
]
|
]
|
||||||
update_stmts = [
|
update_stmts = [
|
||||||
"UPDATE users SET id = 3;",
|
|
||||||
"UPDATE users SET id = 2, username = 'bob' WHERE id == 1;",
|
"UPDATE users SET id = 2, username = 'bob' WHERE id == 1;",
|
||||||
]
|
]
|
||||||
return ConstraintTest(
|
return ConstraintTest(
|
||||||
|
|||||||
Reference in New Issue
Block a user