mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 09:04:19 +01:00
Another post-rebase clippy round with 1.88.0
This commit is contained in:
@@ -21,7 +21,7 @@ pub unsafe extern "C" fn db_open(path: *const c_char) -> *mut c_void {
|
|||||||
let path = unsafe { std::ffi::CStr::from_ptr(path) };
|
let path = unsafe { std::ffi::CStr::from_ptr(path) };
|
||||||
let path = path.to_str().unwrap();
|
let path = path.to_str().unwrap();
|
||||||
let Ok((io, conn)) = Connection::from_uri(path, false, false) else {
|
let Ok((io, conn)) = Connection::from_uri(path, false, false) else {
|
||||||
panic!("Failed to open connection with path: {}", path);
|
panic!("Failed to open connection with path: {path}");
|
||||||
};
|
};
|
||||||
LimboConn::new(conn, io).to_ptr()
|
LimboConn::new(conn, io).to_ptr()
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ impl LimboConn {
|
|||||||
|
|
||||||
fn get_error(&mut self) -> *const c_char {
|
fn get_error(&mut self) -> *const c_char {
|
||||||
if let Some(err) = &self.err {
|
if let Some(err) = &self.err {
|
||||||
let err = format!("{}", err);
|
let err = format!("{err}");
|
||||||
let c_str = std::ffi::CString::new(err).unwrap();
|
let c_str = std::ffi::CString::new(err).unwrap();
|
||||||
self.err = None;
|
self.err = None;
|
||||||
c_str.into_raw() as *const c_char
|
c_str.into_raw() as *const c_char
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl From<TursoError> for JniError {
|
|||||||
| TursoError::InvalidDatabasePointer
|
| TursoError::InvalidDatabasePointer
|
||||||
| TursoError::InvalidConnectionPointer
|
| TursoError::InvalidConnectionPointer
|
||||||
| TursoError::JNIErrors(_) => {
|
| TursoError::JNIErrors(_) => {
|
||||||
eprintln!("Error occurred: {:?}", value);
|
eprintln!("Error occurred: {value:?}");
|
||||||
JniError::Other(-1)
|
JniError::Other(-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ impl Database {
|
|||||||
pragma_name: String,
|
pragma_name: String,
|
||||||
options: Option<PragmaOptions>,
|
options: Option<PragmaOptions>,
|
||||||
) -> napi::Result<JsUnknown> {
|
) -> napi::Result<JsUnknown> {
|
||||||
let sql = format!("PRAGMA {}", pragma_name);
|
let sql = format!("PRAGMA {pragma_name}");
|
||||||
let stmt = self.prepare(sql)?;
|
let stmt = self.prepare(sql)?;
|
||||||
match options {
|
match options {
|
||||||
Some(PragmaOptions { simple: true, .. }) => {
|
Some(PragmaOptions { simple: true, .. }) => {
|
||||||
@@ -129,7 +129,7 @@ impl Database {
|
|||||||
| step @ turso_core::StepResult::Busy => {
|
| step @ turso_core::StepResult::Busy => {
|
||||||
return Err(napi::Error::new(
|
return Err(napi::Error::new(
|
||||||
napi::Status::GenericFailure,
|
napi::Status::GenericFailure,
|
||||||
format!("{:?}", step),
|
format!("{step:?}"),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ impl Database {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(napi::Error::new(
|
return Err(napi::Error::new(
|
||||||
"SQLITE_ERROR".to_owned(),
|
"SQLITE_ERROR".to_owned(),
|
||||||
format!("Error executing SQL: {}", err),
|
format!("Error executing SQL: {err}"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ impl Database {
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Err(napi::Error::new(
|
return Err(napi::Error::new(
|
||||||
"SQLITE_ERROR".to_owned(),
|
"SQLITE_ERROR".to_owned(),
|
||||||
format!("Error executing SQL: {}", err),
|
format!("Error executing SQL: {err}"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ impl Cursor {
|
|||||||
let stmt_is_tx = stmt_is_tx(sql);
|
let stmt_is_tx = stmt_is_tx(sql);
|
||||||
|
|
||||||
let statement = self.conn.conn.prepare(sql).map_err(|e| {
|
let statement = self.conn.conn.prepare(sql).map_err(|e| {
|
||||||
PyErr::new::<ProgrammingError, _>(format!("Failed to prepare statement: {:?}", e))
|
PyErr::new::<ProgrammingError, _>(format!("Failed to prepare statement: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let stmt = Rc::new(RefCell::new(statement));
|
let stmt = Rc::new(RefCell::new(statement));
|
||||||
@@ -96,8 +96,7 @@ impl Cursor {
|
|||||||
if stmt_is_dml && self.conn.conn.get_auto_commit() {
|
if stmt_is_dml && self.conn.conn.get_auto_commit() {
|
||||||
self.conn.conn.execute("BEGIN").map_err(|e| {
|
self.conn.conn.execute("BEGIN").map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!(
|
PyErr::new::<OperationalError, _>(format!(
|
||||||
"Failed to start transaction after DDL: {:?}",
|
"Failed to start transaction after DDL: {e:?}"
|
||||||
e
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
@@ -108,10 +107,10 @@ impl Cursor {
|
|||||||
let mut stmt = stmt.borrow_mut();
|
let mut stmt = stmt.borrow_mut();
|
||||||
while let turso_core::StepResult::IO = stmt
|
while let turso_core::StepResult::IO = stmt
|
||||||
.step()
|
.step()
|
||||||
.map_err(|e| PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e)))?
|
.map_err(|e| PyErr::new::<OperationalError, _>(format!("Step error: {e:?}")))?
|
||||||
{
|
{
|
||||||
stmt.run_once()
|
stmt.run_once()
|
||||||
.map_err(|e| PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e)))?;
|
.map_err(|e| PyErr::new::<OperationalError, _>(format!("IO error: {e:?}")))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +129,10 @@ impl Cursor {
|
|||||||
if let Some(smt) = &self.smt {
|
if let Some(smt) = &self.smt {
|
||||||
loop {
|
loop {
|
||||||
let mut stmt = smt.borrow_mut();
|
let mut stmt = smt.borrow_mut();
|
||||||
match stmt.step().map_err(|e| {
|
match stmt
|
||||||
PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e))
|
.step()
|
||||||
})? {
|
.map_err(|e| PyErr::new::<OperationalError, _>(format!("Step error: {e:?}")))?
|
||||||
|
{
|
||||||
turso_core::StepResult::Row => {
|
turso_core::StepResult::Row => {
|
||||||
let row = stmt.row().unwrap();
|
let row = stmt.row().unwrap();
|
||||||
let py_row = row_to_py(py, row)?;
|
let py_row = row_to_py(py, row)?;
|
||||||
@@ -140,7 +140,7 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
turso_core::StepResult::IO => {
|
turso_core::StepResult::IO => {
|
||||||
stmt.run_once().map_err(|e| {
|
stmt.run_once().map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("IO error: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
turso_core::StepResult::Interrupt => {
|
turso_core::StepResult::Interrupt => {
|
||||||
@@ -166,9 +166,10 @@ impl Cursor {
|
|||||||
if let Some(smt) = &self.smt {
|
if let Some(smt) = &self.smt {
|
||||||
loop {
|
loop {
|
||||||
let mut stmt = smt.borrow_mut();
|
let mut stmt = smt.borrow_mut();
|
||||||
match stmt.step().map_err(|e| {
|
match stmt
|
||||||
PyErr::new::<OperationalError, _>(format!("Step error: {:?}", e))
|
.step()
|
||||||
})? {
|
.map_err(|e| PyErr::new::<OperationalError, _>(format!("Step error: {e:?}")))?
|
||||||
|
{
|
||||||
turso_core::StepResult::Row => {
|
turso_core::StepResult::Row => {
|
||||||
let row = stmt.row().unwrap();
|
let row = stmt.row().unwrap();
|
||||||
let py_row = row_to_py(py, row)?;
|
let py_row = row_to_py(py, row)?;
|
||||||
@@ -176,7 +177,7 @@ impl Cursor {
|
|||||||
}
|
}
|
||||||
turso_core::StepResult::IO => {
|
turso_core::StepResult::IO => {
|
||||||
stmt.run_once().map_err(|e| {
|
stmt.run_once().map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("IO error: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("IO error: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
turso_core::StepResult::Interrupt => {
|
turso_core::StepResult::Interrupt => {
|
||||||
@@ -257,7 +258,7 @@ impl Connection {
|
|||||||
|
|
||||||
pub fn close(&self) -> PyResult<()> {
|
pub fn close(&self) -> PyResult<()> {
|
||||||
self.conn.close().map_err(|e| {
|
self.conn.close().map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("Failed to close connection: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("Failed to close connection: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -266,11 +267,11 @@ impl Connection {
|
|||||||
pub fn commit(&self) -> PyResult<()> {
|
pub fn commit(&self) -> PyResult<()> {
|
||||||
if !self.conn.get_auto_commit() {
|
if !self.conn.get_auto_commit() {
|
||||||
self.conn.execute("COMMIT").map_err(|e| {
|
self.conn.execute("COMMIT").map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("Failed to commit: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("Failed to commit: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.conn.execute("BEGIN").map_err(|e| {
|
self.conn.execute("BEGIN").map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("Failed to commit: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("Failed to commit: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -279,11 +280,11 @@ impl Connection {
|
|||||||
pub fn rollback(&self) -> PyResult<()> {
|
pub fn rollback(&self) -> PyResult<()> {
|
||||||
if !self.conn.get_auto_commit() {
|
if !self.conn.get_auto_commit() {
|
||||||
self.conn.execute("ROLLBACK").map_err(|e| {
|
self.conn.execute("ROLLBACK").map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("Failed to commit: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("Failed to commit: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
self.conn.execute("BEGIN").map_err(|e| {
|
self.conn.execute("BEGIN").map_err(|e| {
|
||||||
PyErr::new::<OperationalError, _>(format!("Failed to commit: {:?}", e))
|
PyErr::new::<OperationalError, _>(format!("Failed to commit: {e:?}"))
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -319,8 +320,7 @@ pub fn connect(path: &str) -> Result<Connection> {
|
|||||||
match turso_core::Connection::from_uri(path, false, false) {
|
match turso_core::Connection::from_uri(path, false, false) {
|
||||||
Ok((io, conn)) => Ok(Connection { conn, _io: io }),
|
Ok((io, conn)) => Ok(Connection { conn, _io: io }),
|
||||||
Err(e) => Err(PyErr::new::<ProgrammingError, _>(format!(
|
Err(e) => Err(PyErr::new::<ProgrammingError, _>(format!(
|
||||||
"Failed to create connection: {:?}",
|
"Failed to create connection: {e:?}"
|
||||||
e
|
|
||||||
))
|
))
|
||||||
.into()),
|
.into()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ impl Connection {
|
|||||||
|
|
||||||
rows.iter().try_for_each(|row| {
|
rows.iter().try_for_each(|row| {
|
||||||
f(row).map_err(|e| {
|
f(row).map_err(|e| {
|
||||||
Error::SqlExecutionFailure(format!("Error executing user defined function: {}", e))
|
Error::SqlExecutionFailure(format!("Error executing user defined function: {e}"))
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -500,10 +500,10 @@ mod tests {
|
|||||||
|
|
||||||
let mut original_data = Vec::with_capacity(NUM_INSERTS);
|
let mut original_data = Vec::with_capacity(NUM_INSERTS);
|
||||||
for i in 0..NUM_INSERTS {
|
for i in 0..NUM_INSERTS {
|
||||||
let prefix = format!("test_string_{:04}_", i);
|
let prefix = format!("test_string_{i:04}_");
|
||||||
let padding_len = TARGET_STRING_LEN.saturating_sub(prefix.len());
|
let padding_len = TARGET_STRING_LEN.saturating_sub(prefix.len());
|
||||||
let padding: String = "A".repeat(padding_len);
|
let padding: String = "A".repeat(padding_len);
|
||||||
original_data.push(format!("{}{}", prefix, padding));
|
original_data.push(format!("{prefix}{padding}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, create the database, a table, and insert many large strings
|
// First, create the database, a table, and insert many large strings
|
||||||
@@ -537,12 +537,11 @@ mod tests {
|
|||||||
let row = rows
|
let row = rows
|
||||||
.next()
|
.next()
|
||||||
.await?
|
.await?
|
||||||
.unwrap_or_else(|| panic!("Expected row {} but found None", i));
|
.unwrap_or_else(|| panic!("Expected row {i} but found None"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
row.get_value(0)?,
|
row.get_value(0)?,
|
||||||
Value::Text(value.clone()),
|
Value::Text(value.clone()),
|
||||||
"Mismatch in retrieved data for row {}",
|
"Mismatch in retrieved data for row {i}"
|
||||||
i
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,9 +551,9 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Delete the WAL file only and try to re-open and query
|
// Delete the WAL file only and try to re-open and query
|
||||||
let wal_path = format!("{}-wal", db_path);
|
let wal_path = format!("{db_path}-wal");
|
||||||
std::fs::remove_file(&wal_path)
|
std::fs::remove_file(&wal_path)
|
||||||
.map_err(|e| eprintln!("Warning: Failed to delete WAL file for test: {}", e))
|
.map_err(|e| eprintln!("Warning: Failed to delete WAL file for test: {e}"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Attempt to re-open the database after deleting WAL and assert that table is missing.
|
// Attempt to re-open the database after deleting WAL and assert that table is missing.
|
||||||
@@ -570,13 +569,11 @@ mod tests {
|
|||||||
Err(Error::SqlExecutionFailure(msg)) => {
|
Err(Error::SqlExecutionFailure(msg)) => {
|
||||||
assert!(
|
assert!(
|
||||||
msg.contains("no such table: test_large_persistence"),
|
msg.contains("no such table: test_large_persistence"),
|
||||||
"Expected 'test_large_persistence not found' error, but got: {}",
|
"Expected 'test_large_persistence not found' error, but got: {msg}"
|
||||||
msg
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(e) => panic!(
|
Err(e) => panic!(
|
||||||
"Expected SqlExecutionFailure for 'no such table', but got a different error: {:?}",
|
"Expected SqlExecutionFailure for 'no such table', but got a different error: {e:?}"
|
||||||
e
|
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
cli/app.rs
65
cli/app.rs
@@ -216,7 +216,7 @@ impl Limbo {
|
|||||||
}) {
|
}) {
|
||||||
n if n < 0 => String::from(")x!...>"),
|
n if n < 0 => String::from(")x!...>"),
|
||||||
0 => String::from(" ...> "),
|
0 => String::from(" ...> "),
|
||||||
n if n < 10 => format!("(x{}...> ", n),
|
n if n < 10 => format!("(x{n}...> "),
|
||||||
_ => String::from("(.....> "),
|
_ => String::from("(.....> "),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ impl Limbo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn dump_table(&mut self, name: &str) -> Result<(), LimboError> {
|
fn dump_table(&mut self, name: &str) -> Result<(), LimboError> {
|
||||||
let query = format!("pragma table_info={}", name);
|
let query = format!("pragma table_info={name}");
|
||||||
let mut cols = vec![];
|
let mut cols = vec![];
|
||||||
let mut value_types = vec![];
|
let mut value_types = vec![];
|
||||||
query_internal!(
|
query_internal!(
|
||||||
@@ -248,7 +248,7 @@ impl Limbo {
|
|||||||
// it, but it requires pragma index_list, and it seems to be relevant
|
// it, but it requires pragma index_list, and it seems to be relevant
|
||||||
// only for indexes.
|
// only for indexes.
|
||||||
let cols_str = cols.join(", ");
|
let cols_str = cols.join(", ");
|
||||||
let select = format!("select {} from {}", cols_str, name);
|
let select = format!("select {cols_str} from {name}");
|
||||||
query_internal!(
|
query_internal!(
|
||||||
self,
|
self,
|
||||||
select,
|
select,
|
||||||
@@ -273,14 +273,14 @@ impl Limbo {
|
|||||||
fmt::Write::write_fmt(&mut output, format_args!("{b:02x}"));
|
fmt::Write::write_fmt(&mut output, format_args!("{b:02x}"));
|
||||||
output
|
output
|
||||||
});
|
});
|
||||||
format!("X'{}'", hex_string)
|
format!("X'{hex_string}'")
|
||||||
} else {
|
} else {
|
||||||
value.to_string()
|
value.to_string()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(",");
|
.join(",");
|
||||||
self.write_fmt(format_args!("INSERT INTO {} VALUES({});", name, values))?;
|
self.write_fmt(format_args!("INSERT INTO {name} VALUES({values});"))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
@@ -306,7 +306,7 @@ impl Limbo {
|
|||||||
|row: &turso_core::Row| -> Result<(), LimboError> {
|
|row: &turso_core::Row| -> Result<(), LimboError> {
|
||||||
let sql: &str = row.get::<&str>(2)?;
|
let sql: &str = row.get::<&str>(2)?;
|
||||||
let name: &str = row.get::<&str>(0)?;
|
let name: &str = row.get::<&str>(0)?;
|
||||||
self.write_fmt(format_args!("{};", sql))?;
|
self.write_fmt(format_args!("{sql};"))?;
|
||||||
self.dump_table(name)
|
self.dump_table(name)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -484,7 +484,7 @@ impl Limbo {
|
|||||||
};
|
};
|
||||||
let sample_stats_as_str = |name: &str, samples: Vec<Duration>| {
|
let sample_stats_as_str = |name: &str, samples: Vec<Duration>| {
|
||||||
if samples.is_empty() {
|
if samples.is_empty() {
|
||||||
return format!("{}: No samples available", name);
|
return format!("{name}: No samples available");
|
||||||
}
|
}
|
||||||
let avg_time_spent = samples.iter().sum::<Duration>() / samples.len() as u32;
|
let avg_time_spent = samples.iter().sum::<Duration>() / samples.len() as u32;
|
||||||
let total_time = samples.iter().fold(Duration::ZERO, |acc, x| acc + *x);
|
let total_time = samples.iter().fold(Duration::ZERO, |acc, x| acc + *x);
|
||||||
@@ -561,7 +561,7 @@ impl Limbo {
|
|||||||
let buff = self.input_buff.clone();
|
let buff = self.input_buff.clone();
|
||||||
self.run_query(buff.as_str());
|
self.run_query(buff.as_str());
|
||||||
} else {
|
} else {
|
||||||
self.buffer_input(format!("{}\n", line).as_str());
|
self.buffer_input(format!("{line}\n").as_str());
|
||||||
self.set_multiline_prompt();
|
self.set_multiline_prompt();
|
||||||
}
|
}
|
||||||
self.reset_line(line)?;
|
self.reset_line(line)?;
|
||||||
@@ -608,12 +608,12 @@ impl Limbo {
|
|||||||
if let Some(opcode) = args.opcode {
|
if let Some(opcode) = args.opcode {
|
||||||
for op in &OPCODE_DESCRIPTIONS {
|
for op in &OPCODE_DESCRIPTIONS {
|
||||||
if op.name.eq_ignore_ascii_case(opcode.trim()) {
|
if op.name.eq_ignore_ascii_case(opcode.trim()) {
|
||||||
let _ = self.write_fmt(format_args!("{}", op));
|
let _ = self.write_fmt(format_args!("{op}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for op in &OPCODE_DESCRIPTIONS {
|
for op in &OPCODE_DESCRIPTIONS {
|
||||||
let _ = self.write_fmt(format_args!("{}\n", op));
|
let _ = self.write_fmt(format_args!("{op}\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,13 +622,13 @@ impl Limbo {
|
|||||||
}
|
}
|
||||||
Command::OutputMode(args) => {
|
Command::OutputMode(args) => {
|
||||||
if let Err(e) = self.set_mode(args.mode) {
|
if let Err(e) = self.set_mode(args.mode) {
|
||||||
let _ = self.write_fmt(format_args!("Error: {}", e));
|
let _ = self.write_fmt(format_args!("Error: {e}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::SetOutput(args) => {
|
Command::SetOutput(args) => {
|
||||||
if let Some(path) = args.path {
|
if let Some(path) = args.path {
|
||||||
if let Err(e) = self.set_output_file(&path) {
|
if let Err(e) = self.set_output_file(&path) {
|
||||||
let _ = self.write_fmt(format_args!("Error: {}", e));
|
let _ = self.write_fmt(format_args!("Error: {e}"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.set_output_stdout();
|
self.set_output_stdout();
|
||||||
@@ -655,7 +655,7 @@ impl Limbo {
|
|||||||
}
|
}
|
||||||
Command::Dump => {
|
Command::Dump => {
|
||||||
if let Err(e) = self.dump_database() {
|
if let Err(e) = self.dump_database() {
|
||||||
let _ = self.write_fmt(format_args!("/****** ERROR: {} ******/", e));
|
let _ = self.write_fmt(format_args!("/****** ERROR: {e} ******/"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::ListVfs => {
|
Command::ListVfs => {
|
||||||
@@ -731,8 +731,7 @@ impl Limbo {
|
|||||||
let _ =
|
let _ =
|
||||||
self.writer.write(self.opts.null_value.as_bytes())?;
|
self.writer.write(self.opts.null_value.as_bytes())?;
|
||||||
} else {
|
} else {
|
||||||
let _ =
|
let _ = self.writer.write(format!("{value}").as_bytes())?;
|
||||||
self.writer.write(format!("{}", value).as_bytes())?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = self.writeln("");
|
let _ = self.writeln("");
|
||||||
@@ -764,7 +763,7 @@ impl Limbo {
|
|||||||
}
|
}
|
||||||
let report =
|
let report =
|
||||||
miette::Error::from(err).with_source_code(sql.to_owned());
|
miette::Error::from(err).with_source_code(sql.to_owned());
|
||||||
let _ = self.write_fmt(format_args!("{:?}", report));
|
let _ = self.write_fmt(format_args!("{report:?}"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -808,17 +807,13 @@ impl Limbo {
|
|||||||
(self.opts.null_value.clone(), CellAlignment::Left)
|
(self.opts.null_value.clone(), CellAlignment::Left)
|
||||||
}
|
}
|
||||||
Value::Integer(_) => {
|
Value::Integer(_) => {
|
||||||
(format!("{}", value), CellAlignment::Right)
|
(format!("{value}"), CellAlignment::Right)
|
||||||
}
|
}
|
||||||
Value::Float(_) => {
|
Value::Float(_) => {
|
||||||
(format!("{}", value), CellAlignment::Right)
|
(format!("{value}"), CellAlignment::Right)
|
||||||
}
|
|
||||||
Value::Text(_) => {
|
|
||||||
(format!("{}", value), CellAlignment::Left)
|
|
||||||
}
|
|
||||||
Value::Blob(_) => {
|
|
||||||
(format!("{}", value), CellAlignment::Left)
|
|
||||||
}
|
}
|
||||||
|
Value::Text(_) => (format!("{value}"), CellAlignment::Left),
|
||||||
|
Value::Blob(_) => (format!("{value}"), CellAlignment::Left),
|
||||||
};
|
};
|
||||||
row.add_cell(
|
row.add_cell(
|
||||||
Cell::new(content)
|
Cell::new(content)
|
||||||
@@ -862,21 +857,21 @@ impl Limbo {
|
|||||||
}
|
}
|
||||||
let report =
|
let report =
|
||||||
miette::Error::from(err).with_source_code(sql.to_owned());
|
miette::Error::from(err).with_source_code(sql.to_owned());
|
||||||
let _ = self.write_fmt(format_args!("{:?}", report));
|
let _ = self.write_fmt(format_args!("{report:?}"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !table.is_empty() {
|
if !table.is_empty() {
|
||||||
let _ = self.write_fmt(format_args!("{}", table));
|
let _ = self.write_fmt(format_args!("{table}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let report = miette::Error::from(err).with_source_code(sql.to_owned());
|
let report = miette::Error::from(err).with_source_code(sql.to_owned());
|
||||||
let _ = self.write_fmt(format_args!("{:?}", report));
|
let _ = self.write_fmt(format_args!("{report:?}"));
|
||||||
anyhow::bail!("We have to throw here, even if we printed error");
|
anyhow::bail!("We have to throw here, even if we printed error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -915,7 +910,7 @@ impl Limbo {
|
|||||||
)
|
)
|
||||||
.try_init()
|
.try_init()
|
||||||
{
|
{
|
||||||
println!("Unable to setup tracing appender: {:?}", e);
|
println!("Unable to setup tracing appender: {e:?}");
|
||||||
}
|
}
|
||||||
Ok(guard)
|
Ok(guard)
|
||||||
}
|
}
|
||||||
@@ -923,8 +918,7 @@ impl Limbo {
|
|||||||
fn display_schema(&mut self, table: Option<&str>) -> anyhow::Result<()> {
|
fn display_schema(&mut self, table: Option<&str>) -> anyhow::Result<()> {
|
||||||
let sql = match table {
|
let sql = match table {
|
||||||
Some(table_name) => format!(
|
Some(table_name) => format!(
|
||||||
"SELECT sql FROM sqlite_schema WHERE type IN ('table', 'index') AND tbl_name = '{}' AND name NOT LIKE 'sqlite_%'",
|
"SELECT sql FROM sqlite_schema WHERE type IN ('table', 'index') AND tbl_name = '{table_name}' AND name NOT LIKE 'sqlite_%'"
|
||||||
table_name
|
|
||||||
),
|
),
|
||||||
None => String::from(
|
None => String::from(
|
||||||
"SELECT sql FROM sqlite_schema WHERE type IN ('table', 'index') AND name NOT LIKE 'sqlite_%'"
|
"SELECT sql FROM sqlite_schema WHERE type IN ('table', 'index') AND name NOT LIKE 'sqlite_%'"
|
||||||
@@ -957,7 +951,7 @@ impl Limbo {
|
|||||||
if !found {
|
if !found {
|
||||||
if let Some(table_name) = table {
|
if let Some(table_name) = table {
|
||||||
let _ = self
|
let _ = self
|
||||||
.write_fmt(format_args!("-- Error: Table '{}' not found.", table_name));
|
.write_fmt(format_args!("-- Error: Table '{table_name}' not found."));
|
||||||
} else {
|
} else {
|
||||||
let _ = self.writeln("-- No tables or indexes found in the database.");
|
let _ = self.writeln("-- No tables or indexes found in the database.");
|
||||||
}
|
}
|
||||||
@@ -981,8 +975,7 @@ impl Limbo {
|
|||||||
fn display_indexes(&mut self, maybe_table: Option<String>) -> anyhow::Result<()> {
|
fn display_indexes(&mut self, maybe_table: Option<String>) -> anyhow::Result<()> {
|
||||||
let sql = match maybe_table {
|
let sql = match maybe_table {
|
||||||
Some(ref tbl_name) => format!(
|
Some(ref tbl_name) => format!(
|
||||||
"SELECT name FROM sqlite_schema WHERE type='index' AND tbl_name = '{}' ORDER BY 1",
|
"SELECT name FROM sqlite_schema WHERE type='index' AND tbl_name = '{tbl_name}' ORDER BY 1"
|
||||||
tbl_name
|
|
||||||
),
|
),
|
||||||
None => String::from("SELECT name FROM sqlite_schema WHERE type='index' ORDER BY 1"),
|
None => String::from("SELECT name FROM sqlite_schema WHERE type='index' ORDER BY 1"),
|
||||||
};
|
};
|
||||||
@@ -1030,8 +1023,7 @@ impl Limbo {
|
|||||||
fn display_tables(&mut self, pattern: Option<&str>) -> anyhow::Result<()> {
|
fn display_tables(&mut self, pattern: Option<&str>) -> anyhow::Result<()> {
|
||||||
let sql = match pattern {
|
let sql = match pattern {
|
||||||
Some(pattern) => format!(
|
Some(pattern) => format!(
|
||||||
"SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name LIKE '{}' ORDER BY 1",
|
"SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name LIKE '{pattern}' ORDER BY 1"
|
||||||
pattern
|
|
||||||
),
|
),
|
||||||
None => String::from(
|
None => String::from(
|
||||||
"SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY 1"
|
"SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY 1"
|
||||||
@@ -1066,8 +1058,7 @@ impl Limbo {
|
|||||||
let _ = self.writeln(tables.trim_end());
|
let _ = self.writeln(tables.trim_end());
|
||||||
} else if let Some(pattern) = pattern {
|
} else if let Some(pattern) = pattern {
|
||||||
let _ = self.write_fmt(format_args!(
|
let _ = self.write_fmt(format_args!(
|
||||||
"Error: Tables with pattern '{}' not found.",
|
"Error: Tables with pattern '{pattern}' not found."
|
||||||
pattern
|
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
let _ = self.writeln("No tables found in the database.");
|
let _ = self.writeln("No tables found in the database.");
|
||||||
|
|||||||
@@ -376,8 +376,7 @@ impl Database {
|
|||||||
"io_uring" => Arc::new(UringIO::new()?),
|
"io_uring" => Arc::new(UringIO::new()?),
|
||||||
other => {
|
other => {
|
||||||
return Err(LimboError::InvalidArgument(format!(
|
return Err(LimboError::InvalidArgument(format!(
|
||||||
"no such VFS: {}",
|
"no such VFS: {other}"
|
||||||
other
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -860,7 +859,7 @@ impl Connection {
|
|||||||
if self.closed.get() {
|
if self.closed.get() {
|
||||||
return Err(LimboError::InternalError("Connection closed".to_string()));
|
return Err(LimboError::InternalError("Connection closed".to_string()));
|
||||||
}
|
}
|
||||||
let pragma = format!("PRAGMA {}", pragma_name);
|
let pragma = format!("PRAGMA {pragma_name}");
|
||||||
let mut stmt = self.prepare(pragma)?;
|
let mut stmt = self.prepare(pragma)?;
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
@@ -891,7 +890,7 @@ impl Connection {
|
|||||||
if self.closed.get() {
|
if self.closed.get() {
|
||||||
return Err(LimboError::InternalError("Connection closed".to_string()));
|
return Err(LimboError::InternalError("Connection closed".to_string()));
|
||||||
}
|
}
|
||||||
let pragma = format!("PRAGMA {} = {}", pragma_name, pragma_value);
|
let pragma = format!("PRAGMA {pragma_name} = {pragma_value}");
|
||||||
let mut stmt = self.prepare(pragma)?;
|
let mut stmt = self.prepare(pragma)?;
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
@@ -924,7 +923,7 @@ impl Connection {
|
|||||||
if self.closed.get() {
|
if self.closed.get() {
|
||||||
return Err(LimboError::InternalError("Connection closed".to_string()));
|
return Err(LimboError::InternalError("Connection closed".to_string()));
|
||||||
}
|
}
|
||||||
let pragma = format!("PRAGMA {}({})", pragma_name, pragma_value);
|
let pragma = format!("PRAGMA {pragma_name}({pragma_value})");
|
||||||
let mut stmt = self.prepare(pragma)?;
|
let mut stmt = self.prepare(pragma)?;
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -977,8 +977,7 @@ impl Affinity {
|
|||||||
SQLITE_AFF_REAL => Ok(Affinity::Real),
|
SQLITE_AFF_REAL => Ok(Affinity::Real),
|
||||||
SQLITE_AFF_NUMERIC => Ok(Affinity::Numeric),
|
SQLITE_AFF_NUMERIC => Ok(Affinity::Numeric),
|
||||||
_ => Err(LimboError::InternalError(format!(
|
_ => Err(LimboError::InternalError(format!(
|
||||||
"Invalid affinity character: {}",
|
"Invalid affinity character: {char}"
|
||||||
char
|
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1009,7 @@ impl fmt::Display for Type {
|
|||||||
Self::Real => "REAL",
|
Self::Real => "REAL",
|
||||||
Self::Blob => "BLOB",
|
Self::Blob => "BLOB",
|
||||||
};
|
};
|
||||||
write!(f, "{}", s)
|
write!(f, "{s}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3071,9 +3071,12 @@ impl BTreeCursor {
|
|||||||
"left pointer is not the same as page id"
|
"left pointer is not the same as page id"
|
||||||
);
|
);
|
||||||
// FIXME: remove this lock
|
// FIXME: remove this lock
|
||||||
|
let database_size = header_accessor::get_database_size(&self.pager)?;
|
||||||
turso_assert!(
|
turso_assert!(
|
||||||
left_pointer <= header_accessor::get_database_size(&self.pager)?,
|
left_pointer <= database_size,
|
||||||
"invalid page number divider left pointer {left_pointer} > database number of pages",
|
"invalid page number divider left pointer {} > database number of pages {}",
|
||||||
|
left_pointer,
|
||||||
|
database_size
|
||||||
);
|
);
|
||||||
// FIXME: defragment shouldn't be needed
|
// FIXME: defragment shouldn't be needed
|
||||||
// defragment_page(parent_contents, self.usable_space() as u16);
|
// defragment_page(parent_contents, self.usable_space() as u16);
|
||||||
@@ -3838,10 +3841,7 @@ impl BTreeCursor {
|
|||||||
while low <= high && cell_count > 0 {
|
while low <= high && cell_count > 0 {
|
||||||
let mid = low + (high - low) / 2;
|
let mid = low + (high - low) / 2;
|
||||||
self.find_cell_state.set((low, high));
|
self.find_cell_state.set((low, high));
|
||||||
let cell = match page.cell_get(mid, self.usable_space()) {
|
let cell = page.cell_get(mid, self.usable_space())?;
|
||||||
Ok(c) => c,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
let comparison_result = match cell {
|
let comparison_result = match cell {
|
||||||
BTreeCell::TableLeafCell(cell) => key.to_rowid().cmp(&cell.rowid),
|
BTreeCell::TableLeafCell(cell) => key.to_rowid().cmp(&cell.rowid),
|
||||||
|
|||||||
@@ -1209,11 +1209,10 @@ mod tests {
|
|||||||
let final_memory = memory_stats::memory_stats().unwrap().physical_mem;
|
let final_memory = memory_stats::memory_stats().unwrap().physical_mem;
|
||||||
|
|
||||||
let growth = final_memory.saturating_sub(initial_memory);
|
let growth = final_memory.saturating_sub(initial_memory);
|
||||||
println!("Growth: {}", growth);
|
println!("Growth: {growth}");
|
||||||
assert!(
|
assert!(
|
||||||
growth < 10_000_000,
|
growth < 10_000_000,
|
||||||
"Memory grew by {} bytes over 10 cycles",
|
"Memory grew by {growth} bytes over 10 cycles"
|
||||||
growth
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -458,9 +458,7 @@ fn update_cache_size(
|
|||||||
|
|
||||||
pager
|
pager
|
||||||
.change_page_cache_size(final_cache_size)
|
.change_page_cache_size(final_cache_size)
|
||||||
.map_err(|e| {
|
.map_err(|e| LimboError::InternalError(format!("Failed to update page cache size: {e}")))?;
|
||||||
LimboError::InternalError(format!("Failed to update page cache size: {}", e))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ pub fn translate_create_table(
|
|||||||
p5: 0,
|
p5: 0,
|
||||||
});
|
});
|
||||||
// TODO: remove format, it sucks for performance but is convenient
|
// TODO: remove format, it sucks for performance but is convenient
|
||||||
let parse_schema_where_clause = format!("tbl_name = '{}' AND type != 'trigger'", tbl_name);
|
let parse_schema_where_clause = format!("tbl_name = '{tbl_name}' AND type != 'trigger'");
|
||||||
program.emit_insn(Insn::ParseSchema {
|
program.emit_insn(Insn::ParseSchema {
|
||||||
db: sqlite_schema_cursor_id,
|
db: sqlite_schema_cursor_id,
|
||||||
where_clause: Some(parse_schema_where_clause),
|
where_clause: Some(parse_schema_where_clause),
|
||||||
@@ -506,7 +506,7 @@ fn create_vtable_body_to_str(vtab: &CreateVirtualTable, module: Rc<VTabImpl>) ->
|
|||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
String::new()
|
String::new()
|
||||||
} else {
|
} else {
|
||||||
format!("({})", args)
|
format!("({args})")
|
||||||
},
|
},
|
||||||
vtab.tbl_name.name.0,
|
vtab.tbl_name.name.0,
|
||||||
vtab_args
|
vtab_args
|
||||||
@@ -602,7 +602,7 @@ pub fn translate_create_virtual_table(
|
|||||||
value: schema.schema_version as i32 + 1,
|
value: schema.schema_version as i32 + 1,
|
||||||
p5: 0,
|
p5: 0,
|
||||||
});
|
});
|
||||||
let parse_schema_where_clause = format!("tbl_name = '{}' AND type != 'trigger'", table_name);
|
let parse_schema_where_clause = format!("tbl_name = '{table_name}' AND type != 'trigger'");
|
||||||
program.emit_insn(Insn::ParseSchema {
|
program.emit_insn(Insn::ParseSchema {
|
||||||
db: sqlite_schema_cursor_id,
|
db: sqlite_schema_cursor_id,
|
||||||
where_clause: Some(parse_schema_where_clause),
|
where_clause: Some(parse_schema_where_clause),
|
||||||
|
|||||||
@@ -666,8 +666,7 @@ impl OpenMode {
|
|||||||
"memory" => Ok(OpenMode::Memory),
|
"memory" => Ok(OpenMode::Memory),
|
||||||
"rwc" => Ok(OpenMode::ReadWriteCreate),
|
"rwc" => Ok(OpenMode::ReadWriteCreate),
|
||||||
_ => Err(LimboError::InvalidArgument(format!(
|
_ => Err(LimboError::InvalidArgument(format!(
|
||||||
"Invalid mode: '{}'. Expected one of 'ro', 'rw', 'memory', 'rwc'",
|
"Invalid mode: '{s}'. Expected one of 'ro', 'rw', 'memory', 'rwc'"
|
||||||
s
|
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -728,8 +727,7 @@ impl<'a> OpenOptions<'a> {
|
|||||||
// sqlite allows only `localhost` or empty authority.
|
// sqlite allows only `localhost` or empty authority.
|
||||||
if !(authority.is_empty() || authority == "localhost") {
|
if !(authority.is_empty() || authority == "localhost") {
|
||||||
return Err(LimboError::InvalidArgument(format!(
|
return Err(LimboError::InvalidArgument(format!(
|
||||||
"Invalid authority '{}'. Only '' or 'localhost' allowed.",
|
"Invalid authority '{authority}'. Only '' or 'localhost' allowed."
|
||||||
authority
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
opts.authority = if authority.is_empty() {
|
opts.authority = if authority.is_empty() {
|
||||||
@@ -1049,8 +1047,7 @@ pub fn parse_string(expr: &Expr) -> Result<String> {
|
|||||||
Ok(s[1..s.len() - 1].to_string())
|
Ok(s[1..s.len() - 1].to_string())
|
||||||
}
|
}
|
||||||
_ => Err(LimboError::InvalidArgument(format!(
|
_ => Err(LimboError::InvalidArgument(format!(
|
||||||
"string parameter expected, got {:?} instead",
|
"string parameter expected, got {expr:?} instead"
|
||||||
expr
|
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1129,8 +1129,7 @@ pub fn op_vupdate(
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
// virtual table update failed
|
// virtual table update failed
|
||||||
return Err(LimboError::ExtensionError(format!(
|
return Err(LimboError::ExtensionError(format!(
|
||||||
"Virtual table update failed: {}",
|
"Virtual table update failed: {e}"
|
||||||
e
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1572,20 +1571,17 @@ pub fn halt(
|
|||||||
0 => {}
|
0 => {}
|
||||||
SQLITE_CONSTRAINT_PRIMARYKEY => {
|
SQLITE_CONSTRAINT_PRIMARYKEY => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"UNIQUE constraint failed: {} (19)",
|
"UNIQUE constraint failed: {description} (19)"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
SQLITE_CONSTRAINT_NOTNULL => {
|
SQLITE_CONSTRAINT_NOTNULL => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"NOT NULL constraint failed: {} (19)",
|
"NOT NULL constraint failed: {description} (19)"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"undocumented halt error code {}",
|
"undocumented halt error code {description}"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1620,20 +1616,17 @@ pub fn op_halt(
|
|||||||
0 => {}
|
0 => {}
|
||||||
SQLITE_CONSTRAINT_PRIMARYKEY => {
|
SQLITE_CONSTRAINT_PRIMARYKEY => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"UNIQUE constraint failed: {} (19)",
|
"UNIQUE constraint failed: {description} (19)"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
SQLITE_CONSTRAINT_NOTNULL => {
|
SQLITE_CONSTRAINT_NOTNULL => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"NOTNULL constraint failed: {} (19)",
|
"NOTNULL constraint failed: {description} (19)"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LimboError::Constraint(format!(
|
return Err(LimboError::Constraint(format!(
|
||||||
"undocumented halt error code {}",
|
"undocumented halt error code {description}"
|
||||||
description
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1855,7 +1848,7 @@ pub fn op_return(
|
|||||||
if let Value::Integer(pc) = state.registers[*return_reg].get_owned_value() {
|
if let Value::Integer(pc) = state.registers[*return_reg].get_owned_value() {
|
||||||
let pc: u32 = (*pc)
|
let pc: u32 = (*pc)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| panic!("Return register is negative: {}", pc));
|
.unwrap_or_else(|_| panic!("Return register is negative: {pc}"));
|
||||||
state.pc = pc;
|
state.pc = pc;
|
||||||
} else {
|
} else {
|
||||||
if !*can_fallthrough {
|
if !*can_fallthrough {
|
||||||
@@ -2178,8 +2171,7 @@ pub fn op_seek(
|
|||||||
};
|
};
|
||||||
assert!(
|
assert!(
|
||||||
target_pc.is_offset(),
|
target_pc.is_offset(),
|
||||||
"target_pc should be an offset, is: {:?}",
|
"target_pc should be an offset, is: {target_pc:?}"
|
||||||
target_pc
|
|
||||||
);
|
);
|
||||||
let eq_only = match insn {
|
let eq_only = match insn {
|
||||||
Insn::SeekGE { eq_only, .. } | Insn::SeekLE { eq_only, .. } => *eq_only,
|
Insn::SeekGE { eq_only, .. } | Insn::SeekLE { eq_only, .. } => *eq_only,
|
||||||
@@ -2663,7 +2655,7 @@ pub fn op_agg_step(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let new_value = col.get_owned_value();
|
let new_value = col.get_owned_value();
|
||||||
if *new_value != Value::Null && acc.as_ref().map_or(true, |acc| new_value > acc) {
|
if *new_value != Value::Null && acc.as_ref().is_none_or(|acc| new_value > acc) {
|
||||||
*acc = Some(new_value.clone());
|
*acc = Some(new_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2681,7 +2673,7 @@ pub fn op_agg_step(
|
|||||||
|
|
||||||
let new_value = col.get_owned_value();
|
let new_value = col.get_owned_value();
|
||||||
|
|
||||||
if *new_value != Value::Null && acc.as_ref().map_or(true, |acc| new_value < acc) {
|
if *new_value != Value::Null && acc.as_ref().is_none_or(|acc| new_value < acc) {
|
||||||
*acc = Some(new_value.clone());
|
*acc = Some(new_value.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2904,7 +2896,7 @@ pub fn op_agg_final(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
panic!("Unexpected value {:?} in AggFinal", other);
|
panic!("Unexpected value {other:?} in AggFinal");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
state.pc += 1;
|
state.pc += 1;
|
||||||
@@ -3449,12 +3441,9 @@ pub fn op_function(
|
|||||||
|
|
||||||
let result = match (pattern, match_expression) {
|
let result = match (pattern, match_expression) {
|
||||||
(Value::Text(pattern), Value::Text(match_expression)) if arg_count == 3 => {
|
(Value::Text(pattern), Value::Text(match_expression)) if arg_count == 3 => {
|
||||||
let escape = match construct_like_escape_arg(
|
let escape = construct_like_escape_arg(
|
||||||
state.registers[*start_reg + 2].get_owned_value(),
|
state.registers[*start_reg + 2].get_owned_value(),
|
||||||
) {
|
)?;
|
||||||
Ok(x) => x,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
};
|
|
||||||
|
|
||||||
Value::Integer(exec_like_with_escape(
|
Value::Integer(exec_like_with_escape(
|
||||||
pattern.as_str(),
|
pattern.as_str(),
|
||||||
@@ -3663,8 +3652,7 @@ pub fn op_function(
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(LimboError::ParseError(format!(
|
return Err(LimboError::ParseError(format!(
|
||||||
"Error encountered while parsing datetime value: {}",
|
"Error encountered while parsing datetime value: {e}"
|
||||||
e
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4149,7 +4137,7 @@ pub fn op_end_coroutine(
|
|||||||
state.ended_coroutine.set(*yield_reg);
|
state.ended_coroutine.set(*yield_reg);
|
||||||
let pc: u32 = (*pc)
|
let pc: u32 = (*pc)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| panic!("EndCoroutine: pc overflow: {}", pc));
|
.unwrap_or_else(|_| panic!("EndCoroutine: pc overflow: {pc}"));
|
||||||
state.pc = pc - 1; // yield jump is always next to yield. Here we subtract 1 to go back to yield instruction
|
state.pc = pc - 1; // yield jump is always next to yield. Here we subtract 1 to go back to yield instruction
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
@@ -4177,7 +4165,7 @@ pub fn op_yield(
|
|||||||
} else {
|
} else {
|
||||||
let pc: u32 = (*pc)
|
let pc: u32 = (*pc)
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap_or_else(|_| panic!("Yield: pc overflow: {}", pc));
|
.unwrap_or_else(|_| panic!("Yield: pc overflow: {pc}"));
|
||||||
// swap the program counter with the value in the yield register
|
// swap the program counter with the value in the yield register
|
||||||
// this is the mechanism that allows jumping back and forth between the coroutine and the caller
|
// this is the mechanism that allows jumping back and forth between the coroutine and the caller
|
||||||
(state.pc, state.registers[*yield_reg]) =
|
(state.pc, state.registers[*yield_reg]) =
|
||||||
@@ -4368,8 +4356,7 @@ pub fn op_idx_delete(
|
|||||||
// Also, do not raise this (self-correcting and non-critical) error if in writable_schema mode.
|
// Also, do not raise this (self-correcting and non-critical) error if in writable_schema mode.
|
||||||
if *raise_error_if_no_matching_entry {
|
if *raise_error_if_no_matching_entry {
|
||||||
return Err(LimboError::Corrupt(format!(
|
return Err(LimboError::Corrupt(format!(
|
||||||
"IdxDelete: no matching index entry found for record {:?}",
|
"IdxDelete: no matching index entry found for record {record:?}"
|
||||||
record
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
state.pc += 1;
|
state.pc += 1;
|
||||||
@@ -4445,8 +4432,7 @@ pub fn op_idx_insert(
|
|||||||
Register::Record(ref r) => r,
|
Register::Record(ref r) => r,
|
||||||
o => {
|
o => {
|
||||||
return Err(LimboError::InternalError(format!(
|
return Err(LimboError::InternalError(format!(
|
||||||
"expected record, got {:?}",
|
"expected record, got {o:?}"
|
||||||
o
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5007,10 +4993,7 @@ pub fn op_parse_schema(
|
|||||||
conn.auto_commit.set(false);
|
conn.auto_commit.set(false);
|
||||||
|
|
||||||
if let Some(where_clause) = where_clause {
|
if let Some(where_clause) = where_clause {
|
||||||
let stmt = conn.prepare(format!(
|
let stmt = conn.prepare(format!("SELECT * FROM sqlite_schema WHERE {where_clause}"))?;
|
||||||
"SELECT * FROM sqlite_schema WHERE {}",
|
|
||||||
where_clause
|
|
||||||
))?;
|
|
||||||
|
|
||||||
let mut new_schema = conn.schema.borrow().clone();
|
let mut new_schema = conn.schema.borrow().clone();
|
||||||
|
|
||||||
@@ -6458,7 +6441,7 @@ fn exec_concat_strings(registers: &[Register]) -> Value {
|
|||||||
match reg.get_owned_value() {
|
match reg.get_owned_value() {
|
||||||
Value::Null => continue,
|
Value::Null => continue,
|
||||||
Value::Blob(_) => todo!("TODO concat blob"),
|
Value::Blob(_) => todo!("TODO concat blob"),
|
||||||
v => result.push_str(&format!("{}", v)),
|
v => result.push_str(&format!("{v}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::build_text(result)
|
Value::build_text(result)
|
||||||
@@ -6471,7 +6454,7 @@ fn exec_concat_ws(registers: &[Register]) -> Value {
|
|||||||
|
|
||||||
let separator = match ®isters[0].get_owned_value() {
|
let separator = match ®isters[0].get_owned_value() {
|
||||||
Value::Null | Value::Blob(_) => return Value::Null,
|
Value::Null | Value::Blob(_) => return Value::Null,
|
||||||
v => format!("{}", v),
|
v => format!("{v}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
@@ -6481,7 +6464,7 @@ fn exec_concat_ws(registers: &[Register]) -> Value {
|
|||||||
}
|
}
|
||||||
match reg.get_owned_value() {
|
match reg.get_owned_value() {
|
||||||
v if matches!(v, Value::Text(_) | Value::Integer(_) | Value::Float(_)) => {
|
v if matches!(v, Value::Text(_) | Value::Integer(_) | Value::Float(_)) => {
|
||||||
result.push_str(&format!("{}", v))
|
result.push_str(&format!("{v}"))
|
||||||
}
|
}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
@@ -6648,7 +6631,7 @@ fn execute_sqlite_version(version_integer: i64) -> String {
|
|||||||
let minor = (version_integer % 1_000_000) / 1_000;
|
let minor = (version_integer % 1_000_000) / 1_000;
|
||||||
let release = version_integer % 1_000;
|
let release = version_integer % 1_000;
|
||||||
|
|
||||||
format!("{}.{}.{}", major, minor, release)
|
format!("{major}.{minor}.{release}")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_int_value(value: &Value) -> i64 {
|
pub fn extract_int_value(value: &Value) -> i64 {
|
||||||
@@ -7115,9 +7098,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_add(rhs),
|
lhs.exec_add(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong ADD for lhs: {}, rhs: {}",
|
"Wrong ADD for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7173,9 +7154,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_subtract(rhs),
|
lhs.exec_subtract(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong subtract for lhs: {}, rhs: {}",
|
"Wrong subtract for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7231,9 +7210,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_multiply(rhs),
|
lhs.exec_multiply(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong multiply for lhs: {}, rhs: {}",
|
"Wrong multiply for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7277,9 +7254,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_divide(rhs),
|
lhs.exec_divide(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong divide for lhs: {}, rhs: {}",
|
"Wrong divide for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7345,9 +7320,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_remainder(rhs),
|
lhs.exec_remainder(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong remainder for lhs: {}, rhs: {}",
|
"Wrong remainder for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7384,9 +7357,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_and(rhs),
|
lhs.exec_and(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong AND for lhs: {}, rhs: {}",
|
"Wrong AND for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7425,9 +7396,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
lhs.exec_or(rhs),
|
lhs.exec_or(rhs),
|
||||||
outputs[i],
|
outputs[i],
|
||||||
"Wrong OR for lhs: {}, rhs: {}",
|
"Wrong OR for lhs: {lhs}, rhs: {rhs}"
|
||||||
lhs,
|
|
||||||
rhs
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ impl Register {
|
|||||||
assert!(!r.is_invalidated());
|
assert!(!r.is_invalidated());
|
||||||
r.as_blob_value()
|
r.as_blob_value()
|
||||||
}
|
}
|
||||||
_ => panic!("register holds unexpected value: {:?}", self),
|
_ => panic!("register holds unexpected value: {self:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,36 +170,36 @@ impl Display for InteractionPlan {
|
|||||||
match interactions {
|
match interactions {
|
||||||
Interactions::Property(property) => {
|
Interactions::Property(property) => {
|
||||||
let name = property.name();
|
let name = property.name();
|
||||||
writeln!(f, "-- begin testing '{}'", name)?;
|
writeln!(f, "-- begin testing '{name}'")?;
|
||||||
for interaction in property.interactions() {
|
for interaction in property.interactions() {
|
||||||
write!(f, "\t")?;
|
write!(f, "\t")?;
|
||||||
|
|
||||||
match interaction {
|
match interaction {
|
||||||
Interaction::Query(query) => writeln!(f, "{};", query)?,
|
Interaction::Query(query) => writeln!(f, "{query};")?,
|
||||||
Interaction::Assumption(assumption) => {
|
Interaction::Assumption(assumption) => {
|
||||||
writeln!(f, "-- ASSUME {};", assumption.message)?
|
writeln!(f, "-- ASSUME {};", assumption.message)?
|
||||||
}
|
}
|
||||||
Interaction::Assertion(assertion) => {
|
Interaction::Assertion(assertion) => {
|
||||||
writeln!(f, "-- ASSERT {};", assertion.message)?
|
writeln!(f, "-- ASSERT {};", assertion.message)?
|
||||||
}
|
}
|
||||||
Interaction::Fault(fault) => writeln!(f, "-- FAULT '{}';", fault)?,
|
Interaction::Fault(fault) => writeln!(f, "-- FAULT '{fault}';")?,
|
||||||
Interaction::FsyncQuery(query) => {
|
Interaction::FsyncQuery(query) => {
|
||||||
writeln!(f, "-- FSYNC QUERY;")?;
|
writeln!(f, "-- FSYNC QUERY;")?;
|
||||||
writeln!(f, "{};", query)?;
|
writeln!(f, "{query};")?;
|
||||||
writeln!(f, "{};", query)?
|
writeln!(f, "{query};")?
|
||||||
}
|
}
|
||||||
Interaction::FaultyQuery(query) => {
|
Interaction::FaultyQuery(query) => {
|
||||||
writeln!(f, "{}; --FAULTY QUERY", query)?
|
writeln!(f, "{query}; --FAULTY QUERY")?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeln!(f, "-- end testing '{}'", name)?;
|
writeln!(f, "-- end testing '{name}'")?;
|
||||||
}
|
}
|
||||||
Interactions::Fault(fault) => {
|
Interactions::Fault(fault) => {
|
||||||
writeln!(f, "-- FAULT '{}'", fault)?;
|
writeln!(f, "-- FAULT '{fault}'")?;
|
||||||
}
|
}
|
||||||
Interactions::Query(query) => {
|
Interactions::Query(query) => {
|
||||||
writeln!(f, "{};", query)?;
|
writeln!(f, "{query};")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,12 +256,12 @@ pub(crate) enum Interaction {
|
|||||||
impl Display for Interaction {
|
impl Display for Interaction {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Query(query) => write!(f, "{}", query),
|
Self::Query(query) => write!(f, "{query}"),
|
||||||
Self::Assumption(assumption) => write!(f, "ASSUME {}", assumption.message),
|
Self::Assumption(assumption) => write!(f, "ASSUME {}", assumption.message),
|
||||||
Self::Assertion(assertion) => write!(f, "ASSERT {}", assertion.message),
|
Self::Assertion(assertion) => write!(f, "ASSERT {}", assertion.message),
|
||||||
Self::Fault(fault) => write!(f, "FAULT '{}'", fault),
|
Self::Fault(fault) => write!(f, "FAULT '{fault}'"),
|
||||||
Self::FsyncQuery(query) => write!(f, "{}", query),
|
Self::FsyncQuery(query) => write!(f, "{query}"),
|
||||||
Self::FaultyQuery(query) => write!(f, "{} -- FAULTY QUERY", query),
|
Self::FaultyQuery(query) => write!(f, "{query} -- FAULTY QUERY"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -685,7 +685,7 @@ fn reopen_database(env: &mut SimulatorEnv) {
|
|||||||
) {
|
) {
|
||||||
Ok(db) => db,
|
Ok(db) => db,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
panic!("error opening simulator test file {:?}: {:?}", db_path, e);
|
panic!("error opening simulator test file {db_path:?}: {e:?}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
env.db = db;
|
env.db = db;
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ impl Property {
|
|||||||
let table_name = select.table.clone();
|
let table_name = select.table.clone();
|
||||||
|
|
||||||
let assumption = Interaction::Assumption(Assertion {
|
let assumption = Interaction::Assumption(Assertion {
|
||||||
message: format!("table {} exists", table_name),
|
message: format!("table {table_name} exists"),
|
||||||
func: Box::new({
|
func: Box::new({
|
||||||
let table_name = table_name.clone();
|
let table_name = table_name.clone();
|
||||||
move |_, env: &mut SimulatorEnv| {
|
move |_, env: &mut SimulatorEnv| {
|
||||||
@@ -321,7 +321,7 @@ impl Property {
|
|||||||
queries,
|
queries,
|
||||||
} => {
|
} => {
|
||||||
let assumption = Interaction::Assumption(Assertion {
|
let assumption = Interaction::Assumption(Assertion {
|
||||||
message: format!("table {} exists", table),
|
message: format!("table {table} exists"),
|
||||||
func: Box::new({
|
func: Box::new({
|
||||||
let table = table.clone();
|
let table = table.clone();
|
||||||
move |_: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
move |_: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
||||||
@@ -344,7 +344,7 @@ impl Property {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
let assertion = Interaction::Assertion(Assertion {
|
let assertion = Interaction::Assertion(Assertion {
|
||||||
message: format!("`{}` should return no values for table `{}`", select, table,),
|
message: format!("`{select}` should return no values for table `{table}`",),
|
||||||
func: Box::new(move |stack: &Vec<ResultSet>, _| {
|
func: Box::new(move |stack: &Vec<ResultSet>, _| {
|
||||||
let rows = stack.last().unwrap();
|
let rows = stack.last().unwrap();
|
||||||
match rows {
|
match rows {
|
||||||
@@ -369,7 +369,7 @@ impl Property {
|
|||||||
select,
|
select,
|
||||||
} => {
|
} => {
|
||||||
let assumption = Interaction::Assumption(Assertion {
|
let assumption = Interaction::Assumption(Assertion {
|
||||||
message: format!("table {} exists", table),
|
message: format!("table {table} exists"),
|
||||||
func: Box::new({
|
func: Box::new({
|
||||||
let table = table.clone();
|
let table = table.clone();
|
||||||
move |_, env: &mut SimulatorEnv| {
|
move |_, env: &mut SimulatorEnv| {
|
||||||
@@ -381,10 +381,7 @@ impl Property {
|
|||||||
let table_name = table.clone();
|
let table_name = table.clone();
|
||||||
|
|
||||||
let assertion = Interaction::Assertion(Assertion {
|
let assertion = Interaction::Assertion(Assertion {
|
||||||
message: format!(
|
message: format!("select query should result in an error for table '{table}'"),
|
||||||
"select query should result in an error for table '{}'",
|
|
||||||
table
|
|
||||||
),
|
|
||||||
func: Box::new(move |stack: &Vec<ResultSet>, _| {
|
func: Box::new(move |stack: &Vec<ResultSet>, _| {
|
||||||
let last = stack.last().unwrap();
|
let last = stack.last().unwrap();
|
||||||
match last {
|
match last {
|
||||||
@@ -414,7 +411,7 @@ impl Property {
|
|||||||
}
|
}
|
||||||
Property::SelectSelectOptimizer { table, predicate } => {
|
Property::SelectSelectOptimizer { table, predicate } => {
|
||||||
let assumption = Interaction::Assumption(Assertion {
|
let assumption = Interaction::Assumption(Assertion {
|
||||||
message: format!("table {} exists", table),
|
message: format!("table {table} exists"),
|
||||||
func: Box::new({
|
func: Box::new({
|
||||||
let table = table.clone();
|
let table = table.clone();
|
||||||
move |_: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
move |_: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
||||||
@@ -491,7 +488,7 @@ impl Property {
|
|||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let msg = format!("{}", err);
|
let msg = format!("{err}");
|
||||||
if msg.contains(FAULT_ERROR_MSG) {
|
if msg.contains(FAULT_ERROR_MSG) {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
@@ -522,20 +519,19 @@ fn assert_all_table_values(tables: &[String]) -> impl Iterator<Item = Interactio
|
|||||||
distinct: Distinctness::All,
|
distinct: Distinctness::All,
|
||||||
}));
|
}));
|
||||||
let assertion = Interaction::Assertion(Assertion {
|
let assertion = Interaction::Assertion(Assertion {
|
||||||
message: format!("table {} should contain all of its values", table),
|
message: format!("table {table} should contain all of its values"),
|
||||||
func: Box::new({
|
func: Box::new({
|
||||||
let table = table.clone();
|
let table = table.clone();
|
||||||
move |stack: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
move |stack: &Vec<ResultSet>, env: &mut SimulatorEnv| {
|
||||||
let table = env.tables.iter().find(|t| t.name == table).ok_or_else(|| {
|
let table = env.tables.iter().find(|t| t.name == table).ok_or_else(|| {
|
||||||
LimboError::InternalError(format!(
|
LimboError::InternalError(format!(
|
||||||
"table {} should exist in simulator env",
|
"table {table} should exist in simulator env"
|
||||||
table
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let last = stack.last().unwrap();
|
let last = stack.last().unwrap();
|
||||||
match last {
|
match last {
|
||||||
Ok(vals) => Ok(*vals == table.rows),
|
Ok(vals) => Ok(*vals == table.rows),
|
||||||
Err(err) => Err(LimboError::InternalError(format!("{}", err))),
|
Err(err) => Err(LimboError::InternalError(format!("{err}"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -92,16 +92,16 @@ impl Query {
|
|||||||
impl Display for Query {
|
impl Display for Query {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Create(create) => write!(f, "{}", create),
|
Self::Create(create) => write!(f, "{create}"),
|
||||||
Self::Select(select) => write!(f, "{}", select),
|
Self::Select(select) => write!(f, "{select}"),
|
||||||
Self::Insert(insert) => write!(f, "{}", insert),
|
Self::Insert(insert) => write!(f, "{insert}"),
|
||||||
Self::Delete(delete) => write!(f, "{}", delete),
|
Self::Delete(delete) => write!(f, "{delete}"),
|
||||||
Self::Update(update) => write!(f, "{}", update),
|
Self::Update(update) => write!(f, "{update}"),
|
||||||
Self::Drop(drop) => write!(f, "{}", drop),
|
Self::Drop(drop) => write!(f, "{drop}"),
|
||||||
Self::CreateIndex(create_index) => write!(f, "{}", create_index),
|
Self::CreateIndex(create_index) => write!(f, "{create_index}"),
|
||||||
Self::Begin(begin) => write!(f, "{}", begin),
|
Self::Begin(begin) => write!(f, "{begin}"),
|
||||||
Self::Commit(commit) => write!(f, "{}", commit),
|
Self::Commit(commit) => write!(f, "{commit}"),
|
||||||
Self::Rollback(rollback) => write!(f, "{}", rollback),
|
Self::Rollback(rollback) => write!(f, "{rollback}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ mod tests {
|
|||||||
let mut stmt = ptr::null_mut();
|
let mut stmt = ptr::null_mut();
|
||||||
for i in 1..2000 {
|
for i in 1..2000 {
|
||||||
let sql =
|
let sql =
|
||||||
std::ffi::CString::new(format!("INSERT INTO test (id) VALUES ({})", i))
|
std::ffi::CString::new(format!("INSERT INTO test (id) VALUES ({i})"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sqlite3_prepare_v2(db, sql.as_ptr(), -1, &mut stmt, ptr::null_mut()),
|
sqlite3_prepare_v2(db, sql.as_ptr(), -1, &mut stmt, ptr::null_mut()),
|
||||||
@@ -473,7 +473,7 @@ mod tests {
|
|||||||
let mut stmt = ptr::null_mut();
|
let mut stmt = ptr::null_mut();
|
||||||
for i in 1..=2000 {
|
for i in 1..=2000 {
|
||||||
let sql =
|
let sql =
|
||||||
std::ffi::CString::new(format!("INSERT INTO test (id) VALUES ({})", i))
|
std::ffi::CString::new(format!("INSERT INTO test (id) VALUES ({i})"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sqlite3_prepare_v2(db, sql.as_ptr(), -1, &mut stmt, ptr::null_mut()),
|
sqlite3_prepare_v2(db, sql.as_ptr(), -1, &mut stmt, ptr::null_mut()),
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ fn generate_plan(opts: &Opts) -> Result<Plan, Box<dyn std::error::Error + Send +
|
|||||||
writeln!(log_file, "{}", opts.nr_iterations)?;
|
writeln!(log_file, "{}", opts.nr_iterations)?;
|
||||||
writeln!(log_file, "{}", ddl_statements.len())?;
|
writeln!(log_file, "{}", ddl_statements.len())?;
|
||||||
for stmt in &ddl_statements {
|
for stmt in &ddl_statements {
|
||||||
writeln!(log_file, "{}", stmt)?;
|
writeln!(log_file, "{stmt}")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
plan.ddl_statements = ddl_statements;
|
plan.ddl_statements = ddl_statements;
|
||||||
@@ -373,7 +373,7 @@ fn generate_plan(opts: &Opts) -> Result<Plan, Box<dyn std::error::Error + Send +
|
|||||||
}
|
}
|
||||||
let sql = generate_random_statement(&schema);
|
let sql = generate_random_statement(&schema);
|
||||||
if !opts.skip_log {
|
if !opts.skip_log {
|
||||||
writeln!(log_file, "{}", sql)?;
|
writeln!(log_file, "{sql}")?;
|
||||||
}
|
}
|
||||||
queries.push(sql);
|
queries.push(sql);
|
||||||
if tx.is_some() {
|
if tx.is_some() {
|
||||||
@@ -443,7 +443,7 @@ pub fn init_tracing() -> Result<WorkerGuard, std::io::Error> {
|
|||||||
.with(EnvFilter::from_default_env())
|
.with(EnvFilter::from_default_env())
|
||||||
.try_init()
|
.try_init()
|
||||||
{
|
{
|
||||||
println!("Unable to setup tracing appender: {:?}", e);
|
println!("Unable to setup tracing appender: {e:?}");
|
||||||
}
|
}
|
||||||
Ok(guard)
|
Ok(guard)
|
||||||
}
|
}
|
||||||
@@ -486,7 +486,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
// Apply each DDL statement individually
|
// Apply each DDL statement individually
|
||||||
for stmt in &plan.ddl_statements {
|
for stmt in &plan.ddl_statements {
|
||||||
if opts.verbose {
|
if opts.verbose {
|
||||||
println!("executing ddl {}", stmt);
|
println!("executing ddl {stmt}");
|
||||||
}
|
}
|
||||||
if let Err(e) = conn.execute(stmt, ()).await {
|
if let Err(e) = conn.execute(stmt, ()).await {
|
||||||
match e {
|
match e {
|
||||||
@@ -494,7 +494,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
if e.contains("Corrupt database") {
|
if e.contains("Corrupt database") {
|
||||||
panic!("Error creating table: {}", e);
|
panic!("Error creating table: {}", e);
|
||||||
} else {
|
} else {
|
||||||
println!("Error creating table: {}", e);
|
println!("Error creating table: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Error creating table: {}", e),
|
_ => panic!("Error creating table: {}", e),
|
||||||
@@ -528,7 +528,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
let sql = &plan.queries_per_thread[thread][query_index];
|
let sql = &plan.queries_per_thread[thread][query_index];
|
||||||
if !opts.silent {
|
if !opts.silent {
|
||||||
if opts.verbose {
|
if opts.verbose {
|
||||||
println!("executing query {}", sql);
|
println!("executing query {sql}");
|
||||||
} else if query_index % 100 == 0 {
|
} else if query_index % 100 == 0 {
|
||||||
print!(
|
print!(
|
||||||
"\r{:.2} %",
|
"\r{:.2} %",
|
||||||
@@ -544,10 +544,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
panic!("Error executing query: {}", e);
|
panic!("Error executing query: {}", e);
|
||||||
} else if e.contains("UNIQUE constraint failed") {
|
} else if e.contains("UNIQUE constraint failed") {
|
||||||
if opts.verbose {
|
if opts.verbose {
|
||||||
println!("Skipping UNIQUE constraint violation: {}", e);
|
println!("Skipping UNIQUE constraint violation: {e}");
|
||||||
}
|
}
|
||||||
} else if opts.verbose {
|
} else if opts.verbose {
|
||||||
println!("Error executing query: {}", e);
|
println!("Error executing query: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("Error executing query: {}", e),
|
_ => panic!("Error executing query: {}", e),
|
||||||
@@ -575,6 +575,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
handle.await??;
|
handle.await??;
|
||||||
}
|
}
|
||||||
println!("Done. SQL statements written to {}", opts.log_file);
|
println!("Done. SQL statements written to {}", opts.log_file);
|
||||||
println!("Database file: {}", db_file);
|
println!("Database file: {db_file}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1367,12 +1367,12 @@ mod tests {
|
|||||||
|
|
||||||
let datatypes = ["INTEGER", "TEXT", "REAL", "BLOB"];
|
let datatypes = ["INTEGER", "TEXT", "REAL", "BLOB"];
|
||||||
let (mut rng, seed) = rng_from_time();
|
let (mut rng, seed) = rng_from_time();
|
||||||
log::info!("seed: {}", seed);
|
log::info!("seed: {seed}");
|
||||||
|
|
||||||
for _ in 0..1000 {
|
for _ in 0..1000 {
|
||||||
// Create table with random datatype
|
// Create table with random datatype
|
||||||
let datatype = datatypes[rng.random_range(0..datatypes.len())];
|
let datatype = datatypes[rng.random_range(0..datatypes.len())];
|
||||||
let create_table = format!("CREATE TABLE t(x {})", datatype);
|
let create_table = format!("CREATE TABLE t(x {datatype})");
|
||||||
|
|
||||||
let db = TempDatabase::new_empty(false);
|
let db = TempDatabase::new_empty(false);
|
||||||
let limbo_conn = db.connect_limbo();
|
let limbo_conn = db.connect_limbo();
|
||||||
@@ -1396,7 +1396,7 @@ mod tests {
|
|||||||
3 => "NULL".to_string(), // NULL
|
3 => "NULL".to_string(), // NULL
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
values.push(format!("({})", value));
|
values.push(format!("({value})"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let insert = format!("INSERT INTO t VALUES {}", values.join(","));
|
let insert = format!("INSERT INTO t VALUES {}", values.join(","));
|
||||||
@@ -1405,14 +1405,13 @@ mod tests {
|
|||||||
|
|
||||||
// Test min and max
|
// Test min and max
|
||||||
for agg in ["min(x)", "max(x)"] {
|
for agg in ["min(x)", "max(x)"] {
|
||||||
let query = format!("SELECT {} FROM t", agg);
|
let query = format!("SELECT {agg} FROM t");
|
||||||
let limbo = limbo_exec_rows(&db, &limbo_conn, &query);
|
let limbo = limbo_exec_rows(&db, &limbo_conn, &query);
|
||||||
let sqlite = sqlite_exec_rows(&sqlite_conn, &query);
|
let sqlite = sqlite_exec_rows(&sqlite_conn, &query);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
limbo, sqlite,
|
limbo, sqlite,
|
||||||
"query: {}, limbo: {:?}, sqlite: {:?}, seed: {}, values: {:?}, schema: {}",
|
"query: {query}, limbo: {limbo:?}, sqlite: {sqlite:?}, seed: {seed}, values: {values:?}, schema: {create_table}"
|
||||||
query, limbo, sqlite, seed, values, create_table
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -728,8 +728,7 @@ fn test_wal_bad_frame() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
panic_msg.contains("WAL frame checksum mismatch."),
|
panic_msg.contains("WAL frame checksum mismatch."),
|
||||||
"Expected panic message not found. Got: {}",
|
"Expected panic message not found. Got: {panic_msg}"
|
||||||
panic_msg
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(_) => panic!("Expected query to panic, but it succeeded"),
|
Ok(_) => panic!("Expected query to panic, but it succeeded"),
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ fn build_keyword_map(
|
|||||||
fn write_entry(writer: &mut impl Write, entry: &PathEntry) -> Result<()> {
|
fn write_entry(writer: &mut impl Write, entry: &PathEntry) -> Result<()> {
|
||||||
if let Some(result) = entry.result {
|
if let Some(result) = entry.result {
|
||||||
writeln!(writer, "if idx == buf.len() {{")?;
|
writeln!(writer, "if idx == buf.len() {{")?;
|
||||||
writeln!(writer, "return Some(TokenType::{});", result)?;
|
writeln!(writer, "return Some(TokenType::{result});")?;
|
||||||
writeln!(writer, "}}")?;
|
writeln!(writer, "}}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ fn build_keyword_map(
|
|||||||
if b.is_ascii_alphabetic() {
|
if b.is_ascii_alphabetic() {
|
||||||
writeln!(writer, "{} | {} => {{", b, b.to_ascii_lowercase())?;
|
writeln!(writer, "{} | {} => {{", b, b.to_ascii_lowercase())?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(writer, "{} => {{", b)?;
|
writeln!(writer, "{b} => {{")?;
|
||||||
}
|
}
|
||||||
writeln!(writer, "idx += 1;")?;
|
writeln!(writer, "idx += 1;")?;
|
||||||
write_entry(writer, sub_entry)?;
|
write_entry(writer, sub_entry)?;
|
||||||
@@ -110,19 +110,16 @@ fn build_keyword_map(
|
|||||||
|
|
||||||
writeln!(
|
writeln!(
|
||||||
writer,
|
writer,
|
||||||
"pub(crate) const MAX_KEYWORD_LEN: usize = {};",
|
"pub(crate) const MAX_KEYWORD_LEN: usize = {max_len};"
|
||||||
max_len
|
|
||||||
)?;
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
writer,
|
writer,
|
||||||
"pub(crate) const MIN_KEYWORD_LEN: usize = {};",
|
"pub(crate) const MIN_KEYWORD_LEN: usize = {min_len};"
|
||||||
min_len
|
|
||||||
)?;
|
)?;
|
||||||
writeln!(writer, "/// Check if `word` is a keyword")?;
|
writeln!(writer, "/// Check if `word` is a keyword")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
writer,
|
writer,
|
||||||
"pub fn {}(buf: &[u8]) -> Option<TokenType> {{",
|
"pub fn {func_name}(buf: &[u8]) -> Option<TokenType> {{"
|
||||||
func_name
|
|
||||||
)?;
|
)?;
|
||||||
writeln!(
|
writeln!(
|
||||||
writer,
|
writer,
|
||||||
|
|||||||
Reference in New Issue
Block a user