From 4f742a3a0ffb8d23a2b932ef3eaefb68eac64c41 Mon Sep 17 00:00:00 2001 From: meteorgan Date: Sun, 15 Jun 2025 22:16:28 +0800 Subject: [PATCH] Implement RowData opcode --- core/vdbe/execute.rs | 30 ++++++++++++++++++++++++++++++ core/vdbe/explain.rs | 10 +++++++++- core/vdbe/insn.rs | 7 +++++++ core/vdbe/mod.rs | 2 +- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 3f82581be..2dbf0c98e 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -1916,6 +1916,36 @@ pub fn op_blob( Ok(InsnFunctionStepResult::Step) } +pub fn op_row_data( + program: &Program, + state: &mut ProgramState, + insn: &Insn, + pager: &Rc, + mv_store: Option<&Rc>, +) -> Result { + let Insn::RowData { cursor_id, dest } = insn else { + unreachable!("unexpected Insn {:?}", insn) + }; + + let record = { + let mut cursor_ref = + must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "RowData"); + let cursor = cursor_ref.as_btree_mut(); + let record_option = return_if_io!(cursor.record()); + + let ret = record_option + .ok_or_else(|| LimboError::InternalError("RowData: cursor has no record".to_string()))? + .clone(); + ret + }; + + let reg = &mut state.registers[*dest]; + *reg = Register::Record(record); + + state.pc += 1; + Ok(InsnFunctionStepResult::Step) +} + pub fn op_row_id( program: &Program, state: &mut ProgramState, diff --git a/core/vdbe/explain.rs b/core/vdbe/explain.rs index b76185ebb..27e3432cb 100644 --- a/core/vdbe/explain.rs +++ b/core/vdbe/explain.rs @@ -1601,7 +1601,15 @@ pub fn insn_to_str( 0, Value::build_text(""), 0, - format!("roots={:?} message_register={}", roots, message_register), + format!("roots={:?} message_register={}", roots, message_register)), + Insn::RowData { cursor_id, dest } => ( + "RowData", + *cursor_id as i32, + *dest as i32, + 0, + Value::build_text(""), + 0, + format!("r[{}] = data", *dest), ), }; format!( diff --git a/core/vdbe/insn.rs b/core/vdbe/insn.rs index dd5cc9831..54a565fc5 100644 --- a/core/vdbe/insn.rs +++ b/core/vdbe/insn.rs @@ -510,6 +510,12 @@ pub enum Insn { dest: usize, }, + /// Read a complete row of data from the current cursor and write it to the destination register. + RowData { + cursor_id: CursorID, + dest: usize, + }, + /// Read the rowid of the current row. RowId { cursor_id: CursorID, @@ -1034,6 +1040,7 @@ impl Insn { Insn::RealAffinity { .. } => execute::op_real_affinity, Insn::String8 { .. } => execute::op_string8, Insn::Blob { .. } => execute::op_blob, + Insn::RowData { .. } => execute::op_row_data, Insn::RowId { .. } => execute::op_row_id, Insn::IdxRowId { .. } => execute::op_idx_row_id, Insn::SeekRowid { .. } => execute::op_seek_rowid, diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 046715e4d..3010781f8 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -317,7 +317,7 @@ impl ProgramState { self.json_cache.clear() } - pub fn get_cursor<'a>(&'a self, cursor_id: CursorID) -> std::cell::RefMut<'a, Cursor> { + pub fn get_cursor(&self, cursor_id: CursorID) -> std::cell::RefMut { let cursors = self.cursors.borrow_mut(); std::cell::RefMut::map(cursors, |c| { c.get_mut(cursor_id)