Merge pull request #227 from penberg/drop-anyhow

Kill anyhow usage
This commit is contained in:
Pekka Enberg
2024-07-25 17:20:45 +03:00
committed by GitHub
28 changed files with 207 additions and 161 deletions

3
Cargo.lock generated
View File

@@ -1024,7 +1024,6 @@ dependencies = [
name = "limbo-wasm"
version = "0.0.2"
dependencies = [
"anyhow",
"limbo_core",
"wasm-bindgen",
]
@@ -1033,7 +1032,6 @@ dependencies = [
name = "limbo_core"
version = "0.0.2"
dependencies = [
"anyhow",
"cfg_block",
"chrono",
"criterion",
@@ -1061,7 +1059,6 @@ dependencies = [
name = "limbo_sim"
version = "0.0.2"
dependencies = [
"anyhow",
"limbo_core",
"rand",
"rand_chacha",

View File

@@ -11,6 +11,5 @@ crate-type = ["cdylib"]
path = "lib.rs"
[dependencies]
anyhow = "1.0.75"
limbo_core = { path = "../../core", default-features = false }
wasm-bindgen = "0.2"

View File

@@ -1,4 +1,4 @@
use anyhow::Result;
use limbo_core::Result;
use std::rc::Rc;
use std::sync::Arc;
use wasm_bindgen::prelude::*;

View File

@@ -28,7 +28,6 @@ rustix = "0.38.34"
mimalloc = { version = "*", default-features = false }
[dependencies]
anyhow = "1.0.75"
cfg_block = "0.1.1"
fallible-iterator = "0.3.0"
libc = "0.2.155"

View File

@@ -1,8 +1,7 @@
use crate::pager::Pager;
use crate::sqlite3_ondisk::{BTreeCell, TableInteriorCell, TableLeafCell};
use crate::types::{Cursor, CursorResult, OwnedRecord};
use anyhow::Result;
use crate::Result;
use std::cell::{Ref, RefCell};
use std::rc::Rc;

View File

@@ -1,7 +1,7 @@
use crate::types::OwnedValue;
use anyhow;
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc};
use log::trace;
use std::result::Result;
use std::{error::Error, fmt::Display};
#[derive(Debug)]
@@ -86,7 +86,7 @@ fn get_max_datetime_exclusive() -> NaiveDateTime {
)
}
pub fn get_date_from_time_value(time_value: &OwnedValue) -> anyhow::Result<String> {
pub fn get_date_from_time_value(time_value: &OwnedValue) -> crate::Result<String> {
let dt = match time_value {
OwnedValue::Text(s) => get_date_time_from_time_value_string(s),
OwnedValue::Integer(i) => get_date_time_from_time_value_integer(*i),
@@ -106,7 +106,7 @@ pub fn get_date_from_time_value(time_value: &OwnedValue) -> anyhow::Result<Strin
}
DateTimeError::Other(s) => {
trace!("Other date time error: {}", s);
anyhow::bail!(s)
Err(crate::error::LimboError::InvalidDate(s))
}
}
}

49
core/error.rs Normal file
View File

@@ -0,0 +1,49 @@
use thiserror::Error;
#[derive(Debug, Error)]
pub enum LimboError {
#[error("Corrupt database: {0}")]
Corrupt(String),
#[error("File is not a database")]
NotADB,
#[error("Internal error: {0}")]
InternalError(String),
#[error("Parse error: {0}")]
ParseError(String),
#[error("Parse error: {0}")]
LexerError(#[from] sqlite3_parser::lexer::sql::Error),
#[error("Conversion error: {0}")]
ConversionError(String),
#[error("Env variable error: {0}")]
EnvVarError(#[from] std::env::VarError),
#[error("I/O error: {0}")]
IOError(#[from] std::io::Error),
#[cfg(target_os = "linux")]
#[error("I/O error: {0}")]
LinuxIOError(String),
#[error("Locking error: {0}")]
LockingError(String),
#[cfg(target_os = "macos")]
#[error("I/O error: {0}")]
RustixIOError(#[from] rustix::io::Errno),
#[error("Parse error: {0}")]
ParseIntError(#[from] std::num::ParseIntError),
#[error("Parse error: {0}")]
ParseFloatError(#[from] std::num::ParseFloatError),
#[error("Parse error: {0}")]
InvalidDate(String),
}
#[macro_export]
macro_rules! bail_parse_error {
($($arg:tt)*) => {
return Err(crate::error::LimboError::ParseError(format!($($arg)*)))
};
}
#[macro_export]
macro_rules! bail_corrupt_error {
($($arg:tt)*) => {
return Err(crate::error::LimboError::Corrupt(format!($($arg)*)))
};
}

View File

@@ -2,8 +2,7 @@ pub const ENV_DISABLE_FILE_LOCK: &str = "LIMBO_DISABLE_FILE_LOCK";
#[cfg(test)]
pub mod tests {
use crate::IO;
use anyhow::Result;
use crate::{Result, IO};
use std::process::{Command, Stdio};
use tempfile::NamedTempFile;

View File

@@ -1,7 +1,8 @@
use crate::error::LimboError;
use crate::io::common;
use crate::Result;
use super::{Completion, File, WriteCompletion, IO};
use anyhow::{Ok, Result};
use libc::{c_short, fcntl, flock, F_SETLK};
use log::trace;
use polling::{Event, Events, Poller};
@@ -137,11 +138,11 @@ impl File for DarwinFile {
if lock_result == -1 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::WouldBlock {
return Err(anyhow::anyhow!(
return Err(LimboError::LockingError(format!(
"Failed locking file. File is locked by another process"
));
)));
} else {
return Err(anyhow::anyhow!("Failed locking file, {}", err));
return Err(LimboError::LockingError(format!("Failed locking file, {}", err)));
}
}
Ok(())
@@ -159,10 +160,10 @@ impl File for DarwinFile {
let unlock_result = unsafe { fcntl(fd, F_SETLK, &flock) };
if unlock_result == -1 {
return Err(anyhow::anyhow!(
return Err(LimboError::LockingError(format!(
"Failed to release file lock: {}",
std::io::Error::last_os_error()
));
)));
}
Ok(())
}

View File

@@ -1,5 +1,4 @@
use super::{Completion, File, WriteCompletion, IO};
use anyhow::{Ok, Result};
use crate::{Completion, File, Result, WriteCompletion, IO};
use log::trace;
use std::cell::RefCell;
use std::io::{Read, Seek, Write};

View File

@@ -1,5 +1,5 @@
use super::{common, Completion, File, WriteCompletion, IO};
use anyhow::{ensure, Result};
use crate::{Result, LimboError};
use libc::{c_short, fcntl, flock, iovec, F_SETLK};
use log::{debug, trace};
use nix::fcntl::{FcntlArg, OFlag};
@@ -94,7 +94,9 @@ impl IO for LinuxIO {
ring.submit_and_wait(1)?;
while let Some(cqe) = ring.completion().next() {
let result = cqe.result();
ensure!(result >= 0, LinuxIOError::IOUringCQError(result));
if result < 0 {
return Err(LimboError::LinuxIOError(format!("{}", LinuxIOError::IOUringCQError(result))));
}
let c = unsafe { Rc::from_raw(cqe.user_data() as *const Completion) };
c.complete();
}
@@ -128,9 +130,9 @@ impl File for LinuxFile {
if lock_result == -1 {
let err = std::io::Error::last_os_error();
if err.kind() == std::io::ErrorKind::WouldBlock {
return Err(anyhow::anyhow!("File is locked by another process"));
return Err(LimboError::LockingError("File is locked by another process".into()));
} else {
return Err(anyhow::anyhow!(err));
return Err(LimboError::IOError(err));
}
}
Ok(())
@@ -148,10 +150,10 @@ impl File for LinuxFile {
let unlock_result = unsafe { fcntl(fd, F_SETLK, &flock) };
if unlock_result == -1 {
return Err(anyhow::anyhow!(
return Err(LimboError::LockingError(format!(
"Failed to release file lock: {}",
std::io::Error::last_os_error()
));
)));
}
Ok(())
}

View File

@@ -1,4 +1,4 @@
use anyhow::Result;
use crate::Result;
use cfg_block::cfg_block;
use std::{
cell::{Ref, RefCell, RefMut},

View File

@@ -1,5 +1,4 @@
use super::{Completion, File, WriteCompletion, IO};
use anyhow::{Ok, Result};
use crate::{Completion, File, Result, WriteCompletion, IO};
use log::trace;
use std::cell::RefCell;
use std::io::{Read, Seek, Write};

View File

@@ -1,6 +1,7 @@
mod btree;
mod buffer_pool;
mod datetime;
mod error;
mod function;
mod io;
mod pager;
@@ -17,7 +18,6 @@ mod vdbe;
#[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
use anyhow::Result;
use fallible_iterator::FallibleIterator;
use log::trace;
use pager::Pager;
@@ -27,6 +27,9 @@ use sqlite3_parser::{ast::Cmd, lexer::sql::Parser};
use std::sync::Arc;
use std::{cell::RefCell, rc::Rc};
pub use error::LimboError;
pub type Result<T> = std::result::Result<T, error::LimboError>;
#[cfg(feature = "fs")]
pub use io::PlatformIO;
pub use io::{Buffer, Completion, File, WriteCompletion, IO};

View File

@@ -1,7 +1,7 @@
use crate::buffer_pool::BufferPool;
use crate::sqlite3_ondisk::BTreePage;
use crate::sqlite3_ondisk::{self, DatabaseHeader};
use crate::PageSource;
use crate::{PageSource, Result};
use log::trace;
use sieve_cache::SieveCache;
use std::cell::RefCell;
@@ -106,7 +106,7 @@ pub struct Pager {
}
impl Pager {
pub fn begin_open(page_source: &PageSource) -> anyhow::Result<Rc<RefCell<DatabaseHeader>>> {
pub fn begin_open(page_source: &PageSource) -> Result<Rc<RefCell<DatabaseHeader>>> {
sqlite3_ondisk::begin_read_database_header(page_source)
}
@@ -114,7 +114,7 @@ impl Pager {
db_header: Rc<RefCell<DatabaseHeader>>,
page_source: PageSource,
io: Arc<dyn crate::io::IO>,
) -> anyhow::Result<Self> {
) -> Result<Self> {
let db_header = db_header.borrow();
let page_size = db_header.page_size as usize;
let buffer_pool = Rc::new(BufferPool::new(page_size));
@@ -127,7 +127,7 @@ impl Pager {
})
}
pub fn read_page(&self, page_idx: usize) -> anyhow::Result<Rc<Page>> {
pub fn read_page(&self, page_idx: usize) -> Result<Rc<Page>> {
trace!("read_page(page_idx = {})", page_idx);
let mut page_cache = self.page_cache.borrow_mut();
if let Some(page) = page_cache.get(&page_idx) {

View File

@@ -1,4 +1,4 @@
use anyhow::Result;
use crate::Result;
use std::cell::{Ref, RefCell};
use crate::types::{Cursor, CursorResult, OwnedRecord, OwnedValue};

View File

@@ -1,5 +1,4 @@
use crate::util::normalize_ident;
use anyhow::Result;
use crate::{util::normalize_ident, Result};
use core::fmt;
use fallible_iterator::FallibleIterator;
use log::trace;
@@ -130,7 +129,7 @@ impl BTreeTable {
Some(Cmd::Stmt(Stmt::CreateTable { tbl_name, body, .. })) => {
create_table(tbl_name, body, root_page)
}
_ => anyhow::bail!("Expected CREATE TABLE statement"),
_ => todo!("Expected CREATE TABLE statement"),
}
}
@@ -213,9 +212,7 @@ fn create_table(
value.trim_matches('\'').to_owned()
}
_ => {
return Err(anyhow::anyhow!(
"Unsupported primary key expression"
))
todo!("Unsupported primary key expression");
}
});
}

View File

@@ -24,11 +24,11 @@
///
/// For more information, see: https://www.sqlite.org/fileformat.html
use crate::buffer_pool::BufferPool;
use crate::error::LimboError;
use crate::io::{Buffer, Completion, WriteCompletion};
use crate::pager::{Page, Pager};
use crate::types::{OwnedRecord, OwnedValue};
use crate::PageSource;
use anyhow::{anyhow, Result};
use crate::{PageSource, Result};
use log::trace;
use std::cell::RefCell;
use std::rc::Rc;
@@ -204,7 +204,7 @@ pub enum PageType {
}
impl TryFrom<u8> for PageType {
type Error = anyhow::Error;
type Error = crate::error::LimboError;
fn try_from(value: u8) -> Result<Self> {
match value {
@@ -212,7 +212,7 @@ impl TryFrom<u8> for PageType {
5 => Ok(Self::TableInterior),
10 => Ok(Self::IndexLeaf),
13 => Ok(Self::TableLeaf),
_ => Err(anyhow!("Invalid page type: {}", value)),
_ => Err(LimboError::Corrupt(format!("Invalid page type: {}", value))),
}
}
}
@@ -410,7 +410,7 @@ pub enum SerialType {
}
impl TryFrom<u64> for SerialType {
type Error = anyhow::Error;
type Error = crate::error::LimboError;
fn try_from(value: u64) -> Result<Self> {
match value {
@@ -426,7 +426,7 @@ impl TryFrom<u64> for SerialType {
9 => Ok(Self::ConstInt1),
n if value > 12 && value % 2 == 0 => Ok(Self::Blob(((n - 12) / 2) as usize)),
n if value > 13 && value % 2 == 1 => Ok(Self::String(((n - 13) / 2) as usize)),
_ => Err(anyhow!("Invalid serial type: {}", value)),
_ => crate::bail_corrupt_error!("Invalid serial type: {}", value),
}
}
}
@@ -461,13 +461,13 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
SerialType::Null => Ok((OwnedValue::Null, 0)),
SerialType::UInt8 => {
if buf.is_empty() {
return Err(anyhow!("Invalid UInt8 value"));
crate::bail_corrupt_error!("Invalid UInt8 value");
}
Ok((OwnedValue::Integer(buf[0] as i64), 1))
}
SerialType::BEInt16 => {
if buf.len() < 2 {
return Err(anyhow!("Invalid BEInt16 value"));
crate::bail_corrupt_error!("Invalid BEInt16 value");
}
Ok((
OwnedValue::Integer(i16::from_be_bytes([buf[0], buf[1]]) as i64),
@@ -476,7 +476,7 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
}
SerialType::BEInt24 => {
if buf.len() < 3 {
return Err(anyhow!("Invalid BEInt24 value"));
crate::bail_corrupt_error!("Invalid BEInt24 value");
}
Ok((
OwnedValue::Integer(i32::from_be_bytes([0, buf[0], buf[1], buf[2]]) as i64),
@@ -485,7 +485,7 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
}
SerialType::BEInt32 => {
if buf.len() < 4 {
return Err(anyhow!("Invalid BEInt32 value"));
crate::bail_corrupt_error!("Invalid BEInt32 value");
}
Ok((
OwnedValue::Integer(i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]) as i64),
@@ -494,7 +494,7 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
}
SerialType::BEInt48 => {
if buf.len() < 6 {
return Err(anyhow!("Invalid BEInt48 value"));
crate::bail_corrupt_error!("Invalid BEInt48 value");
}
Ok((
OwnedValue::Integer(i64::from_be_bytes([
@@ -505,7 +505,7 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
}
SerialType::BEInt64 => {
if buf.len() < 8 {
return Err(anyhow!("Invalid BEInt64 value"));
crate::bail_corrupt_error!("Invalid BEInt64 value");
}
Ok((
OwnedValue::Integer(i64::from_be_bytes([
@@ -516,7 +516,7 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
}
SerialType::BEFloat64 => {
if buf.len() < 8 {
return Err(anyhow!("Invalid BEFloat64 value"));
crate::bail_corrupt_error!("Invalid BEFloat64 value");
}
Ok((
OwnedValue::Float(f64::from_be_bytes([
@@ -529,13 +529,13 @@ pub fn read_value(buf: &[u8], serial_type: &SerialType) -> Result<(OwnedValue, u
SerialType::ConstInt1 => Ok((OwnedValue::Integer(1), 0)),
SerialType::Blob(n) => {
if buf.len() < n {
return Err(anyhow!("Invalid Blob value"));
crate::bail_corrupt_error!("Invalid Blob value");
}
Ok((OwnedValue::Blob(buf[0..n].to_vec().into()), n))
}
SerialType::String(n) => {
if buf.len() < n {
return Err(anyhow!("Invalid String value"));
crate::bail_corrupt_error!("Invalid String value");
}
let bytes = buf[0..n].to_vec();
let value = unsafe { String::from_utf8_unchecked(bytes) };
@@ -555,7 +555,7 @@ fn read_varint(buf: &[u8]) -> Result<(u64, usize)> {
}
}
None => {
return Err(anyhow!("Invalid varint"));
crate::bail_corrupt_error!("Invalid varint");
}
}
}

View File

@@ -1,18 +1,11 @@
#[cfg(feature = "fs")]
use crate::io::File;
use crate::{
error::LimboError,
io::{Completion, WriteCompletion},
Buffer,
Buffer, Result,
};
use anyhow::{ensure, Result};
use std::{cell::RefCell, rc::Rc};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum StorageError {
#[error("file is not a database")]
NotADB,
}
pub struct PageSource {
io: Rc<dyn PageIO>,
@@ -72,10 +65,9 @@ impl PageIO for FileStorage {
fn get(&self, page_idx: usize, c: Rc<Completion>) -> Result<()> {
let size = c.buf().len();
assert!(page_idx > 0);
ensure!(
(1 << 9..=1 << 16).contains(&size) && size & (size - 1) == 0,
StorageError::NotADB
);
if size < 512 || size > 65536 || size & (size - 1) != 0 {
return Err(LimboError::NotADB.into());
}
let pos = (page_idx - 1) * size;
self.file.pread(pos, c)?;
Ok(())

View File

@@ -1,4 +1,4 @@
use anyhow::Result;
use crate::Result;
use sqlite3_parser::ast::{self, Expr, UnaryOperator};
use crate::{
@@ -132,22 +132,22 @@ pub fn translate_expr(
match func_type {
Some(Func::Agg(_)) => {
anyhow::bail!("Parse error: aggregation function in non-aggregation context")
crate::bail_parse_error!("aggregation function in non-aggregation context")
}
Some(Func::Scalar(srf)) => {
match srf {
ScalarFunc::Coalesce => {
let args = if let Some(args) = args {
if args.len() < 2 {
anyhow::bail!(
"Parse error: {} function with less than 2 arguments",
crate::bail_parse_error!(
"{} function with less than 2 arguments",
srf.to_string()
);
}
args
} else {
anyhow::bail!(
"Parse error: {} function with no arguments",
crate::bail_parse_error!(
"{} function with no arguments",
srf.to_string()
);
};
@@ -180,15 +180,15 @@ pub fn translate_expr(
ScalarFunc::Like => {
let args = if let Some(args) = args {
if args.len() < 2 {
anyhow::bail!(
"Parse error: {} function with less than 2 arguments",
crate::bail_parse_error!(
"{} function with less than 2 arguments",
srf.to_string()
);
}
args
} else {
anyhow::bail!(
"Parse error: {} function with no arguments",
crate::bail_parse_error!(
"{} function with no arguments",
srf.to_string()
);
};
@@ -213,15 +213,15 @@ pub fn translate_expr(
| ScalarFunc::Length => {
let args = if let Some(args) = args {
if args.len() != 1 {
anyhow::bail!(
"Parse error: {} function with not exactly 1 argument",
crate::bail_parse_error!(
"{} function with not exactly 1 argument",
srf.to_string()
);
}
args
} else {
anyhow::bail!(
"Parse error: {} function with no arguments",
crate::bail_parse_error!(
"{} function with no arguments",
srf.to_string()
);
};
@@ -237,8 +237,8 @@ pub fn translate_expr(
}
ScalarFunc::Random => {
if args.is_some() {
anyhow::bail!(
"Parse error: {} function with arguments",
crate::bail_parse_error!(
"{} function with arguments",
srf.to_string()
);
}
@@ -254,7 +254,7 @@ pub fn translate_expr(
let mut start_reg = 0;
if let Some(args) = args {
if args.len() > 1 {
anyhow::bail!("Parse error: date function with > 1 arguments. Modifiers are not yet supported.");
crate::bail_parse_error!("date function with > 1 arguments. Modifiers are not yet supported.");
} else if args.len() == 1 {
let arg_reg = program.alloc_register();
let _ = translate_expr(
@@ -277,15 +277,15 @@ pub fn translate_expr(
ScalarFunc::Trim | ScalarFunc::Round => {
let args = if let Some(args) = args {
if args.len() > 2 {
anyhow::bail!(
"Parse error: {} function with more than 2 arguments",
crate::bail_parse_error!(
"{} function with more than 2 arguments",
srf.to_string()
);
}
args
} else {
anyhow::bail!(
"Parse error: {} function with no arguments",
crate::bail_parse_error!(
"{} function with no arguments",
srf.to_string()
);
};
@@ -307,13 +307,13 @@ pub fn translate_expr(
ScalarFunc::Min => {
let args = if let Some(args) = args {
if args.len() < 1 {
anyhow::bail!(
"Parse error: min function with less than one argument"
crate::bail_parse_error!(
"min function with less than one argument"
);
}
args
} else {
anyhow::bail!("Parse error: min function with no arguments");
crate::bail_parse_error!("min function with no arguments");
};
for arg in args {
let reg = program.alloc_register();
@@ -334,13 +334,13 @@ pub fn translate_expr(
ScalarFunc::Max => {
let args = if let Some(args) = args {
if args.len() < 1 {
anyhow::bail!(
"Parse error: max function with less than one argument"
crate::bail_parse_error!(
"max function with less than one argument"
);
}
args
} else {
anyhow::bail!("Parse error: max function with no arguments");
crate::bail_parse_error!("max function with no arguments");
};
for arg in args {
let reg = program.alloc_register();
@@ -361,7 +361,7 @@ pub fn translate_expr(
}
}
None => {
anyhow::bail!("Parse error: unknown function {}", name.0);
crate::bail_parse_error!("unknown function {}", name.0);
}
}
}
@@ -600,8 +600,8 @@ pub fn resolve_ident_qualified(
Table::Pseudo(_) => todo!(),
}
}
anyhow::bail!(
"Parse error: column with qualified name {}.{} not found",
crate::bail_parse_error!(
"column with qualified name {}.{} not found",
table_name,
ident
);
@@ -654,10 +654,10 @@ pub fn resolve_ident_table(
return Ok(found[0]);
}
if found.is_empty() {
anyhow::bail!("Parse error: column with name {} not found", ident.as_str());
crate::bail_parse_error!("column with name {} not found", ident.as_str());
}
anyhow::bail!("Parse error: ambiguous column name {}", ident.as_str());
crate::bail_parse_error!("ambiguous column name {}", ident.as_str());
}
pub fn maybe_apply_affinity(col_type: Type, target_register: usize, program: &mut ProgramBuilder) {

View File

@@ -10,7 +10,7 @@ use crate::schema::Schema;
use crate::sqlite3_ondisk::{DatabaseHeader, MIN_PAGE_CACHE_SIZE};
use crate::util::normalize_ident;
use crate::vdbe::{builder::ProgramBuilder, BranchOffset, Insn, Program};
use anyhow::Result;
use crate::Result;
use select::{build_select, translate_select};
use sqlite3_parser::ast;

View File

@@ -1,6 +1,6 @@
use std::rc::Rc;
use anyhow::Result;
use crate::Result;
use sqlite3_parser::ast::{self, JoinOperator, JoinType};
use crate::function::AggFunc;
@@ -136,7 +136,7 @@ pub fn build_select<'a>(schema: &Schema, select: &'a ast::Select) -> Result<Sele
let maybe_alias = maybe_alias.map(|als| &als.0);
let table = match schema.get_table(table_name) {
Some(table) => table,
None => anyhow::bail!("Parse error: no such table: {}", table_name),
None => crate::bail_parse_error!("no such table: {}", table_name),
};
let identifier = normalize_ident(maybe_alias.unwrap_or(table_name));
let mut joins = Vec::new();
@@ -161,7 +161,9 @@ pub fn build_select<'a>(schema: &Schema, select: &'a ast::Select) -> Result<Sele
let maybe_alias = maybe_alias.as_ref().map(|als| &als.0);
let table = match schema.get_table(table_name) {
Some(table) => table,
None => anyhow::bail!("Parse error: no such table: {}", table_name),
None => {
crate::bail_parse_error!("no such table: {}", table_name)
}
};
let identifier = normalize_ident(maybe_alias.unwrap_or(table_name));
@@ -715,11 +717,13 @@ fn translate_aggregation(
let empty_args = &Vec::<ast::Expr>::new();
let args = info.args.as_ref().unwrap_or(empty_args);
let dest = match func {
Func::Scalar(_) => anyhow::bail!("Parse error: single row function in aggregation"),
Func::Scalar(_) => {
crate::bail_parse_error!("single row function in aggregation")
}
Func::Agg(agg_func) => match agg_func {
AggFunc::Avg => {
if args.len() != 1 {
anyhow::bail!("Parse error: avg bad number of arguments");
crate::bail_parse_error!("avg bad number of arguments");
}
let expr = &args[0];
let expr_reg = program.alloc_register();
@@ -751,7 +755,7 @@ fn translate_aggregation(
}
AggFunc::GroupConcat => {
if args.len() != 1 && args.len() != 2 {
anyhow::bail!("Parse error: group_concat bad number of arguments");
crate::bail_parse_error!("group_concat bad number of arguments");
}
let expr_reg = program.alloc_register();
@@ -774,21 +778,15 @@ fn translate_aggregation(
delimiter_expr =
ast::Expr::Literal(ast::Literal::String(s.to_string()));
}
_ => anyhow::bail!("Incorrect delimiter parameter"),
_ => crate::bail_parse_error!("Incorrect delimiter parameter"),
};
} else {
delimiter_expr =
ast::Expr::Literal(ast::Literal::String(String::from("\",\"")));
}
if let Err(error) = translate_expr(program, select, expr, expr_reg, cursor_hint) {
anyhow::bail!(error);
}
if let Err(error) =
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)
{
anyhow::bail!(error);
}
translate_expr(program, select, expr, expr_reg, cursor_hint)?;
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
@@ -801,7 +799,7 @@ fn translate_aggregation(
}
AggFunc::Max => {
if args.len() != 1 {
anyhow::bail!("Parse error: max bad number of arguments");
crate::bail_parse_error!("max bad number of arguments");
}
let expr = &args[0];
let expr_reg = program.alloc_register();
@@ -816,7 +814,7 @@ fn translate_aggregation(
}
AggFunc::Min => {
if args.len() != 1 {
anyhow::bail!("Parse error: min bad number of arguments");
crate::bail_parse_error!("min bad number of arguments");
}
let expr = &args[0];
let expr_reg = program.alloc_register();
@@ -831,7 +829,7 @@ fn translate_aggregation(
}
AggFunc::StringAgg => {
if args.len() != 2 {
anyhow::bail!("Parse error: string_agg bad number of arguments");
crate::bail_parse_error!("string_agg bad number of arguments");
}
let expr_reg = program.alloc_register();
@@ -843,7 +841,7 @@ fn translate_aggregation(
match &args[1] {
ast::Expr::Id(ident) => {
if ident.0.starts_with('"') {
anyhow::bail!("Parse error: no such column: \",\" - should this be a string literal in single-quotes?");
crate::bail_parse_error!("no such column: \",\" - should this be a string literal in single-quotes?");
} else {
delimiter_expr = args[1].clone();
}
@@ -851,17 +849,11 @@ fn translate_aggregation(
ast::Expr::Literal(ast::Literal::String(s)) => {
delimiter_expr = ast::Expr::Literal(ast::Literal::String(s.to_string()));
}
_ => anyhow::bail!("Incorrect delimiter parameter"),
_ => crate::bail_parse_error!("Incorrect delimiter parameter"),
};
if let Err(error) = translate_expr(program, select, expr, expr_reg, cursor_hint) {
anyhow::bail!(error);
}
if let Err(error) =
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)
{
anyhow::bail!(error);
}
translate_expr(program, select, expr, expr_reg, cursor_hint)?;
translate_expr(program, select, &delimiter_expr, delimiter_reg, cursor_hint)?;
program.emit_insn(Insn::AggStep {
acc_reg: target_register,
@@ -874,7 +866,7 @@ fn translate_aggregation(
}
AggFunc::Sum => {
if args.len() != 1 {
anyhow::bail!("Parse error: sum bad number of arguments");
crate::bail_parse_error!("sum bad number of arguments");
}
let expr = &args[0];
let expr_reg = program.alloc_register();
@@ -889,7 +881,7 @@ fn translate_aggregation(
}
AggFunc::Total => {
if args.len() != 1 {
anyhow::bail!("Parse error: total bad number of arguments");
crate::bail_parse_error!("total bad number of arguments");
}
let expr = &args[0];
let expr_reg = program.alloc_register();

View File

@@ -1,15 +1,18 @@
use anyhow::Result;
use sqlite3_parser::ast::{self};
use crate::{
error::LimboError,
function::ScalarFunc,
translate::expr::{resolve_ident_qualified, resolve_ident_table, translate_expr},
translate::select::Select,
translate::{
expr::{resolve_ident_qualified, resolve_ident_table, translate_expr},
select::Select,
},
vdbe::{builder::ProgramBuilder, BranchOffset, Insn},
Result,
};
use super::select::LoopInfo;
use sqlite3_parser::ast::{self};
#[derive(Debug)]
pub struct WhereTerm {
pub expr: ast::Expr,
@@ -60,10 +63,10 @@ pub fn split_constraint_to_terms<'a>(
.loops
.iter()
.find(|t| t.identifier == *table)
.ok_or(anyhow::anyhow!(
.ok_or(LimboError::ParseError(format!(
"Could not find cursor for table {}",
table
))?
)))?
.open_cursor
}
None => {
@@ -87,7 +90,9 @@ pub fn split_constraint_to_terms<'a>(
.map(|t| t.open_cursor)
.min()
.ok_or_else(|| {
anyhow::anyhow!("No open cursors found in any of the loops")
LimboError::ParseError(format!(
"No open cursors found in any of the loops"
))
})?;
*cursors.iter().max().unwrap_or(&outermost_cursor)
@@ -377,7 +382,7 @@ fn translate_condition_expr(
null_reg: reg,
});
} else {
anyhow::bail!("Parse error: unsupported literal type in condition");
crate::bail_parse_error!("unsupported literal type in condition");
}
}
_ => todo!(),

View File

@@ -1,7 +1,8 @@
use std::fmt::Display;
use std::{cell::Ref, rc::Rc};
use anyhow::Result;
use crate::error::LimboError;
use crate::Result;
#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
@@ -257,7 +258,7 @@ impl<'a> FromValue<'a> for i64 {
fn from_value(value: &Value<'a>) -> Result<Self> {
match value {
Value::Integer(i) => Ok(*i),
_ => anyhow::bail!("Expected integer value"),
_ => Err(LimboError::ConversionError("Expected integer value".into())),
}
}
}
@@ -266,7 +267,7 @@ impl<'a> FromValue<'a> for String {
fn from_value(value: &Value<'a>) -> Result<Self> {
match value {
Value::Text(s) => Ok(s.to_string()),
_ => anyhow::bail!("Expected text value"),
_ => Err(LimboError::ConversionError("Expected text value".into())),
}
}
}
@@ -275,7 +276,7 @@ impl<'a> FromValue<'a> for &'a str {
fn from_value(value: &Value<'a>) -> Result<&'a str> {
match value {
Value::Text(s) => Ok(s),
_ => anyhow::bail!("Expected text value"),
_ => Err(LimboError::ConversionError("Expected text value".into())),
}
}
}

View File

@@ -4,13 +4,14 @@ pub mod sorter;
use crate::btree::BTreeCursor;
use crate::datetime::get_date_from_time_value;
use crate::error::LimboError;
use crate::function::{AggFunc, ScalarFunc};
use crate::pager::Pager;
use crate::pseudo::PseudoCursor;
use crate::schema::Table;
use crate::types::{AggContext, Cursor, CursorResult, OwnedRecord, OwnedValue, Record};
use crate::Result;
use anyhow::Result;
use regex::Regex;
use std::borrow::BorrowMut;
use std::cell::RefCell;
@@ -380,7 +381,9 @@ impl Program {
state.pc += 1;
}
_ => {
anyhow::bail!("IfPos: the value in the register is not an integer");
return Err(LimboError::InternalError(
"IfPos: the value in the register is not an integer".into(),
));
}
}
}
@@ -1141,10 +1144,10 @@ impl Program {
state.registers[*dest] = OwnedValue::Text(Rc::new(date))
}
Err(e) => {
anyhow::bail!(
return Err(LimboError::ParseError(format!(
"Error encountered while parsing time value: {}",
e
)
)));
}
}
}

View File

@@ -1,5 +1,7 @@
use crate::types::{Cursor, CursorResult, OwnedRecord};
use anyhow::Result;
use crate::{
types::{Cursor, CursorResult, OwnedRecord},
Result,
};
use std::{
cell::{Ref, RefCell},
collections::{BTreeMap, VecDeque},

View File

@@ -15,7 +15,6 @@ name = "limbo_sim"
path = "main.rs"
[dependencies]
anyhow = "1.0.86"
limbo_core = { path = "../core" }
rand = "0.8.5"
rand_chacha = "0.3.1"

View File

@@ -1,5 +1,4 @@
use anyhow::Result;
use limbo_core::{Database, File, PlatformIO, IO};
use limbo_core::{Database, File, PlatformIO, Result, IO};
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;
use std::cell::RefCell;
@@ -100,7 +99,9 @@ impl IO for SimulatorIO {
fn run_once(&self) -> Result<()> {
if *self.fault.borrow() {
return Err(anyhow::anyhow!("Injected fault"));
return Err(limbo_core::LimboError::InternalError(
"Injected fault".into(),
));
}
self.inner.run_once().unwrap();
Ok(())
@@ -131,14 +132,18 @@ impl SimulatorFile {
impl limbo_core::File for SimulatorFile {
fn lock_file(&self, exclusive: bool) -> Result<()> {
if *self.fault.borrow() {
return Err(anyhow::anyhow!("Injected fault"));
return Err(limbo_core::LimboError::InternalError(
"Injected fault".into(),
));
}
self.inner.lock_file(exclusive)
}
fn unlock_file(&self) -> Result<()> {
if *self.fault.borrow() {
return Err(anyhow::anyhow!("Injected fault"));
return Err(limbo_core::LimboError::InternalError(
"Injected fault".into(),
));
}
self.inner.unlock_file()
}
@@ -146,7 +151,9 @@ impl limbo_core::File for SimulatorFile {
fn pread(&self, pos: usize, c: Rc<limbo_core::Completion>) -> Result<()> {
if *self.fault.borrow() {
*self.nr_pread_faults.borrow_mut() += 1;
return Err(anyhow::anyhow!("Injected fault"));
return Err(limbo_core::LimboError::InternalError(
"Injected fault".into(),
));
}
self.inner.pread(pos, c)
}
@@ -159,7 +166,9 @@ impl limbo_core::File for SimulatorFile {
) -> Result<()> {
if *self.fault.borrow() {
*self.nr_pwrite_faults.borrow_mut() += 1;
return Err(anyhow::anyhow!("Injected fault"));
return Err(limbo_core::LimboError::InternalError(
"Injected fault".into(),
));
}
self.inner.pwrite(pos, buffer, c)
}