From f6d829f52dd444df28ee78dd2d2f66459b21383b Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Tue, 30 Sep 2025 13:06:25 +0400 Subject: [PATCH] simplify upsert codegen --- core/translate/insert.rs | 41 ++++++++-------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/core/translate/insert.rs b/core/translate/insert.rs index a1af7b8f0..1b1e17c79 100644 --- a/core/translate/insert.rs +++ b/core/translate/insert.rs @@ -23,7 +23,7 @@ use crate::translate::upsert::{ }; use crate::util::normalize_ident; use crate::vdbe::builder::ProgramBuilderOpts; -use crate::vdbe::insn::{CmpInsFlags, IdxInsertFlags, InsertFlags, RegisterOrLiteral}; +use crate::vdbe::insn::{IdxInsertFlags, InsertFlags, RegisterOrLiteral}; use crate::vdbe::BranchOffset; use crate::{ schema::{Column, Schema}, @@ -137,7 +137,7 @@ pub fn translate_insert( let root_page = btree_table.root_page; let mut values: Option>> = None; - let mut upsert_actions: Vec<(ResolvedUpsertTarget, Box)> = Vec::new(); + let mut upsert_actions: Vec<(ResolvedUpsertTarget, BranchOffset, Box)> = Vec::new(); let upsert_matched_idx_reg = program.alloc_register(); let mut inserting_multiple_rows = false; @@ -210,6 +210,7 @@ pub fn translate_insert( upsert_actions.push(( // resolve the constrained target for UPSERT in the chain resolve_upsert_target(resolver.schema, &table, &upsert)?, + program.allocate_label(), upsert, )); *upsert_opt = next; @@ -432,7 +433,6 @@ pub fn translate_insert( let insertion = build_insertion(&mut program, &table, &columns, num_values)?; - let upsert_entry = program.allocate_label(); let conflict_rowid_reg = program.alloc_register(); if inserting_multiple_rows { @@ -641,7 +641,7 @@ pub fn translate_insert( // Conflict on rowid: attempt to route through UPSERT if it targets the PK, otherwise raise constraint. // emit Halt for every case *except* when upsert handles the conflict 'emit_halt: { - for (i, (target, _)) in upsert_actions.iter().enumerate() { + for (i, (target, label, _)) in upsert_actions.iter().enumerate() { match target { ResolvedUpsertTarget::CatchAll | ResolvedUpsertTarget::PrimaryKey => { program.emit_int(i as i64, upsert_matched_idx_reg); @@ -651,9 +651,7 @@ pub fn translate_insert( dst_reg: conflict_rowid_reg, extra_amount: 0, }); - program.emit_insn(Insn::Goto { - target_pc: upsert_entry, - }); + program.emit_insn(Insn::Goto { target_pc: *label }); break 'emit_halt; } _ => {} @@ -779,7 +777,7 @@ pub fn translate_insert( }); // Conflict detected, figure out if this UPSERT handles the conflict - for (i, (target, upsert)) in upsert_actions.iter().enumerate() { + for (i, (target, label, upsert)) in upsert_actions.iter().enumerate() { match target { ResolvedUpsertTarget::CatchAll => {} ResolvedUpsertTarget::Index(tgt) if Arc::ptr_eq(tgt, index) => {} @@ -799,9 +797,7 @@ pub fn translate_insert( cursor_id: idx_cursor_id, dest: conflict_rowid_reg, }); - program.emit_insn(Insn::Goto { - target_pc: upsert_entry, - }); + program.emit_insn(Insn::Goto { target_pc: *label }); } } break; @@ -1081,10 +1077,7 @@ pub fn translate_insert( target_pc: row_done_label, }); - let mut upsert_action_labels = Vec::new(); - for (_, mut upsert) in upsert_actions { - let label = program.allocate_label(); - upsert_action_labels.push(label); + for (_, label, mut upsert) in upsert_actions { program.preassign_label_to_next_insn(label); if let UpsertDo::Set { @@ -1117,24 +1110,6 @@ pub fn translate_insert( } } - // Normal INSERT path is done above - // Any conflict routed to UPSERT jumps past all that to here: - program.preassign_label_to_next_insn(upsert_entry); - - for (i, label) in upsert_action_labels.iter().enumerate() { - let upsert_action_id = program.alloc_register(); - program.emit_int(i as i64, upsert_action_id); - program.mark_last_insn_constant(); - - program.emit_insn(Insn::Eq { - lhs: upsert_matched_idx_reg, - rhs: upsert_action_id, - target_pc: *label, - flags: CmpInsFlags::default(), - collation: None, - }); - } - if inserting_multiple_rows { if let Some(temp_table_ctx) = temp_table_ctx { program.resolve_label(row_done_label, program.offset());