mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
Merge 'core: constraint check uniqueness' from Pere Diaz Bou
```bash limbo> insert into products values (1, 'asdf', 432); Runtime error: UNIQUE constraint failed: products.id (19) ``` Closes #336
This commit is contained in:
commit
b67640c437
6 changed files with 56 additions and 9 deletions
|
@ -36,6 +36,8 @@ pub enum LimboError {
|
|||
InvalidTime(String),
|
||||
#[error("Modifier parsing error: {0}")]
|
||||
InvalidModifier(String),
|
||||
#[error("Runtime error: {0}")]
|
||||
Constraint(String),
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -51,3 +53,6 @@ macro_rules! bail_corrupt_error {
|
|||
return Err($crate::error::LimboError::Corrupt(format!($($arg)*)))
|
||||
};
|
||||
}
|
||||
|
||||
pub const SQLITE_CONSTRAINT: usize = 19;
|
||||
pub const SQLITE_CONSTRAINT_PRIMARYKEY: usize = SQLITE_CONSTRAINT | (6 << 8);
|
||||
|
|
|
@ -1453,7 +1453,10 @@ fn epilogue(
|
|||
start_offset: BranchOffset,
|
||||
) -> Result<()> {
|
||||
program.resolve_label(halt_label, program.offset());
|
||||
program.emit_insn(Insn::Halt);
|
||||
program.emit_insn(Insn::Halt {
|
||||
err_code: 0,
|
||||
description: String::new(),
|
||||
});
|
||||
|
||||
program.resolve_label(init_label, program.offset());
|
||||
program.emit_insn(Insn::Transaction);
|
||||
|
|
|
@ -4,6 +4,7 @@ use sqlite3_parser::ast::{
|
|||
DistinctNames, InsertBody, QualifiedName, ResolveType, ResultColumn, With,
|
||||
};
|
||||
|
||||
use crate::error::SQLITE_CONSTRAINT_PRIMARYKEY;
|
||||
use crate::Result;
|
||||
use crate::{
|
||||
schema::{Schema, Table},
|
||||
|
@ -167,7 +168,15 @@ pub fn translate_insert(
|
|||
},
|
||||
make_record_label,
|
||||
);
|
||||
program.emit_insn(Insn::Halt); // Add error code 1555 and rollback
|
||||
// TODO: rollback
|
||||
program.emit_insn(Insn::Halt {
|
||||
err_code: SQLITE_CONSTRAINT_PRIMARYKEY,
|
||||
description: format!(
|
||||
"{}.{}",
|
||||
table.get_name(),
|
||||
table.column_index_to_name(0).unwrap()
|
||||
),
|
||||
});
|
||||
program.resolve_label(make_record_label, program.offset());
|
||||
program.emit_insn(Insn::MakeRecord {
|
||||
start_reg: column_registers_start + 1,
|
||||
|
@ -188,7 +197,10 @@ pub fn translate_insert(
|
|||
});
|
||||
|
||||
program.resolve_label(halt_label, program.offset());
|
||||
program.emit_insn(Insn::Halt);
|
||||
program.emit_insn(Insn::Halt {
|
||||
err_code: 0,
|
||||
description: String::new(),
|
||||
});
|
||||
program.resolve_label(init_label, program.offset());
|
||||
program.emit_insn(Insn::Transaction);
|
||||
program.emit_constant_insns();
|
||||
|
|
|
@ -135,7 +135,10 @@ fn translate_pragma(
|
|||
todo!()
|
||||
}
|
||||
};
|
||||
program.emit_insn(Insn::Halt);
|
||||
program.emit_insn(Insn::Halt {
|
||||
err_code: 0,
|
||||
description: String::new(),
|
||||
});
|
||||
program.resolve_label(init_label, program.offset());
|
||||
program.emit_insn(Insn::Transaction);
|
||||
program.emit_constant_insns();
|
||||
|
|
|
@ -383,9 +383,12 @@ pub fn insn_to_str(
|
|||
0,
|
||||
"".to_string(),
|
||||
),
|
||||
Insn::Halt => (
|
||||
Insn::Halt {
|
||||
err_code,
|
||||
description: _,
|
||||
} => (
|
||||
"Halt",
|
||||
0,
|
||||
*err_code as i32,
|
||||
0,
|
||||
0,
|
||||
OwnedValue::Text(Rc::new("".to_string())),
|
||||
|
|
|
@ -23,7 +23,7 @@ pub mod sorter;
|
|||
|
||||
mod datetime;
|
||||
|
||||
use crate::error::LimboError;
|
||||
use crate::error::{LimboError, SQLITE_CONSTRAINT_PRIMARYKEY};
|
||||
use crate::function::{AggFunc, FuncCtx, JsonFunc, ScalarFunc};
|
||||
use crate::json::get_json;
|
||||
use crate::pseudo::PseudoCursor;
|
||||
|
@ -232,7 +232,10 @@ pub enum Insn {
|
|||
},
|
||||
|
||||
// Halt the program.
|
||||
Halt,
|
||||
Halt {
|
||||
err_code: usize,
|
||||
description: String,
|
||||
},
|
||||
|
||||
// Start a transaction.
|
||||
Transaction,
|
||||
|
@ -1001,7 +1004,25 @@ impl Program {
|
|||
state.pc += 1;
|
||||
}
|
||||
}
|
||||
Insn::Halt => {
|
||||
Insn::Halt {
|
||||
err_code,
|
||||
description,
|
||||
} => {
|
||||
match *err_code {
|
||||
0 => {}
|
||||
SQLITE_CONSTRAINT_PRIMARYKEY => {
|
||||
return Err(LimboError::Constraint(format!(
|
||||
"UNIQUE constraint failed: {} (19)",
|
||||
description
|
||||
)));
|
||||
}
|
||||
_ => {
|
||||
return Err(LimboError::Constraint(format!(
|
||||
"undocumented halt error code {}",
|
||||
description
|
||||
)));
|
||||
}
|
||||
}
|
||||
pager.end_read_tx()?;
|
||||
return Ok(StepResult::Done);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue