VDBE: NewRowid needs to call next() in case op_not_exists() is not called afterwards

This commit is contained in:
Jussi Saurio
2025-07-07 17:52:10 +03:00
parent 4f0ef663e2
commit 9ee6988fc5

View File

@@ -5195,8 +5195,17 @@ pub enum OpNewRowidState {
Start,
SeekingToLast,
ReadingMaxRowid,
GeneratingRandom { attempts: u32 },
VerifyingCandidate { attempts: u32, candidate: i64 },
GeneratingRandom {
attempts: u32,
},
VerifyingCandidate {
attempts: u32,
candidate: i64,
},
/// In case a rowid was generated and not provided by the user, we need to call next() on the cursor
/// after generating the rowid. This is because the rowid was generated by seeking to the last row in the
/// table, and we need to insert _after_ that row.
GoNext,
}
pub fn op_new_rowid(
@@ -5253,9 +5262,8 @@ pub fn op_new_rowid(
Some(rowid) if rowid < MAX_ROWID => {
// Can use sequential
state.registers[*rowid_reg] = Register::Value(Value::Integer(rowid + 1));
state.op_new_rowid_state = OpNewRowidState::Start;
state.pc += 1;
return Ok(InsnFunctionStepResult::Step);
state.op_new_rowid_state = OpNewRowidState::GoNext;
continue;
}
Some(_) => {
// Must use random (rowid == MAX_ROWID)
@@ -5265,9 +5273,8 @@ pub fn op_new_rowid(
None => {
// Empty table
state.registers[*rowid_reg] = Register::Value(Value::Integer(1));
state.op_new_rowid_state = OpNewRowidState::Start;
state.pc += 1;
return Ok(InsnFunctionStepResult::Step);
state.op_new_rowid_state = OpNewRowidState::GoNext;
continue;
}
}
}
@@ -5318,6 +5325,16 @@ pub fn op_new_rowid(
};
}
}
OpNewRowidState::GoNext => {
{
let mut cursor = state.get_cursor(*cursor);
let cursor = cursor.as_btree_mut();
return_if_io!(cursor.next());
}
state.op_new_rowid_state = OpNewRowidState::Start;
state.pc += 1;
return Ok(InsnFunctionStepResult::Step);
}
}
}
}