From 86ea224069c5e886646ab9ef90aa21c7763d9468 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Sun, 15 Jun 2025 00:21:15 -0300 Subject: [PATCH 1/3] add delete where basic functionality --- core/translate/emitter.rs | 24 +++++++++++++++++++++++- testing/delete.test | 16 ++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) mode change 100644 => 100755 testing/delete.test diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index 00dd9c0bc..24390c3ac 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -422,7 +422,7 @@ fn emit_program_for_delete( &mut plan.where_clause, )?; - emit_delete_insns(program, &mut t_ctx, &plan.table_references)?; + emit_delete_insns(program, &mut t_ctx, &plan.table_references, &plan)?; // Clean up and close the main execution loop close_loop( @@ -444,6 +444,7 @@ fn emit_delete_insns( program: &mut ProgramBuilder, t_ctx: &mut TranslateCtx, table_references: &TableReferences, + plan: &DeletePlan, ) -> Result<()> { let table_reference = table_references.joined_tables().first().unwrap(); let cursor_id = match &table_reference.op { @@ -465,6 +466,27 @@ fn emit_delete_insns( let main_table_cursor_id = program.resolve_cursor_id(&CursorKey::table(table_reference.internal_id)); + for cond in plan + .where_clause + .iter() + .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) + { + let jump_target = program.allocate_label(); + let meta = ConditionMetadata { + jump_if_condition_is_true: false, + jump_target_when_true: jump_target, + jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), + }; + translate_condition_expr( + program, + &plan.table_references, + &cond.expr, + meta, + &t_ctx.resolver, + )?; + program.preassign_label_to_next_insn(jump_target); + } + // Emit the instructions to delete the row let key_reg = program.alloc_register(); program.emit_insn(Insn::RowId { diff --git a/testing/delete.test b/testing/delete.test old mode 100644 new mode 100755 index 83e523295..45a75c7e9 --- a/testing/delete.test +++ b/testing/delete.test @@ -62,3 +62,19 @@ if {[info exists ::env(SQLITE_EXEC)] && $::env(SQLITE_EXEC) eq "scripts/limbo-sq SELECT * FROM t; } {} } + +do_execsql_test_on_specific_db {:memory:} delete_where_falsy { + CREATE TABLE resourceful_schurz (diplomatic_kaplan BLOB); + INSERT INTO resourceful_schurz VALUES (X'696E646570656E64656E745F6A6165636B6C65'), (X'67656E65726F75735F62617262616E65677261'), (X'73757065725F74616E6E656E6261756D'), (X'6D6F76696E675F6E616F756D6F76'), (X'7374756E6E696E675F6B62'); + INSERT INTO resourceful_schurz VALUES (X'70617373696F6E6174655F726F62696E'), (X'666169746866756C5F74686F6D6173'), (X'76696272616E745F6D69726F736C6176'), (X'737061726B6C696E675F67726179'); + DELETE FROM resourceful_schurz WHERE - x'666169746866756c5f74686f6d6173'; + SELECT * FROM resourceful_schurz; +} {independent_jaeckle +generous_barbanegra +super_tannenbaum +moving_naoumov +stunning_kb +passionate_robin +faithful_thomas +vibrant_miroslav +sparkling_gray} From b1706ae84985c46d6d0e9126413ed9489ecc4b44 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Thu, 19 Jun 2025 13:15:04 -0300 Subject: [PATCH 2/3] change location where WhereTerms are emitted --- core/translate/emitter.rs | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index 24390c3ac..601afe280 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -413,6 +413,27 @@ fn emit_program_for_delete( OperationMode::DELETE, )?; + for cond in plan + .where_clause + .iter() + .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) + { + let jump_target = program.allocate_label(); + let meta = ConditionMetadata { + jump_if_condition_is_true: false, + jump_target_when_true: jump_target, + jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), + }; + translate_condition_expr( + program, + &plan.table_references, + &cond.expr, + meta, + &t_ctx.resolver, + )?; + program.preassign_label_to_next_insn(jump_target); + } + // Set up main query execution loop open_loop( program, @@ -466,27 +487,6 @@ fn emit_delete_insns( let main_table_cursor_id = program.resolve_cursor_id(&CursorKey::table(table_reference.internal_id)); - for cond in plan - .where_clause - .iter() - .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) - { - let jump_target = program.allocate_label(); - let meta = ConditionMetadata { - jump_if_condition_is_true: false, - jump_target_when_true: jump_target, - jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), - }; - translate_condition_expr( - program, - &plan.table_references, - &cond.expr, - meta, - &t_ctx.resolver, - )?; - program.preassign_label_to_next_insn(jump_target); - } - // Emit the instructions to delete the row let key_reg = program.alloc_register(); program.emit_insn(Insn::RowId { From fcff306f98a9b07b275dab37be254f4256a32f57 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Thu, 19 Jun 2025 13:44:33 -0300 Subject: [PATCH 3/3] emit constant where terms in init_loop --- core/translate/emitter.rs | 91 ++----------------------------------- core/translate/main_loop.rs | 15 ++++++ 2 files changed, 20 insertions(+), 86 deletions(-) diff --git a/core/translate/emitter.rs b/core/translate/emitter.rs index 601afe280..df9d73e8e 100644 --- a/core/translate/emitter.rs +++ b/core/translate/emitter.rs @@ -7,7 +7,7 @@ use limbo_sqlite3_parser::ast::{self}; use tracing::{instrument, Level}; use super::aggregation::emit_ungrouped_aggregation; -use super::expr::{translate_condition_expr, translate_expr, ConditionMetadata}; +use super::expr::translate_expr; use super::group_by::{ group_by_agg_phase, group_by_emit_row_phase, init_group_by, GroupByMetadata, GroupByRowSource, }; @@ -295,6 +295,7 @@ pub fn emit_query<'a>( &mut plan.aggregates, plan.group_by.as_ref(), OperationMode::SELECT, + &plan.where_clause, )?; if plan.is_simple_count() { @@ -302,27 +303,6 @@ pub fn emit_query<'a>( return Ok(t_ctx.reg_result_cols_start.unwrap()); } - for where_term in plan - .where_clause - .iter() - .filter(|wt| wt.should_eval_before_loop(&plan.join_order)) - { - let jump_target_when_true = program.allocate_label(); - let condition_metadata = ConditionMetadata { - jump_if_condition_is_true: false, - jump_target_when_false: after_main_loop_label, - jump_target_when_true, - }; - translate_condition_expr( - program, - &plan.table_references, - &where_term.expr, - condition_metadata, - &t_ctx.resolver, - )?; - program.preassign_label_to_next_insn(jump_target_when_true); - } - // Set up main query execution loop open_loop( program, @@ -411,29 +391,9 @@ fn emit_program_for_delete( &mut [], None, OperationMode::DELETE, + &plan.where_clause, )?; - for cond in plan - .where_clause - .iter() - .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) - { - let jump_target = program.allocate_label(); - let meta = ConditionMetadata { - jump_if_condition_is_true: false, - jump_target_when_true: jump_target, - jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), - }; - translate_condition_expr( - program, - &plan.table_references, - &cond.expr, - meta, - &t_ctx.resolver, - )?; - program.preassign_label_to_next_insn(jump_target); - } - // Set up main query execution loop open_loop( program, @@ -443,7 +403,7 @@ fn emit_program_for_delete( &mut plan.where_clause, )?; - emit_delete_insns(program, &mut t_ctx, &plan.table_references, &plan)?; + emit_delete_insns(program, &mut t_ctx, &plan.table_references)?; // Clean up and close the main execution loop close_loop( @@ -465,7 +425,6 @@ fn emit_delete_insns( program: &mut ProgramBuilder, t_ctx: &mut TranslateCtx, table_references: &TableReferences, - plan: &DeletePlan, ) -> Result<()> { let table_reference = table_references.joined_tables().first().unwrap(); let cursor_id = match &table_reference.op { @@ -613,6 +572,7 @@ fn emit_program_for_update( &mut [], None, OperationMode::UPDATE, + &plan.where_clause, )?; // Open indexes for update. let mut index_cursors = Vec::with_capacity(plan.indexes_to_update.len()); @@ -707,26 +667,6 @@ fn emit_update_insns( }, }; - for cond in plan - .where_clause - .iter() - .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) - { - let jump_target = program.allocate_label(); - let meta = ConditionMetadata { - jump_if_condition_is_true: false, - jump_target_when_true: jump_target, - jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), - }; - translate_condition_expr( - program, - &plan.table_references, - &cond.expr, - meta, - &t_ctx.resolver, - )?; - program.preassign_label_to_next_insn(jump_target); - } let beg = program.alloc_registers( table_ref.table.columns().len() + if is_virtual { @@ -793,27 +733,6 @@ fn emit_update_insns( }); } - for cond in plan - .where_clause - .iter() - .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) - { - let jump_target = program.allocate_label(); - let meta = ConditionMetadata { - jump_if_condition_is_true: false, - jump_target_when_true: jump_target, - jump_target_when_false: loop_labels.next, - }; - translate_condition_expr( - program, - &plan.table_references, - &cond.expr, - meta, - &t_ctx.resolver, - )?; - program.preassign_label_to_next_insn(jump_target); - } - // we scan a column at a time, loading either the column's values, or the new value // from the Set expression, into registers so we can emit a MakeRecord and update the row. let start = if is_virtual { beg + 2 } else { beg + 1 }; diff --git a/core/translate/main_loop.rs b/core/translate/main_loop.rs index fd8ec644f..62b515729 100644 --- a/core/translate/main_loop.rs +++ b/core/translate/main_loop.rs @@ -115,6 +115,7 @@ pub fn init_loop( aggregates: &mut [Aggregate], group_by: Option<&GroupBy>, mode: OperationMode, + where_clause: &[WhereTerm], ) -> Result<()> { assert!( t_ctx.meta_left_joins.len() == tables.joined_tables().len(), @@ -334,6 +335,20 @@ pub fn init_loop( } } + for cond in where_clause + .iter() + .filter(|c| c.should_eval_before_loop(&[JoinOrderMember::default()])) + { + let jump_target = program.allocate_label(); + let meta = ConditionMetadata { + jump_if_condition_is_true: false, + jump_target_when_true: jump_target, + jump_target_when_false: t_ctx.label_main_loop_end.unwrap(), + }; + translate_condition_expr(program, &tables, &cond.expr, meta, &t_ctx.resolver)?; + program.preassign_label_to_next_insn(jump_target); + } + Ok(()) }