mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
Add support for Insn::Once
This commit is contained in:
parent
f79da7194f
commit
9dadc58194
5 changed files with 49 additions and 1 deletions
|
@ -501,7 +501,7 @@ Modifiers:
|
|||
| NotNull | Yes | |
|
||||
| Null | Yes | |
|
||||
| NullRow | Yes | |
|
||||
| Once | No | |
|
||||
| Once | Yes | |
|
||||
| OpenAutoindex | No | |
|
||||
| OpenEphemeral | No | |
|
||||
| OpenPseudo | Yes | |
|
||||
|
|
|
@ -4432,6 +4432,34 @@ pub fn op_open_ephemeral(
|
|||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
/// Execute the [Insn::Once] instruction.
|
||||
///
|
||||
/// This instruction is used to execute a block of code only once.
|
||||
/// If the instruction is executed again, it will jump to the target program counter.
|
||||
pub fn op_once(
|
||||
program: &Program,
|
||||
state: &mut ProgramState,
|
||||
insn: &Insn,
|
||||
pager: &Rc<Pager>,
|
||||
mv_store: Option<&Rc<MvStore>>,
|
||||
) -> Result<InsnFunctionStepResult> {
|
||||
let Insn::Once {
|
||||
target_pc_when_reentered,
|
||||
} = insn
|
||||
else {
|
||||
unreachable!("unexpected Insn: {:?}", insn)
|
||||
};
|
||||
assert!(target_pc_when_reentered.is_offset());
|
||||
let offset = state.pc;
|
||||
if state.once.iter().any(|o| o == offset) {
|
||||
state.pc = target_pc_when_reentered.to_offset_int();
|
||||
return Ok(InsnFunctionStepResult::Step);
|
||||
}
|
||||
state.once.push(offset);
|
||||
state.pc += 1;
|
||||
Ok(InsnFunctionStepResult::Step)
|
||||
}
|
||||
|
||||
fn exec_lower(reg: &OwnedValue) -> Option<OwnedValue> {
|
||||
match reg {
|
||||
OwnedValue::Text(t) => Some(OwnedValue::build_text(&t.as_str().to_lowercase())),
|
||||
|
|
|
@ -1321,6 +1321,17 @@ pub fn insn_to_str(
|
|||
if *is_table { "true" } else { "false" }
|
||||
),
|
||||
),
|
||||
Insn::Once {
|
||||
target_pc_when_reentered,
|
||||
} => (
|
||||
"Once",
|
||||
target_pc_when_reentered.to_debug_int(),
|
||||
0,
|
||||
0,
|
||||
OwnedValue::build_text(""),
|
||||
0,
|
||||
format!("goto {}", target_pc_when_reentered.to_debug_int()),
|
||||
),
|
||||
};
|
||||
format!(
|
||||
"{:<4} {:<17} {:<4} {:<4} {:<4} {:<13} {:<2} {}",
|
||||
|
|
|
@ -780,6 +780,10 @@ pub enum Insn {
|
|||
cursor_id: usize,
|
||||
is_table: bool,
|
||||
},
|
||||
/// Fall through to the next instruction on the first invocation, otherwise jump to target_pc
|
||||
Once {
|
||||
target_pc_when_reentered: BranchOffset,
|
||||
},
|
||||
}
|
||||
|
||||
impl Insn {
|
||||
|
@ -889,6 +893,7 @@ impl Insn {
|
|||
Insn::PageCount { .. } => execute::op_page_count,
|
||||
Insn::ReadCookie { .. } => execute::op_read_cookie,
|
||||
Insn::OpenEphemeral { .. } => execute::op_open_ephemeral,
|
||||
Insn::Once { .. } => execute::op_once,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ use crate::{
|
|||
error::LimboError,
|
||||
fast_lock::SpinLock,
|
||||
function::{AggFunc, FuncCtx},
|
||||
storage::sqlite3_ondisk::SmallVec,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -232,6 +233,8 @@ pub struct ProgramState {
|
|||
last_compare: Option<std::cmp::Ordering>,
|
||||
deferred_seek: Option<(CursorID, CursorID)>,
|
||||
ended_coroutine: Bitfield<4>, // flag to indicate that a coroutine has ended (key is the yield register. currently we assume that the yield register is always between 0-255, YOLO)
|
||||
/// Indicate whether an [Insn::Once] instruction at a given program counter position has already been executed, well, once.
|
||||
once: SmallVec<u32, 4>,
|
||||
regex_cache: RegexCache,
|
||||
pub(crate) mv_tx_id: Option<crate::mvcc::database::TxID>,
|
||||
interrupted: bool,
|
||||
|
@ -254,6 +257,7 @@ impl ProgramState {
|
|||
last_compare: None,
|
||||
deferred_seek: None,
|
||||
ended_coroutine: Bitfield::new(),
|
||||
once: SmallVec::<u32, 4>::new(),
|
||||
regex_cache: RegexCache::new(),
|
||||
mv_tx_id: None,
|
||||
interrupted: false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue