Skip to content

Commit e61234d

Browse files
authored
Merge 'translate/insert: Implement INSERT OR REPLACE' from Preston Thorpe
This PR implements support for `INSERT OR REPLACE INTO t`. For `OR IGNORE`, we currently rewrite this internally to an `ON CONFLICT DO NOTHING`, and I was hopeful we could do this with OR REPLACE, however it seems SQLite actually deletes the row and then proceeds to insert, so we could not simply rewrite this to an `ON CONFLICT DO UPDATE SET col=excluded.col`, as this would result in differing rowid's when compared to SQLite. Reviewed-by: Jussi Saurio <[email protected]> Closes #3972
2 parents 693eaeb + 56f35ad commit e61234d

File tree

6 files changed

+483
-53
lines changed

6 files changed

+483
-53
lines changed

core/translate/emitter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ pub fn emit_fk_child_decrement_on_delete(
609609
// Parent MISSING, decrement is guarded by FkIfZero to avoid underflow
610610
program.preassign_label_to_next_insn(missing);
611611
program.emit_insn(Insn::Close { cursor_id: pcur });
612-
emit_guarded_fk_decrement(program, done);
612+
emit_guarded_fk_decrement(program, done, true);
613613
program.preassign_label_to_next_insn(done);
614614
} else {
615615
// Probe parent unique index
@@ -657,7 +657,7 @@ pub fn emit_fk_child_decrement_on_delete(
657657
num_regs: n,
658658
});
659659
program.emit_insn(Insn::Close { cursor_id: icur });
660-
emit_guarded_fk_decrement(program, ok);
660+
emit_guarded_fk_decrement(program, ok, true);
661661
program.preassign_label_to_next_insn(ok);
662662
program.emit_insn(Insn::Close { cursor_id: icur });
663663
}

core/translate/fkeys.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ use crate::{
1414
use std::{collections::HashSet, num::NonZeroUsize, sync::Arc};
1515

1616
#[inline]
17-
pub fn emit_guarded_fk_decrement(program: &mut ProgramBuilder, label: BranchOffset) {
17+
pub fn emit_guarded_fk_decrement(
18+
program: &mut ProgramBuilder,
19+
label: BranchOffset,
20+
deferred: bool,
21+
) {
1822
program.emit_insn(Insn::FkIfZero {
19-
deferred: true,
23+
deferred,
2024
target_pc: label,
2125
});
2226
program.emit_insn(Insn::FkCounter {
2327
increment_value: -1,
24-
deferred: true,
28+
deferred,
2529
});
2630
}
2731

@@ -508,7 +512,7 @@ fn emit_fk_parent_key_probe(
508512
(true, ParentProbePass::New) => {
509513
// Guard to avoid underflow if OLD pass didn't increment.
510514
let skip = p.allocate_label();
511-
emit_guarded_fk_decrement(p, skip);
515+
emit_guarded_fk_decrement(p, skip, fk_ref.fk.deferred);
512516
p.preassign_label_to_next_insn(skip);
513517
}
514518
// Immediate FK on NEW pass: nothing to cancel; do nothing.
@@ -676,7 +680,7 @@ pub fn emit_fk_child_update_counters(
676680
program.preassign_label_to_next_insn(miss);
677681
program.emit_insn(Insn::Close { cursor_id: pcur });
678682
let skip = program.allocate_label();
679-
emit_guarded_fk_decrement(program, skip);
683+
emit_guarded_fk_decrement(program, skip, fk_ref.fk.deferred);
680684
program.preassign_label_to_next_insn(skip);
681685

682686
program.preassign_label_to_next_insn(join);
@@ -703,7 +707,7 @@ pub fn emit_fk_child_update_counters(
703707
|_p| Ok(()),
704708
|p| {
705709
let skip = p.allocate_label();
706-
emit_guarded_fk_decrement(p, skip);
710+
emit_guarded_fk_decrement(p, skip, fk_ref.fk.deferred);
707711
p.preassign_label_to_next_insn(skip);
708712
Ok(())
709713
},

0 commit comments

Comments
 (0)