mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-07 09:14:26 +01:00
syntactic changes: remove unneeded paths when the type is already imported
This commit is contained in:
@@ -11,7 +11,7 @@ use std::sync::Arc;
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("SQL conversion failure: `{0}`")]
|
||||
ToSqlConversionFailure(crate::BoxError),
|
||||
ToSqlConversionFailure(BoxError),
|
||||
}
|
||||
|
||||
impl From<limbo_core::LimboError> for Error {
|
||||
|
||||
@@ -153,7 +153,7 @@ impl From<u32> for Value {
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for Value {
|
||||
type Error = crate::Error;
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: u64) -> Result<Value> {
|
||||
if value > i64::MAX as u64 {
|
||||
|
||||
@@ -337,7 +337,7 @@ impl Limbo {
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn display_in_memory(&mut self) -> std::io::Result<()> {
|
||||
fn display_in_memory(&mut self) -> io::Result<()> {
|
||||
if self.opts.db_file == ":memory:" {
|
||||
self.writeln("Connected to a transient in-memory database.")?;
|
||||
self.writeln("Use \".open FILENAME\" to reopen on a persistent database")?;
|
||||
@@ -345,7 +345,7 @@ impl Limbo {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn show_info(&mut self) -> std::io::Result<()> {
|
||||
fn show_info(&mut self) -> io::Result<()> {
|
||||
let opts = format!("{}", self.opts);
|
||||
self.writeln(opts)
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ pub enum ScalarFunc {
|
||||
}
|
||||
|
||||
impl Display for ScalarFunc {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let str = match self {
|
||||
Self::Cast => "cast".to_string(),
|
||||
Self::Changes => "changes".to_string(),
|
||||
@@ -324,7 +324,7 @@ impl MathFunc {
|
||||
}
|
||||
|
||||
impl Display for MathFunc {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let str = match self {
|
||||
Self::Acos => "acos".to_string(),
|
||||
Self::Acosh => "acosh".to_string(),
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
}
|
||||
|
||||
let json_val = get_json_value(json_value)?;
|
||||
let json = crate::json::to_string(&json_val).unwrap();
|
||||
let json = to_string(&json_val).unwrap();
|
||||
|
||||
Ok(OwnedValue::Text(LimboText::json(Rc::new(json))))
|
||||
}
|
||||
@@ -52,7 +52,7 @@ pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
OwnedValue::Null => Ok(OwnedValue::Null),
|
||||
_ => {
|
||||
let json_val = get_json_value(json_value)?;
|
||||
let json = crate::json::to_string(&json_val).unwrap();
|
||||
let json = to_string(&json_val).unwrap();
|
||||
|
||||
Ok(OwnedValue::Text(LimboText::json(Rc::new(json))))
|
||||
}
|
||||
@@ -61,7 +61,7 @@ pub fn get_json(json_value: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
|
||||
fn get_json_value(json_value: &OwnedValue) -> crate::Result<Val> {
|
||||
match json_value {
|
||||
OwnedValue::Text(ref t) => match crate::json::from_str::<Val>(&t.value) {
|
||||
OwnedValue::Text(ref t) => match from_str::<Val>(&t.value) {
|
||||
Ok(json) => Ok(json),
|
||||
Err(_) => {
|
||||
crate::bail_parse_error!("malformed JSON")
|
||||
@@ -92,17 +92,17 @@ pub fn json_array(values: &[OwnedValue]) -> crate::Result<OwnedValue> {
|
||||
if t.subtype == TextSubtype::Json {
|
||||
s.push_str(&t.value);
|
||||
} else {
|
||||
match crate::json::to_string(&*t.value) {
|
||||
match to_string(&*t.value) {
|
||||
Ok(json) => s.push_str(&json),
|
||||
Err(_) => crate::bail_parse_error!("malformed JSON"),
|
||||
}
|
||||
}
|
||||
}
|
||||
OwnedValue::Integer(i) => match crate::json::to_string(&i) {
|
||||
OwnedValue::Integer(i) => match to_string(&i) {
|
||||
Ok(json) => s.push_str(&json),
|
||||
Err(_) => crate::bail_parse_error!("malformed JSON"),
|
||||
},
|
||||
OwnedValue::Float(f) => match crate::json::to_string(&f) {
|
||||
OwnedValue::Float(f) => match to_string(&f) {
|
||||
Ok(json) => s.push_str(&json),
|
||||
Err(_) => crate::bail_parse_error!("malformed JSON"),
|
||||
},
|
||||
@@ -152,7 +152,7 @@ pub fn json_arrow_extract(value: &OwnedValue, path: &OwnedValue) -> crate::Resul
|
||||
let extracted = json_extract_single(&json, path, false)?;
|
||||
|
||||
if let Some(val) = extracted {
|
||||
let json = crate::json::to_string(val).unwrap();
|
||||
let json = to_string(val).unwrap();
|
||||
|
||||
Ok(OwnedValue::Text(LimboText::json(Rc::new(json))))
|
||||
} else {
|
||||
@@ -209,7 +209,7 @@ pub fn json_extract(value: &OwnedValue, paths: &[OwnedValue]) -> crate::Result<O
|
||||
return Ok(OwnedValue::Null);
|
||||
}
|
||||
|
||||
result.push_str(&crate::json::to_string(&extracted).unwrap());
|
||||
result.push_str(&to_string(&extracted).unwrap());
|
||||
result.push(',');
|
||||
}
|
||||
}
|
||||
@@ -245,7 +245,7 @@ fn convert_json_to_db_type(extracted: &Val, all_as_db: bool) -> crate::Result<Ow
|
||||
}
|
||||
Val::String(s) => Ok(OwnedValue::Text(LimboText::new(Rc::new(s.clone())))),
|
||||
_ => {
|
||||
let json = crate::json::to_string(&extracted).unwrap();
|
||||
let json = to_string(&extracted).unwrap();
|
||||
if all_as_db {
|
||||
Ok(OwnedValue::Text(LimboText::new(Rc::new(json))))
|
||||
} else {
|
||||
@@ -374,7 +374,7 @@ fn json_extract_single<'a>(
|
||||
|
||||
pub fn json_error_position(json: &OwnedValue) -> crate::Result<OwnedValue> {
|
||||
match json {
|
||||
OwnedValue::Text(t) => match crate::json::from_str::<Val>(&t.value) {
|
||||
OwnedValue::Text(t) => match from_str::<Val>(&t.value) {
|
||||
Ok(_) => Ok(OwnedValue::Integer(0)),
|
||||
Err(JsonError::Message { location, .. }) => {
|
||||
if let Some(loc) = location {
|
||||
|
||||
14
core/lib.rs
14
core/lib.rs
@@ -45,7 +45,7 @@ use util::parse_schema_rows;
|
||||
|
||||
pub use error::LimboError;
|
||||
use translate::select::prepare_select_plan;
|
||||
pub type Result<T, E = error::LimboError> = std::result::Result<T, E>;
|
||||
pub type Result<T, E = LimboError> = std::result::Result<T, E>;
|
||||
|
||||
use crate::translate::optimizer::optimize_plan;
|
||||
pub use io::OpenFlags;
|
||||
@@ -86,7 +86,7 @@ impl Database {
|
||||
pub fn open_file(io: Arc<dyn IO>, path: &str) -> Result<Arc<Database>> {
|
||||
use storage::wal::WalFileShared;
|
||||
|
||||
let file = io.open_file(path, io::OpenFlags::Create, true)?;
|
||||
let file = io.open_file(path, OpenFlags::Create, true)?;
|
||||
maybe_init_database_file(&file, &io)?;
|
||||
let page_io = Rc::new(FileStorage::new(file));
|
||||
let wal_path = format!("{}-wal", path);
|
||||
@@ -488,7 +488,7 @@ pub struct Row<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Row<'a> {
|
||||
pub fn get<T: crate::types::FromValue<'a> + 'a>(&self, idx: usize) -> Result<T> {
|
||||
pub fn get<T: types::FromValue<'a> + 'a>(&self, idx: usize) -> Result<T> {
|
||||
let value = &self.values[idx];
|
||||
T::from_value(value)
|
||||
}
|
||||
@@ -509,9 +509,9 @@ impl Rows {
|
||||
}
|
||||
|
||||
pub(crate) struct SymbolTable {
|
||||
pub functions: HashMap<String, Rc<crate::function::ExternalFunc>>,
|
||||
pub functions: HashMap<String, Rc<function::ExternalFunc>>,
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
extensions: Vec<(libloading::Library, *const ExtensionApi)>,
|
||||
extensions: Vec<(Library, *const ExtensionApi)>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SymbolTable {
|
||||
@@ -563,7 +563,7 @@ impl SymbolTable {
|
||||
&self,
|
||||
name: &str,
|
||||
_arg_count: usize,
|
||||
) -> Option<Rc<crate::function::ExternalFunc>> {
|
||||
) -> Option<Rc<function::ExternalFunc>> {
|
||||
self.functions.get(name).cloned()
|
||||
}
|
||||
}
|
||||
@@ -589,7 +589,7 @@ impl Iterator for QueryRunner<'_> {
|
||||
match self.parser.next() {
|
||||
Ok(Some(cmd)) => Some(self.conn.run_cmd(cmd)),
|
||||
Ok(None) => None,
|
||||
Err(err) => Some(Result::Err(LimboError::from(err))),
|
||||
Err(err) => Some(Err(LimboError::from(err))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -716,7 +716,7 @@ impl BTreeCursor {
|
||||
// insert
|
||||
let overflow = {
|
||||
let contents = page.get().contents.as_mut().unwrap();
|
||||
log::debug!(
|
||||
debug!(
|
||||
"insert_into_page(overflow, cell_count={})",
|
||||
contents.cell_count()
|
||||
);
|
||||
@@ -1353,7 +1353,7 @@ impl BTreeCursor {
|
||||
|
||||
/// Defragment a page. This means packing all the cells to the end of the page.
|
||||
fn defragment_page(&self, page: &PageContent, db_header: Ref<DatabaseHeader>) {
|
||||
log::debug!("defragment_page");
|
||||
debug!("defragment_page");
|
||||
let cloned_page = page.clone();
|
||||
// TODO(pere): usable space should include offset probably
|
||||
let usable_space = (db_header.page_size - db_header.reserved_space as u16) as u64;
|
||||
@@ -1555,7 +1555,7 @@ impl BTreeCursor {
|
||||
}
|
||||
|
||||
let payload_overflow_threshold_max = self.payload_overflow_threshold_max(page_type.clone());
|
||||
log::debug!(
|
||||
debug!(
|
||||
"fill_cell_payload(record_size={}, payload_overflow_threshold_max={})",
|
||||
record_buf.len(),
|
||||
payload_overflow_threshold_max
|
||||
@@ -1565,7 +1565,7 @@ impl BTreeCursor {
|
||||
cell_payload.extend_from_slice(record_buf.as_slice());
|
||||
return;
|
||||
}
|
||||
log::debug!("fill_cell_payload(overflow)");
|
||||
debug!("fill_cell_payload(overflow)");
|
||||
|
||||
let payload_overflow_threshold_min = self.payload_overflow_threshold_min(page_type);
|
||||
// see e.g. https://github.com/sqlite/sqlite/blob/9591d3fe93936533c8c3b0dc4d025ac999539e11/src/dbstat.c#L371
|
||||
|
||||
@@ -216,7 +216,7 @@ impl Pager {
|
||||
}
|
||||
|
||||
/// Reads a page from the database.
|
||||
pub fn read_page(&self, page_idx: usize) -> crate::Result<PageRef> {
|
||||
pub fn read_page(&self, page_idx: usize) -> Result<PageRef> {
|
||||
trace!("read_page(page_idx = {})", page_idx);
|
||||
let mut page_cache = self.page_cache.write().unwrap();
|
||||
let page_key = PageCacheKey::new(page_idx, Some(self.wal.borrow().get_max_frame()));
|
||||
@@ -312,7 +312,7 @@ impl Pager {
|
||||
PageCacheKey::new(*page_id, Some(self.wal.borrow().get_max_frame()));
|
||||
let page = cache.get(&page_key).expect("we somehow added a page to dirty list but we didn't mark it as dirty, causing cache to drop it.");
|
||||
let page_type = page.get().contents.as_ref().unwrap().maybe_page_type();
|
||||
log::trace!("cacheflush(page={}, page_type={:?}", page_id, page_type);
|
||||
trace!("cacheflush(page={}, page_type={:?}", page_id, page_type);
|
||||
self.wal.borrow_mut().append_frame(
|
||||
page.clone(),
|
||||
db_size,
|
||||
@@ -374,7 +374,7 @@ impl Pager {
|
||||
pub fn checkpoint(&self) -> Result<CheckpointStatus> {
|
||||
loop {
|
||||
let state = self.checkpoint_state.borrow().clone();
|
||||
log::trace!("pager_checkpoint(state={:?})", state);
|
||||
trace!("pager_checkpoint(state={:?})", state);
|
||||
match state {
|
||||
CheckpointState::Checkpoint => {
|
||||
let in_flight = self.checkpoint_inflight.clone();
|
||||
|
||||
@@ -263,7 +263,7 @@ fn finish_read_database_header(
|
||||
) -> Result<()> {
|
||||
let buf = buf.borrow();
|
||||
let buf = buf.as_slice();
|
||||
let mut header = std::cell::RefCell::borrow_mut(&header);
|
||||
let mut header = RefCell::borrow_mut(&header);
|
||||
header.magic.copy_from_slice(&buf[0..16]);
|
||||
header.page_size = u16::from_be_bytes([buf[16], buf[17]]);
|
||||
header.write_version = buf[18];
|
||||
@@ -705,12 +705,12 @@ pub fn begin_write_btree_page(
|
||||
page: &PageRef,
|
||||
write_counter: Rc<RefCell<usize>>,
|
||||
) -> Result<()> {
|
||||
log::trace!("begin_write_btree_page(page={})", page.get().id);
|
||||
trace!("begin_write_btree_page(page={})", page.get().id);
|
||||
let page_source = &pager.page_io;
|
||||
let page_finish = page.clone();
|
||||
|
||||
let page_id = page.get().id;
|
||||
log::trace!("begin_write_btree_page(page_id={})", page_id);
|
||||
trace!("begin_write_btree_page(page_id={})", page_id);
|
||||
let buffer = {
|
||||
let page = page.get();
|
||||
let contents = page.contents.as_ref().unwrap();
|
||||
@@ -721,7 +721,7 @@ pub fn begin_write_btree_page(
|
||||
let write_complete = {
|
||||
let buf_copy = buffer.clone();
|
||||
Box::new(move |bytes_written: i32| {
|
||||
log::trace!("finish_write_btree_page");
|
||||
trace!("finish_write_btree_page");
|
||||
let buf_copy = buf_copy.clone();
|
||||
let buf_len = buf_copy.borrow().len();
|
||||
*write_counter.borrow_mut() -= 1;
|
||||
@@ -926,7 +926,7 @@ pub enum SerialType {
|
||||
}
|
||||
|
||||
impl TryFrom<u64> for SerialType {
|
||||
type Error = crate::error::LimboError;
|
||||
type Error = LimboError;
|
||||
|
||||
fn try_from(value: u64) -> Result<Self> {
|
||||
match value {
|
||||
@@ -1165,7 +1165,7 @@ pub fn begin_read_wal_frame(
|
||||
buffer_pool: Rc<BufferPool>,
|
||||
page: PageRef,
|
||||
) -> Result<()> {
|
||||
log::trace!(
|
||||
trace!(
|
||||
"begin_read_wal_frame(offset={}, page={})",
|
||||
offset,
|
||||
page.get().id
|
||||
@@ -1366,7 +1366,7 @@ pub fn checksum_wal(
|
||||
|
||||
impl WalHeader {
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
unsafe { std::mem::transmute::<&WalHeader, &[u8; std::mem::size_of::<WalHeader>()]>(self) }
|
||||
unsafe { std::mem::transmute::<&WalHeader, &[u8; size_of::<WalHeader>()]>(self) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ struct OngoingCheckpoint {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct WalFile {
|
||||
io: Arc<dyn crate::io::IO>,
|
||||
io: Arc<dyn IO>,
|
||||
buffer_pool: Rc<BufferPool>,
|
||||
|
||||
sync_state: RefCell<SyncState>,
|
||||
@@ -222,7 +222,7 @@ pub struct WalFile {
|
||||
/// that needs to be communicated between threads so this struct does the job.
|
||||
#[allow(dead_code)]
|
||||
pub struct WalFileShared {
|
||||
wal_header: Arc<RwLock<sqlite3_ondisk::WalHeader>>,
|
||||
wal_header: Arc<RwLock<WalHeader>>,
|
||||
min_frame: u64,
|
||||
max_frame: u64,
|
||||
nbackfills: u64,
|
||||
@@ -293,7 +293,7 @@ impl Wal for WalFile {
|
||||
self.max_frame_read_lock_index = max_read_mark_index as usize;
|
||||
self.max_frame = max_read_mark as u64;
|
||||
self.min_frame = shared.nbackfills + 1;
|
||||
log::trace!(
|
||||
trace!(
|
||||
"begin_read_tx(min_frame={}, max_frame={}, lock={})",
|
||||
self.min_frame,
|
||||
self.max_frame,
|
||||
@@ -424,7 +424,7 @@ impl Wal for WalFile {
|
||||
);
|
||||
'checkpoint_loop: loop {
|
||||
let state = self.ongoing_checkpoint.state;
|
||||
log::debug!("checkpoint(state={:?})", state);
|
||||
debug!("checkpoint(state={:?})", state);
|
||||
match state {
|
||||
CheckpointState::Start => {
|
||||
// TODO(pere): check what frames are safe to checkpoint between many readers!
|
||||
@@ -447,7 +447,7 @@ impl Wal for WalFile {
|
||||
self.ongoing_checkpoint.max_frame = max_safe_frame;
|
||||
self.ongoing_checkpoint.current_page = 0;
|
||||
self.ongoing_checkpoint.state = CheckpointState::ReadFrame;
|
||||
log::trace!(
|
||||
trace!(
|
||||
"checkpoint_start(min_frame={}, max_frame={})",
|
||||
self.ongoing_checkpoint.max_frame,
|
||||
self.ongoing_checkpoint.min_frame
|
||||
@@ -475,11 +475,9 @@ impl Wal for WalFile {
|
||||
if *frame >= self.ongoing_checkpoint.min_frame
|
||||
&& *frame <= self.ongoing_checkpoint.max_frame
|
||||
{
|
||||
log::debug!(
|
||||
debug!(
|
||||
"checkpoint page(state={:?}, page={}, frame={})",
|
||||
state,
|
||||
page,
|
||||
*frame
|
||||
state, page, *frame
|
||||
);
|
||||
self.ongoing_checkpoint.page.get().id = page as usize;
|
||||
|
||||
@@ -553,13 +551,13 @@ impl Wal for WalFile {
|
||||
match state {
|
||||
SyncState::NotSyncing => {
|
||||
let shared = self.shared.write().unwrap();
|
||||
log::debug!("wal_sync");
|
||||
debug!("wal_sync");
|
||||
{
|
||||
let syncing = self.syncing.clone();
|
||||
*syncing.borrow_mut() = true;
|
||||
let completion = Completion::Sync(SyncCompletion {
|
||||
complete: Box::new(move |_| {
|
||||
log::debug!("wal_sync finish");
|
||||
debug!("wal_sync finish");
|
||||
*syncing.borrow_mut() = false;
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -1771,7 +1771,7 @@ fn wrap_eval_jump_expr(
|
||||
}
|
||||
|
||||
pub fn maybe_apply_affinity(col_type: Type, target_register: usize, program: &mut ProgramBuilder) {
|
||||
if col_type == crate::schema::Type::Real {
|
||||
if col_type == Type::Real {
|
||||
program.emit_insn(Insn::RealAffinity {
|
||||
register: target_register,
|
||||
})
|
||||
|
||||
@@ -291,12 +291,12 @@ fn check_automatic_pk_index_required(
|
||||
|
||||
for result in primary_key_column_results {
|
||||
if let Err(e) = result {
|
||||
crate::bail_parse_error!("{}", e);
|
||||
bail_parse_error!("{}", e);
|
||||
}
|
||||
let column_name = result.unwrap();
|
||||
let column_def = columns.get(&ast::Name(column_name.clone()));
|
||||
if column_def.is_none() {
|
||||
crate::bail_parse_error!("No such column: {}", column_name);
|
||||
bail_parse_error!("No such column: {}", column_name);
|
||||
}
|
||||
|
||||
if matches!(
|
||||
@@ -326,10 +326,7 @@ fn check_automatic_pk_index_required(
|
||||
ast::ColumnConstraint::PrimaryKey { .. }
|
||||
) {
|
||||
if primary_key_definition.is_some() {
|
||||
crate::bail_parse_error!(
|
||||
"table {} has more than one primary key",
|
||||
tbl_name
|
||||
);
|
||||
bail_parse_error!("table {} has more than one primary key", tbl_name);
|
||||
}
|
||||
let typename = col_def.col_type.as_ref().map(|t| t.name.as_str());
|
||||
primary_key_definition =
|
||||
@@ -340,7 +337,7 @@ fn check_automatic_pk_index_required(
|
||||
|
||||
// Check if table has rowid
|
||||
if options.contains(ast::TableOptions::WITHOUT_ROWID) {
|
||||
crate::bail_parse_error!("WITHOUT ROWID tables are not supported yet");
|
||||
bail_parse_error!("WITHOUT ROWID tables are not supported yet");
|
||||
}
|
||||
|
||||
// Check if we need an automatic index
|
||||
@@ -364,7 +361,7 @@ fn check_automatic_pk_index_required(
|
||||
}
|
||||
}
|
||||
ast::CreateTableBody::AsSelect(_) => {
|
||||
crate::bail_parse_error!("CREATE TABLE AS SELECT not supported yet")
|
||||
bail_parse_error!("CREATE TABLE AS SELECT not supported yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ pub struct DeletePlan {
|
||||
}
|
||||
|
||||
impl Display for Plan {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Select(select_plan) => write!(f, "{}", select_plan.source),
|
||||
Delete(delete_plan) => write!(f, "{}", delete_plan.source),
|
||||
|
||||
@@ -29,7 +29,7 @@ impl OperatorIdCounter {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_aggregates(expr: &ast::Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
pub fn resolve_aggregates(expr: &Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
if aggs
|
||||
.iter()
|
||||
.any(|a| exprs_are_equivalent(&a.original_expr, expr))
|
||||
@@ -37,7 +37,7 @@ pub fn resolve_aggregates(expr: &ast::Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
return true;
|
||||
}
|
||||
match expr {
|
||||
ast::Expr::FunctionCall { name, args, .. } => {
|
||||
Expr::FunctionCall { name, args, .. } => {
|
||||
let args_count = if let Some(args) = &args {
|
||||
args.len()
|
||||
} else {
|
||||
@@ -63,7 +63,7 @@ pub fn resolve_aggregates(expr: &ast::Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::Expr::FunctionCallStar { name, .. } => {
|
||||
Expr::FunctionCallStar { name, .. } => {
|
||||
if let Ok(Func::Agg(f)) =
|
||||
Func::resolve_function(normalize_ident(name.0.as_str()).as_str(), 0)
|
||||
{
|
||||
@@ -77,13 +77,13 @@ pub fn resolve_aggregates(expr: &ast::Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
ast::Expr::Binary(lhs, _, rhs) => {
|
||||
Expr::Binary(lhs, _, rhs) => {
|
||||
let mut contains_aggregates = false;
|
||||
contains_aggregates |= resolve_aggregates(lhs, aggs);
|
||||
contains_aggregates |= resolve_aggregates(rhs, aggs);
|
||||
contains_aggregates
|
||||
}
|
||||
ast::Expr::Unary(_, expr) => {
|
||||
Expr::Unary(_, expr) => {
|
||||
let mut contains_aggregates = false;
|
||||
contains_aggregates |= resolve_aggregates(expr, aggs);
|
||||
contains_aggregates
|
||||
@@ -93,12 +93,9 @@ pub fn resolve_aggregates(expr: &ast::Expr, aggs: &mut Vec<Aggregate>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_column_references(
|
||||
expr: &mut ast::Expr,
|
||||
referenced_tables: &[TableReference],
|
||||
) -> Result<()> {
|
||||
pub fn bind_column_references(expr: &mut Expr, referenced_tables: &[TableReference]) -> Result<()> {
|
||||
match expr {
|
||||
ast::Expr::Id(id) => {
|
||||
Expr::Id(id) => {
|
||||
// true and false are special constants that are effectively aliases for 1 and 0
|
||||
// and not identifiers of columns
|
||||
if id.0.eq_ignore_ascii_case("true") || id.0.eq_ignore_ascii_case("false") {
|
||||
@@ -133,7 +130,7 @@ pub fn bind_column_references(
|
||||
crate::bail_parse_error!("Column {} not found", id.0);
|
||||
}
|
||||
let (tbl_idx, col_idx, is_rowid_alias) = match_result.unwrap();
|
||||
*expr = ast::Expr::Column {
|
||||
*expr = Expr::Column {
|
||||
database: None, // TODO: support different databases
|
||||
table: tbl_idx,
|
||||
column: col_idx,
|
||||
@@ -141,7 +138,7 @@ pub fn bind_column_references(
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Qualified(tbl, id) => {
|
||||
Expr::Qualified(tbl, id) => {
|
||||
let normalized_table_name = normalize_ident(tbl.0.as_str());
|
||||
let matching_tbl_idx = referenced_tables.iter().position(|t| {
|
||||
t.table_identifier
|
||||
@@ -169,7 +166,7 @@ pub fn bind_column_references(
|
||||
.columns()
|
||||
.get(col_idx.unwrap())
|
||||
.unwrap();
|
||||
*expr = ast::Expr::Column {
|
||||
*expr = Expr::Column {
|
||||
database: None, // TODO: support different databases
|
||||
table: tbl_idx,
|
||||
column: col_idx.unwrap(),
|
||||
@@ -177,7 +174,7 @@ pub fn bind_column_references(
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Between {
|
||||
Expr::Between {
|
||||
lhs,
|
||||
not: _,
|
||||
start,
|
||||
@@ -188,12 +185,12 @@ pub fn bind_column_references(
|
||||
bind_column_references(end, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Binary(expr, _operator, expr1) => {
|
||||
Expr::Binary(expr, _operator, expr1) => {
|
||||
bind_column_references(expr, referenced_tables)?;
|
||||
bind_column_references(expr1, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Case {
|
||||
Expr::Case {
|
||||
base,
|
||||
when_then_pairs,
|
||||
else_expr,
|
||||
@@ -210,9 +207,9 @@ pub fn bind_column_references(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Cast { expr, type_name: _ } => bind_column_references(expr, referenced_tables),
|
||||
ast::Expr::Collate(expr, _string) => bind_column_references(expr, referenced_tables),
|
||||
ast::Expr::FunctionCall {
|
||||
Expr::Cast { expr, type_name: _ } => bind_column_references(expr, referenced_tables),
|
||||
Expr::Collate(expr, _string) => bind_column_references(expr, referenced_tables),
|
||||
Expr::FunctionCall {
|
||||
name: _,
|
||||
distinctness: _,
|
||||
args,
|
||||
@@ -227,11 +224,11 @@ pub fn bind_column_references(
|
||||
Ok(())
|
||||
}
|
||||
// Already bound earlier
|
||||
ast::Expr::Column { .. } | ast::Expr::RowId { .. } => Ok(()),
|
||||
ast::Expr::DoublyQualified(_, _, _) => todo!(),
|
||||
ast::Expr::Exists(_) => todo!(),
|
||||
ast::Expr::FunctionCallStar { .. } => Ok(()),
|
||||
ast::Expr::InList { lhs, not: _, rhs } => {
|
||||
Expr::Column { .. } | Expr::RowId { .. } => Ok(()),
|
||||
Expr::DoublyQualified(_, _, _) => todo!(),
|
||||
Expr::Exists(_) => todo!(),
|
||||
Expr::FunctionCallStar { .. } => Ok(()),
|
||||
Expr::InList { lhs, not: _, rhs } => {
|
||||
bind_column_references(lhs, referenced_tables)?;
|
||||
if let Some(rhs) = rhs {
|
||||
for arg in rhs {
|
||||
@@ -240,36 +237,36 @@ pub fn bind_column_references(
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::InSelect { .. } => todo!(),
|
||||
ast::Expr::InTable { .. } => todo!(),
|
||||
ast::Expr::IsNull(expr) => {
|
||||
Expr::InSelect { .. } => todo!(),
|
||||
Expr::InTable { .. } => todo!(),
|
||||
Expr::IsNull(expr) => {
|
||||
bind_column_references(expr, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Like { lhs, rhs, .. } => {
|
||||
Expr::Like { lhs, rhs, .. } => {
|
||||
bind_column_references(lhs, referenced_tables)?;
|
||||
bind_column_references(rhs, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Literal(_) => Ok(()),
|
||||
ast::Expr::Name(_) => todo!(),
|
||||
ast::Expr::NotNull(expr) => {
|
||||
Expr::Literal(_) => Ok(()),
|
||||
Expr::Name(_) => todo!(),
|
||||
Expr::NotNull(expr) => {
|
||||
bind_column_references(expr, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Parenthesized(expr) => {
|
||||
Expr::Parenthesized(expr) => {
|
||||
for e in expr.iter_mut() {
|
||||
bind_column_references(e, referenced_tables)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Raise(_, _) => todo!(),
|
||||
ast::Expr::Subquery(_) => todo!(),
|
||||
ast::Expr::Unary(_, expr) => {
|
||||
Expr::Raise(_, _) => todo!(),
|
||||
Expr::Subquery(_) => todo!(),
|
||||
Expr::Unary(_, expr) => {
|
||||
bind_column_references(expr, referenced_tables)?;
|
||||
Ok(())
|
||||
}
|
||||
ast::Expr::Variable(_) => Ok(()),
|
||||
Expr::Variable(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +410,7 @@ struct JoinParseResult {
|
||||
source_operator: SourceOperator,
|
||||
is_outer_join: bool,
|
||||
using: Option<ast::DistinctNames>,
|
||||
predicates: Option<Vec<ast::Expr>>,
|
||||
predicates: Option<Vec<Expr>>,
|
||||
}
|
||||
|
||||
fn parse_join(
|
||||
@@ -540,15 +537,15 @@ fn parse_join(
|
||||
}
|
||||
let (left_table_idx, left_col_idx, left_col) = left_col.unwrap();
|
||||
let (right_col_idx, right_col) = right_col.unwrap();
|
||||
using_predicates.push(ast::Expr::Binary(
|
||||
Box::new(ast::Expr::Column {
|
||||
using_predicates.push(Expr::Binary(
|
||||
Box::new(Expr::Column {
|
||||
database: None,
|
||||
table: left_table_idx,
|
||||
column: left_col_idx,
|
||||
is_rowid_alias: left_col.is_rowid_alias,
|
||||
}),
|
||||
ast::Operator::Equals,
|
||||
Box::new(ast::Expr::Column {
|
||||
Box::new(Expr::Column {
|
||||
database: None,
|
||||
table: right_table.table_index,
|
||||
column: right_col_idx,
|
||||
@@ -586,12 +583,9 @@ pub fn parse_limit(limit: Limit) -> Option<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn break_predicate_at_and_boundaries(
|
||||
predicate: ast::Expr,
|
||||
out_predicates: &mut Vec<ast::Expr>,
|
||||
) {
|
||||
pub fn break_predicate_at_and_boundaries(predicate: Expr, out_predicates: &mut Vec<Expr>) {
|
||||
match predicate {
|
||||
ast::Expr::Binary(left, ast::Operator::And, right) => {
|
||||
Expr::Binary(left, ast::Operator::And, right) => {
|
||||
break_predicate_at_and_boundaries(*left, out_predicates);
|
||||
break_predicate_at_and_boundaries(*right, out_predicates);
|
||||
}
|
||||
@@ -601,7 +595,7 @@ pub fn break_predicate_at_and_boundaries(
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_row_id<F>(column_name: &str, table_id: usize, fn_check: F) -> Result<Option<ast::Expr>>
|
||||
fn parse_row_id<F>(column_name: &str, table_id: usize, fn_check: F) -> Result<Option<Expr>>
|
||||
where
|
||||
F: FnOnce() -> bool,
|
||||
{
|
||||
@@ -610,7 +604,7 @@ where
|
||||
crate::bail_parse_error!("ROWID is ambiguous");
|
||||
}
|
||||
|
||||
return Ok(Some(ast::Expr::RowId {
|
||||
return Ok(Some(Expr::RowId {
|
||||
database: None, // TODO: support different databases
|
||||
table: table_id,
|
||||
}));
|
||||
|
||||
@@ -69,10 +69,10 @@ pub fn prepare_select_plan(
|
||||
let mut aggregate_expressions = Vec::new();
|
||||
for (result_column_idx, column) in columns.iter_mut().enumerate() {
|
||||
match column {
|
||||
ast::ResultColumn::Star => {
|
||||
ResultColumn::Star => {
|
||||
plan.source.select_star(&mut plan.result_columns);
|
||||
}
|
||||
ast::ResultColumn::TableStar(name) => {
|
||||
ResultColumn::TableStar(name) => {
|
||||
let name_normalized = normalize_ident(name.0.as_str());
|
||||
let referenced_table = plan
|
||||
.referenced_tables
|
||||
@@ -96,7 +96,7 @@ pub fn prepare_select_plan(
|
||||
});
|
||||
}
|
||||
}
|
||||
ast::ResultColumn::Expr(ref mut expr, maybe_alias) => {
|
||||
ResultColumn::Expr(ref mut expr, maybe_alias) => {
|
||||
bind_column_references(expr, &plan.referenced_tables)?;
|
||||
match expr {
|
||||
ast::Expr::FunctionCall {
|
||||
|
||||
@@ -146,13 +146,13 @@ impl OwnedValue {
|
||||
let Some(text) = v.to_text() else {
|
||||
return OwnedValue::Null;
|
||||
};
|
||||
OwnedValue::build_text(std::rc::Rc::new(text))
|
||||
OwnedValue::build_text(Rc::new(text))
|
||||
}
|
||||
ExtValueType::Blob => {
|
||||
let Some(blob) = v.to_blob() else {
|
||||
return OwnedValue::Null;
|
||||
};
|
||||
OwnedValue::Blob(std::rc::Rc::new(blob))
|
||||
OwnedValue::Blob(Rc::new(blob))
|
||||
}
|
||||
ExtValueType::Error => {
|
||||
let Some(err) = v.to_text() else {
|
||||
@@ -241,7 +241,7 @@ impl PartialOrd<OwnedValue> for OwnedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::PartialOrd<AggContext> for AggContext {
|
||||
impl PartialOrd<AggContext> for AggContext {
|
||||
fn partial_cmp(&self, other: &AggContext) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
(Self::Avg(a, _), Self::Avg(b, _)) => a.partial_cmp(b),
|
||||
@@ -255,9 +255,9 @@ impl std::cmp::PartialOrd<AggContext> for AggContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::Eq for OwnedValue {}
|
||||
impl Eq for OwnedValue {}
|
||||
|
||||
impl std::cmp::Ord for OwnedValue {
|
||||
impl Ord for OwnedValue {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
|
||||
42
core/util.rs
42
core/util.rs
@@ -328,7 +328,7 @@ pub mod tests {
|
||||
Add,
|
||||
Box::new(Expr::Literal(Literal::Numeric("826".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -343,7 +343,7 @@ pub mod tests {
|
||||
Add,
|
||||
Box::new(Expr::Literal(Literal::Numeric("123".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -358,7 +358,7 @@ pub mod tests {
|
||||
Subtract,
|
||||
Box::new(Expr::Literal(Literal::Numeric("364".to_string()))),
|
||||
);
|
||||
assert!(!super::exprs_are_equivalent(&expr3, &expr4));
|
||||
assert!(!exprs_are_equivalent(&expr3, &expr4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -373,7 +373,7 @@ pub mod tests {
|
||||
Subtract,
|
||||
Box::new(Expr::Literal(Literal::Numeric("22.0".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr3, &expr4));
|
||||
assert!(exprs_are_equivalent(&expr3, &expr4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -392,7 +392,7 @@ pub mod tests {
|
||||
order_by: None,
|
||||
filter_over: None,
|
||||
};
|
||||
assert!(super::exprs_are_equivalent(&func1, &func2));
|
||||
assert!(exprs_are_equivalent(&func1, &func2));
|
||||
|
||||
let func3 = Expr::FunctionCall {
|
||||
name: Id("SUM".to_string()),
|
||||
@@ -401,7 +401,7 @@ pub mod tests {
|
||||
order_by: None,
|
||||
filter_over: None,
|
||||
};
|
||||
assert!(!super::exprs_are_equivalent(&func1, &func3));
|
||||
assert!(!exprs_are_equivalent(&func1, &func3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -420,7 +420,7 @@ pub mod tests {
|
||||
order_by: None,
|
||||
filter_over: None,
|
||||
};
|
||||
assert!(!super::exprs_are_equivalent(&sum, &sum_distinct));
|
||||
assert!(!exprs_are_equivalent(&sum, &sum_distinct));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -435,7 +435,7 @@ pub mod tests {
|
||||
Multiply,
|
||||
Box::new(Expr::Literal(Literal::Numeric("42".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -450,7 +450,7 @@ pub mod tests {
|
||||
Add,
|
||||
Box::new(Expr::Literal(Literal::Numeric("683".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
#[test]
|
||||
fn test_expressions_parenthesized_equivalent() {
|
||||
@@ -464,7 +464,7 @@ pub mod tests {
|
||||
Add,
|
||||
Box::new(Expr::Literal(Literal::Numeric("7".to_string()))),
|
||||
);
|
||||
assert!(super::exprs_are_equivalent(&expr7, &expr8));
|
||||
assert!(exprs_are_equivalent(&expr7, &expr8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -483,7 +483,7 @@ pub mod tests {
|
||||
rhs: Box::new(Expr::Literal(Literal::String("%john%".to_string()))),
|
||||
escape: Some(Box::new(Expr::Literal(Literal::String("\\".to_string())))),
|
||||
};
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -502,7 +502,7 @@ pub mod tests {
|
||||
rhs: Box::new(Expr::Literal(Literal::String("%john%".to_string()))),
|
||||
escape: Some(Box::new(Expr::Literal(Literal::String("#".to_string())))),
|
||||
};
|
||||
assert!(!super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(!exprs_are_equivalent(&expr1, &expr2));
|
||||
}
|
||||
#[test]
|
||||
fn test_expressions_equivalent_between() {
|
||||
@@ -518,7 +518,7 @@ pub mod tests {
|
||||
start: Box::new(Expr::Literal(Literal::Numeric("18".to_string()))),
|
||||
end: Box::new(Expr::Literal(Literal::Numeric("65".to_string()))),
|
||||
};
|
||||
assert!(super::exprs_are_equivalent(&expr1, &expr2));
|
||||
assert!(exprs_are_equivalent(&expr1, &expr2));
|
||||
|
||||
// differing BETWEEN bounds
|
||||
let expr3 = Expr::Between {
|
||||
@@ -527,7 +527,7 @@ pub mod tests {
|
||||
start: Box::new(Expr::Literal(Literal::Numeric("20".to_string()))),
|
||||
end: Box::new(Expr::Literal(Literal::Numeric("65".to_string()))),
|
||||
};
|
||||
assert!(!super::exprs_are_equivalent(&expr1, &expr3));
|
||||
assert!(!exprs_are_equivalent(&expr1, &expr3));
|
||||
}
|
||||
#[test]
|
||||
fn test_cast_exprs_equivalent() {
|
||||
@@ -546,16 +546,16 @@ pub mod tests {
|
||||
size: None,
|
||||
}),
|
||||
};
|
||||
assert!(super::exprs_are_equivalent(&cast1, &cast2));
|
||||
assert!(exprs_are_equivalent(&cast1, &cast2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ident_equivalency() {
|
||||
assert!(super::check_ident_equivalency("\"foo\"", "foo"));
|
||||
assert!(super::check_ident_equivalency("[foo]", "foo"));
|
||||
assert!(super::check_ident_equivalency("`FOO`", "foo"));
|
||||
assert!(super::check_ident_equivalency("\"foo\"", "`FOO`"));
|
||||
assert!(!super::check_ident_equivalency("\"foo\"", "[bar]"));
|
||||
assert!(!super::check_ident_equivalency("foo", "\"bar\""));
|
||||
assert!(check_ident_equivalency("\"foo\"", "foo"));
|
||||
assert!(check_ident_equivalency("[foo]", "foo"));
|
||||
assert!(check_ident_equivalency("`FOO`", "foo"));
|
||||
assert!(check_ident_equivalency("\"foo\"", "`FOO`"));
|
||||
assert!(!check_ident_equivalency("\"foo\"", "[bar]"));
|
||||
assert!(!check_ident_equivalency("foo", "\"bar\""));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1401,7 +1401,7 @@ mod tests {
|
||||
fn format(dt: NaiveDateTime) -> String {
|
||||
dt.format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
}
|
||||
fn weekday_sunday_based(dt: &chrono::NaiveDateTime) -> u32 {
|
||||
fn weekday_sunday_based(dt: &NaiveDateTime) -> u32 {
|
||||
dt.weekday().num_days_from_sunday()
|
||||
}
|
||||
|
||||
@@ -1438,8 +1438,7 @@ mod tests {
|
||||
&[text("2023-06-15 12:30:45"), text("subsec")],
|
||||
DateTimeOutput::Time,
|
||||
);
|
||||
let result =
|
||||
chrono::NaiveTime::parse_from_str(&result.to_string(), "%H:%M:%S%.3f").unwrap();
|
||||
let result = NaiveTime::parse_from_str(&result.to_string(), "%H:%M:%S%.3f").unwrap();
|
||||
assert_eq!(time.time(), result);
|
||||
}
|
||||
|
||||
@@ -1537,8 +1536,7 @@ mod tests {
|
||||
DateTimeOutput::DateTime,
|
||||
);
|
||||
let result =
|
||||
chrono::NaiveDateTime::parse_from_str(&result.to_string(), "%Y-%m-%d %H:%M:%S%.3f")
|
||||
.unwrap();
|
||||
NaiveDateTime::parse_from_str(&result.to_string(), "%Y-%m-%d %H:%M:%S%.3f").unwrap();
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn construct_like_escape_arg(escape_value: &OwnedValue) -> Result<char, Limb
|
||||
let mut escape_chars = text.value.chars();
|
||||
match (escape_chars.next(), escape_chars.next()) {
|
||||
(Some(escape), None) => Ok(escape),
|
||||
_ => Result::Err(LimboError::Constraint(
|
||||
_ => Err(LimboError::Constraint(
|
||||
"ESCAPE expression must be a single character".to_string(),
|
||||
)),
|
||||
}
|
||||
@@ -175,7 +175,7 @@ fn construct_glob_regex(pattern: &str) -> Result<Regex, LimboError> {
|
||||
if bracket_closed {
|
||||
Ok(Regex::new(®ex_pattern).unwrap())
|
||||
} else {
|
||||
Result::Err(LimboError::Constraint(
|
||||
Err(LimboError::Constraint(
|
||||
"blob pattern is not closed".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -903,12 +903,12 @@ impl Program {
|
||||
let connection = self.connection.upgrade().unwrap();
|
||||
let current_state = connection.transaction_state.borrow().clone();
|
||||
let (new_transaction_state, updated) = match (¤t_state, write) {
|
||||
(crate::TransactionState::Write, true) => (TransactionState::Write, false),
|
||||
(crate::TransactionState::Write, false) => (TransactionState::Write, false),
|
||||
(crate::TransactionState::Read, true) => (TransactionState::Write, true),
|
||||
(crate::TransactionState::Read, false) => (TransactionState::Read, false),
|
||||
(crate::TransactionState::None, true) => (TransactionState::Write, true),
|
||||
(crate::TransactionState::None, false) => (TransactionState::Read, true),
|
||||
(TransactionState::Write, true) => (TransactionState::Write, false),
|
||||
(TransactionState::Write, false) => (TransactionState::Write, false),
|
||||
(TransactionState::Read, true) => (TransactionState::Write, true),
|
||||
(TransactionState::Read, false) => (TransactionState::Read, false),
|
||||
(TransactionState::None, true) => (TransactionState::Write, true),
|
||||
(TransactionState::None, false) => (TransactionState::Read, true),
|
||||
};
|
||||
|
||||
if updated && matches!(current_state, TransactionState::None) {
|
||||
@@ -1476,7 +1476,7 @@ impl Program {
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect();
|
||||
let cursor = sorter::Sorter::new(order);
|
||||
let cursor = Sorter::new(order);
|
||||
sorter_cursors.insert(*cursor_id, cursor);
|
||||
state.pc += 1;
|
||||
}
|
||||
@@ -1710,7 +1710,7 @@ impl Program {
|
||||
&state.registers[*start_reg + 2],
|
||||
) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Result::Err(e),
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
OwnedValue::Integer(exec_like_with_escape(
|
||||
|
||||
@@ -35,7 +35,7 @@ pub trait ArbitraryFrom<T> {
|
||||
pub(crate) fn frequency<
|
||||
'a,
|
||||
T,
|
||||
R: rand::Rng,
|
||||
R: Rng,
|
||||
N: Sum + PartialOrd + Copy + Default + SampleUniform + SubAssign,
|
||||
>(
|
||||
choices: Vec<(N, Box<dyn Fn(&mut R) -> T + 'a>)>,
|
||||
@@ -55,23 +55,20 @@ pub(crate) fn frequency<
|
||||
}
|
||||
|
||||
/// one_of is a helper function for composing different generators with equal probability of occurence.
|
||||
pub(crate) fn one_of<'a, T, R: rand::Rng>(
|
||||
choices: Vec<Box<dyn Fn(&mut R) -> T + 'a>>,
|
||||
rng: &mut R,
|
||||
) -> T {
|
||||
pub(crate) fn one_of<'a, T, R: Rng>(choices: Vec<Box<dyn Fn(&mut R) -> T + 'a>>, rng: &mut R) -> T {
|
||||
let index = rng.gen_range(0..choices.len());
|
||||
choices[index](rng)
|
||||
}
|
||||
|
||||
/// pick is a helper function for uniformly picking a random element from a slice
|
||||
pub(crate) fn pick<'a, T, R: rand::Rng>(choices: &'a [T], rng: &mut R) -> &'a T {
|
||||
pub(crate) fn pick<'a, T, R: Rng>(choices: &'a [T], rng: &mut R) -> &'a T {
|
||||
let index = rng.gen_range(0..choices.len());
|
||||
&choices[index]
|
||||
}
|
||||
|
||||
/// pick_index is typically used for picking an index from a slice to later refer to the element
|
||||
/// at that index.
|
||||
pub(crate) fn pick_index<R: rand::Rng>(choices: usize, rng: &mut R) -> usize {
|
||||
pub(crate) fn pick_index<R: Rng>(choices: usize, rng: &mut R) -> usize {
|
||||
rng.gen_range(0..choices)
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ impl Arbitrary for ColumnType {
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&Table> for Vec<Value> {
|
||||
fn arbitrary_from<R: rand::Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
let mut row = Vec::new();
|
||||
for column in table.columns.iter() {
|
||||
let value = Value::arbitrary_from(rng, &column.column_type);
|
||||
|
||||
@@ -45,7 +45,7 @@ impl ExecutionHistory {
|
||||
|
||||
pub(crate) struct ExecutionResult {
|
||||
pub(crate) history: ExecutionHistory,
|
||||
pub(crate) error: Option<limbo_core::LimboError>,
|
||||
pub(crate) error: Option<LimboError>,
|
||||
}
|
||||
|
||||
impl ExecutionResult {
|
||||
@@ -87,7 +87,7 @@ pub(crate) fn execute_plans(
|
||||
if now.elapsed().as_secs() >= env.opts.max_time_simulation as u64 {
|
||||
return ExecutionResult::new(
|
||||
history,
|
||||
Some(limbo_core::LimboError::InternalError(
|
||||
Some(LimboError::InternalError(
|
||||
"maximum time for simulation reached".into(),
|
||||
)),
|
||||
);
|
||||
@@ -170,7 +170,7 @@ fn execute_interaction(
|
||||
) -> Result<ExecutionContinuation> {
|
||||
log::info!("executing: {}", interaction);
|
||||
match interaction {
|
||||
generation::plan::Interaction::Query(_) => {
|
||||
Interaction::Query(_) => {
|
||||
let conn = match &mut env.connections[connection_index] {
|
||||
SimConnection::Connected(conn) => conn,
|
||||
SimConnection::Disconnected => unreachable!(),
|
||||
@@ -181,11 +181,11 @@ fn execute_interaction(
|
||||
log::debug!("{:?}", results);
|
||||
stack.push(results);
|
||||
}
|
||||
generation::plan::Interaction::Assertion(_) => {
|
||||
Interaction::Assertion(_) => {
|
||||
interaction.execute_assertion(stack, env)?;
|
||||
stack.clear();
|
||||
}
|
||||
generation::plan::Interaction::Assumption(_) => {
|
||||
Interaction::Assumption(_) => {
|
||||
let assumption_result = interaction.execute_assumption(stack, env);
|
||||
stack.clear();
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ impl SimulatorFile {
|
||||
}
|
||||
}
|
||||
|
||||
impl limbo_core::File for SimulatorFile {
|
||||
impl File for SimulatorFile {
|
||||
fn lock_file(&self, exclusive: bool) -> Result<()> {
|
||||
if *self.fault.borrow() {
|
||||
return Err(limbo_core::LimboError::InternalError(
|
||||
@@ -88,7 +88,7 @@ impl limbo_core::File for SimulatorFile {
|
||||
fn pwrite(
|
||||
&self,
|
||||
pos: usize,
|
||||
buffer: Rc<std::cell::RefCell<limbo_core::Buffer>>,
|
||||
buffer: Rc<RefCell<limbo_core::Buffer>>,
|
||||
c: Rc<limbo_core::Completion>,
|
||||
) -> Result<()> {
|
||||
*self.nr_pwrite_calls.borrow_mut() += 1;
|
||||
|
||||
@@ -46,7 +46,7 @@ pub struct sqlite3 {
|
||||
pub(crate) err_mask: ffi::c_int,
|
||||
pub(crate) malloc_failed: bool,
|
||||
pub(crate) e_open_state: u8,
|
||||
pub(crate) p_err: *mut std::ffi::c_void,
|
||||
pub(crate) p_err: *mut ffi::c_void,
|
||||
}
|
||||
|
||||
impl sqlite3 {
|
||||
@@ -107,7 +107,7 @@ pub unsafe extern "C" fn sqlite3_open(
|
||||
if db_out.is_null() {
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
let filename = ffi::CStr::from_ptr(filename);
|
||||
let filename = CStr::from_ptr(filename);
|
||||
let filename = match filename.to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return SQLITE_MISUSE,
|
||||
@@ -164,14 +164,9 @@ pub unsafe extern "C" fn sqlite3_trace_v2(
|
||||
_db: *mut sqlite3,
|
||||
_mask: ffi::c_uint,
|
||||
_callback: Option<
|
||||
unsafe extern "C" fn(
|
||||
ffi::c_uint,
|
||||
*mut std::ffi::c_void,
|
||||
*mut std::ffi::c_void,
|
||||
*mut std::ffi::c_void,
|
||||
),
|
||||
unsafe extern "C" fn(ffi::c_uint, *mut ffi::c_void, *mut ffi::c_void, *mut ffi::c_void),
|
||||
>,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
@@ -181,7 +176,7 @@ pub unsafe extern "C" fn sqlite3_progress_handler(
|
||||
_db: *mut sqlite3,
|
||||
_n: ffi::c_int,
|
||||
_callback: Option<unsafe extern "C" fn() -> ffi::c_int>,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
@@ -195,15 +190,13 @@ pub unsafe extern "C" fn sqlite3_busy_timeout(_db: *mut sqlite3, _ms: ffi::c_int
|
||||
pub unsafe extern "C" fn sqlite3_set_authorizer(
|
||||
_db: *mut sqlite3,
|
||||
_callback: Option<unsafe extern "C" fn() -> ffi::c_int>,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_context_db_handle(
|
||||
_context: *mut std::ffi::c_void,
|
||||
) -> *mut std::ffi::c_void {
|
||||
pub unsafe extern "C" fn sqlite3_context_db_handle(_context: *mut ffi::c_void) -> *mut ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -219,7 +212,7 @@ pub unsafe extern "C" fn sqlite3_prepare_v2(
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
let db: &mut sqlite3 = &mut *db;
|
||||
let sql = ffi::CStr::from_ptr(sql);
|
||||
let sql = CStr::from_ptr(sql);
|
||||
let sql = match sql.to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return SQLITE_MISUSE,
|
||||
@@ -242,7 +235,7 @@ pub unsafe extern "C" fn sqlite3_finalize(stmt: *mut sqlite3_stmt) -> ffi::c_int
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_step(stmt: *mut sqlite3_stmt) -> std::ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_step(stmt: *mut sqlite3_stmt) -> ffi::c_int {
|
||||
let stmt = &mut *stmt;
|
||||
if let Ok(result) = stmt.stmt.step() {
|
||||
match result {
|
||||
@@ -262,10 +255,10 @@ pub unsafe extern "C" fn sqlite3_step(stmt: *mut sqlite3_stmt) -> std::ffi::c_in
|
||||
|
||||
type exec_callback = Option<
|
||||
unsafe extern "C" fn(
|
||||
context: *mut std::ffi::c_void,
|
||||
n_column: std::ffi::c_int,
|
||||
argv: *mut *mut std::ffi::c_char,
|
||||
colv: *mut *mut std::ffi::c_char,
|
||||
context: *mut ffi::c_void,
|
||||
n_column: ffi::c_int,
|
||||
argv: *mut *mut ffi::c_char,
|
||||
colv: *mut *mut ffi::c_char,
|
||||
) -> ffi::c_int,
|
||||
>;
|
||||
|
||||
@@ -274,14 +267,14 @@ pub unsafe extern "C" fn sqlite3_exec(
|
||||
db: *mut sqlite3,
|
||||
sql: *const ffi::c_char,
|
||||
_callback: exec_callback,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_err: *mut *mut std::ffi::c_char,
|
||||
_context: *mut ffi::c_void,
|
||||
_err: *mut *mut ffi::c_char,
|
||||
) -> ffi::c_int {
|
||||
if db.is_null() || sql.is_null() {
|
||||
return SQLITE_MISUSE;
|
||||
}
|
||||
let db: &mut sqlite3 = &mut *db;
|
||||
let sql = ffi::CStr::from_ptr(sql);
|
||||
let sql = CStr::from_ptr(sql);
|
||||
let sql = match sql.to_str() {
|
||||
Ok(s) => s,
|
||||
Err(_) => return SQLITE_MISUSE,
|
||||
@@ -317,8 +310,8 @@ pub unsafe extern "C" fn sqlite3_stmt_busy(_stmt: *mut sqlite3_stmt) -> ffi::c_i
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_serialize(
|
||||
_db: *mut sqlite3,
|
||||
_schema: *const std::ffi::c_char,
|
||||
_out: *mut *mut std::ffi::c_void,
|
||||
_schema: *const ffi::c_char,
|
||||
_out: *mut *mut ffi::c_void,
|
||||
_out_bytes: *mut ffi::c_int,
|
||||
_flags: ffi::c_uint,
|
||||
) -> ffi::c_int {
|
||||
@@ -328,8 +321,8 @@ pub unsafe extern "C" fn sqlite3_serialize(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_deserialize(
|
||||
_db: *mut sqlite3,
|
||||
_schema: *const std::ffi::c_char,
|
||||
_in_: *const std::ffi::c_void,
|
||||
_schema: *const ffi::c_char,
|
||||
_in_: *const ffi::c_void,
|
||||
_in_bytes: ffi::c_int,
|
||||
_flags: ffi::c_uint,
|
||||
) -> ffi::c_int {
|
||||
@@ -381,12 +374,12 @@ pub unsafe extern "C" fn sqlite3_limit(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_malloc64(_n: ffi::c_int) -> *mut std::ffi::c_void {
|
||||
pub unsafe extern "C" fn sqlite3_malloc64(_n: ffi::c_int) -> *mut ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_free(_ptr: *mut std::ffi::c_void) {
|
||||
pub unsafe extern "C" fn sqlite3_free(_ptr: *mut ffi::c_void) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -404,52 +397,50 @@ pub unsafe extern "C" fn sqlite3_errcode(_db: *mut sqlite3) -> ffi::c_int {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_errstr(_err: ffi::c_int) -> *const std::ffi::c_char {
|
||||
pub unsafe extern "C" fn sqlite3_errstr(_err: ffi::c_int) -> *const ffi::c_char {
|
||||
sqlite3_errstr_impl(_err)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_user_data(
|
||||
_context: *mut std::ffi::c_void,
|
||||
) -> *mut std::ffi::c_void {
|
||||
pub unsafe extern "C" fn sqlite3_user_data(_context: *mut ffi::c_void) -> *mut ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_backup_init(
|
||||
_dest_db: *mut sqlite3,
|
||||
_dest_name: *const std::ffi::c_char,
|
||||
_dest_name: *const ffi::c_char,
|
||||
_source_db: *mut sqlite3,
|
||||
_source_name: *const std::ffi::c_char,
|
||||
) -> *mut std::ffi::c_void {
|
||||
_source_name: *const ffi::c_char,
|
||||
) -> *mut ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_backup_step(
|
||||
_backup: *mut std::ffi::c_void,
|
||||
_backup: *mut ffi::c_void,
|
||||
_n_pages: ffi::c_int,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_backup_remaining(_backup: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_backup_remaining(_backup: *mut ffi::c_void) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_backup_pagecount(_backup: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_backup_pagecount(_backup: *mut ffi::c_void) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_backup_finish(_backup: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_backup_finish(_backup: *mut ffi::c_void) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_expanded_sql(_stmt: *mut sqlite3_stmt) -> *mut std::ffi::c_char {
|
||||
pub unsafe extern "C" fn sqlite3_expanded_sql(_stmt: *mut sqlite3_stmt) -> *mut ffi::c_char {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -473,7 +464,7 @@ pub unsafe extern "C" fn sqlite3_bind_parameter_count(_stmt: *mut sqlite3_stmt)
|
||||
pub unsafe extern "C" fn sqlite3_bind_parameter_name(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
) -> *const std::ffi::c_char {
|
||||
) -> *const ffi::c_char {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -507,9 +498,9 @@ pub unsafe extern "C" fn sqlite3_bind_double(
|
||||
pub unsafe extern "C" fn sqlite3_bind_text(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
_text: *const std::ffi::c_char,
|
||||
_text: *const ffi::c_char,
|
||||
_len: ffi::c_int,
|
||||
_destroy: *mut std::ffi::c_void,
|
||||
_destroy: *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
@@ -518,9 +509,9 @@ pub unsafe extern "C" fn sqlite3_bind_text(
|
||||
pub unsafe extern "C" fn sqlite3_bind_blob(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
_blob: *const std::ffi::c_void,
|
||||
_blob: *const ffi::c_void,
|
||||
_len: ffi::c_int,
|
||||
_destroy: *mut std::ffi::c_void,
|
||||
_destroy: *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
@@ -542,7 +533,7 @@ pub unsafe extern "C" fn sqlite3_column_count(_stmt: *mut sqlite3_stmt) -> ffi::
|
||||
pub unsafe extern "C" fn sqlite3_column_decltype(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
) -> *const std::ffi::c_char {
|
||||
) -> *const ffi::c_char {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -550,7 +541,7 @@ pub unsafe extern "C" fn sqlite3_column_decltype(
|
||||
pub unsafe extern "C" fn sqlite3_column_name(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
) -> *const std::ffi::c_char {
|
||||
) -> *const ffi::c_char {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -568,7 +559,7 @@ pub unsafe extern "C" fn sqlite3_column_double(_stmt: *mut sqlite3_stmt, _idx: f
|
||||
pub unsafe extern "C" fn sqlite3_column_blob(
|
||||
_stmt: *mut sqlite3_stmt,
|
||||
_idx: ffi::c_int,
|
||||
) -> *const std::ffi::c_void {
|
||||
) -> *const ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -581,7 +572,7 @@ pub unsafe extern "C" fn sqlite3_column_bytes(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_type(value: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_value_type(value: *mut ffi::c_void) -> ffi::c_int {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
@@ -594,7 +585,7 @@ pub unsafe extern "C" fn sqlite3_value_type(value: *mut std::ffi::c_void) -> ffi
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_int64(value: *mut std::ffi::c_void) -> i64 {
|
||||
pub unsafe extern "C" fn sqlite3_value_int64(value: *mut ffi::c_void) -> i64 {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
@@ -604,7 +595,7 @@ pub unsafe extern "C" fn sqlite3_value_int64(value: *mut std::ffi::c_void) -> i6
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_double(value: *mut std::ffi::c_void) -> f64 {
|
||||
pub unsafe extern "C" fn sqlite3_value_double(value: *mut ffi::c_void) -> f64 {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
@@ -614,9 +605,7 @@ pub unsafe extern "C" fn sqlite3_value_double(value: *mut std::ffi::c_void) -> f
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_text(
|
||||
value: *mut std::ffi::c_void,
|
||||
) -> *const std::ffi::c_uchar {
|
||||
pub unsafe extern "C" fn sqlite3_value_text(value: *mut ffi::c_void) -> *const ffi::c_uchar {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
@@ -626,19 +615,17 @@ pub unsafe extern "C" fn sqlite3_value_text(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_blob(
|
||||
value: *mut std::ffi::c_void,
|
||||
) -> *const std::ffi::c_void {
|
||||
pub unsafe extern "C" fn sqlite3_value_blob(value: *mut ffi::c_void) -> *const ffi::c_void {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
limbo_core::Value::Blob(blob) => blob.as_ptr() as *const std::ffi::c_void,
|
||||
limbo_core::Value::Blob(blob) => blob.as_ptr() as *const ffi::c_void,
|
||||
_ => std::ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_value_bytes(value: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_value_bytes(value: *mut ffi::c_void) -> ffi::c_int {
|
||||
let value = value as *mut limbo_core::Value;
|
||||
let value = &*value;
|
||||
match value {
|
||||
@@ -650,8 +637,8 @@ pub unsafe extern "C" fn sqlite3_value_bytes(value: *mut std::ffi::c_void) -> ff
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_column_text(
|
||||
stmt: *mut sqlite3_stmt,
|
||||
idx: std::ffi::c_int,
|
||||
) -> *const std::ffi::c_uchar {
|
||||
idx: ffi::c_int,
|
||||
) -> *const ffi::c_uchar {
|
||||
let stmt = &mut *stmt;
|
||||
let row = stmt.row.borrow();
|
||||
let row = match row.as_ref() {
|
||||
@@ -665,11 +652,11 @@ pub unsafe extern "C" fn sqlite3_column_text(
|
||||
}
|
||||
|
||||
pub struct TabResult {
|
||||
az_result: Vec<*mut std::ffi::c_char>,
|
||||
az_result: Vec<*mut ffi::c_char>,
|
||||
n_row: usize,
|
||||
n_column: usize,
|
||||
z_err_msg: Option<CString>,
|
||||
rc: std::ffi::c_int,
|
||||
rc: ffi::c_int,
|
||||
}
|
||||
|
||||
impl TabResult {
|
||||
@@ -697,11 +684,11 @@ impl TabResult {
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn sqlite_get_table_cb(
|
||||
context: *mut std::ffi::c_void,
|
||||
n_column: std::ffi::c_int,
|
||||
argv: *mut *mut std::ffi::c_char,
|
||||
colv: *mut *mut std::ffi::c_char,
|
||||
) -> std::ffi::c_int {
|
||||
context: *mut ffi::c_void,
|
||||
n_column: ffi::c_int,
|
||||
argv: *mut *mut ffi::c_char,
|
||||
colv: *mut *mut ffi::c_char,
|
||||
) -> ffi::c_int {
|
||||
let res = &mut *(context as *mut TabResult);
|
||||
|
||||
if res.n_row == 0 {
|
||||
@@ -729,7 +716,7 @@ unsafe extern "C" fn sqlite_get_table_cb(
|
||||
let value_cstring = if !value.is_null() {
|
||||
let len = libc::strlen(value);
|
||||
let mut buf = Vec::with_capacity(len + 1);
|
||||
libc::strncpy(buf.as_mut_ptr() as *mut std::ffi::c_char, value, len);
|
||||
libc::strncpy(buf.as_mut_ptr() as *mut ffi::c_char, value, len);
|
||||
buf.set_len(len + 1);
|
||||
CString::from_vec_with_nul(buf).unwrap()
|
||||
} else {
|
||||
@@ -745,12 +732,12 @@ unsafe extern "C" fn sqlite_get_table_cb(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_get_table(
|
||||
db: *mut sqlite3,
|
||||
sql: *const std::ffi::c_char,
|
||||
paz_result: *mut *mut *mut std::ffi::c_char,
|
||||
pn_row: *mut std::ffi::c_int,
|
||||
pn_column: *mut std::ffi::c_int,
|
||||
pz_err_msg: *mut *mut std::ffi::c_char,
|
||||
) -> std::ffi::c_int {
|
||||
sql: *const ffi::c_char,
|
||||
paz_result: *mut *mut *mut ffi::c_char,
|
||||
pn_row: *mut ffi::c_int,
|
||||
pn_column: *mut ffi::c_int,
|
||||
pz_err_msg: *mut *mut ffi::c_char,
|
||||
) -> ffi::c_int {
|
||||
if db.is_null() || sql.is_null() || paz_result.is_null() {
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
@@ -781,8 +768,8 @@ pub unsafe extern "C" fn sqlite3_get_table(
|
||||
}
|
||||
|
||||
*paz_result = res.az_result.as_mut_ptr();
|
||||
*pn_row = res.n_row as std::ffi::c_int;
|
||||
*pn_column = res.n_column as std::ffi::c_int;
|
||||
*pn_row = res.n_row as ffi::c_int;
|
||||
*pn_column = res.n_column as ffi::c_int;
|
||||
|
||||
std::mem::forget(res);
|
||||
|
||||
@@ -790,60 +777,60 @@ pub unsafe extern "C" fn sqlite3_get_table(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_free_table(paz_result: *mut *mut *mut std::ffi::c_char) {
|
||||
pub unsafe extern "C" fn sqlite3_free_table(paz_result: *mut *mut *mut ffi::c_char) {
|
||||
let res = &mut *(paz_result as *mut TabResult);
|
||||
res.free();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_null(_context: *mut std::ffi::c_void) {
|
||||
pub unsafe extern "C" fn sqlite3_result_null(_context: *mut ffi::c_void) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_int64(_context: *mut std::ffi::c_void, _val: i64) {
|
||||
pub unsafe extern "C" fn sqlite3_result_int64(_context: *mut ffi::c_void, _val: i64) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_double(_context: *mut std::ffi::c_void, _val: f64) {
|
||||
pub unsafe extern "C" fn sqlite3_result_double(_context: *mut ffi::c_void, _val: f64) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_text(
|
||||
_context: *mut std::ffi::c_void,
|
||||
_text: *const std::ffi::c_char,
|
||||
_context: *mut ffi::c_void,
|
||||
_text: *const ffi::c_char,
|
||||
_len: ffi::c_int,
|
||||
_destroy: *mut std::ffi::c_void,
|
||||
_destroy: *mut ffi::c_void,
|
||||
) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_blob(
|
||||
_context: *mut std::ffi::c_void,
|
||||
_blob: *const std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
_blob: *const ffi::c_void,
|
||||
_len: ffi::c_int,
|
||||
_destroy: *mut std::ffi::c_void,
|
||||
_destroy: *mut ffi::c_void,
|
||||
) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_error_nomem(_context: *mut std::ffi::c_void) {
|
||||
pub unsafe extern "C" fn sqlite3_result_error_nomem(_context: *mut ffi::c_void) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_error_toobig(_context: *mut std::ffi::c_void) {
|
||||
pub unsafe extern "C" fn sqlite3_result_error_toobig(_context: *mut ffi::c_void) {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_result_error(
|
||||
_context: *mut std::ffi::c_void,
|
||||
_err: *const std::ffi::c_char,
|
||||
_context: *mut ffi::c_void,
|
||||
_err: *const ffi::c_char,
|
||||
_len: ffi::c_int,
|
||||
) {
|
||||
stub!();
|
||||
@@ -851,29 +838,29 @@ pub unsafe extern "C" fn sqlite3_result_error(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_aggregate_context(
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
_n: ffi::c_int,
|
||||
) -> *mut std::ffi::c_void {
|
||||
) -> *mut ffi::c_void {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_blob_open(
|
||||
_db: *mut sqlite3,
|
||||
_db_name: *const std::ffi::c_char,
|
||||
_table_name: *const std::ffi::c_char,
|
||||
_column_name: *const std::ffi::c_char,
|
||||
_db_name: *const ffi::c_char,
|
||||
_table_name: *const ffi::c_char,
|
||||
_column_name: *const ffi::c_char,
|
||||
_rowid: i64,
|
||||
_flags: ffi::c_int,
|
||||
_blob_out: *mut *mut std::ffi::c_void,
|
||||
_blob_out: *mut *mut ffi::c_void,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_blob_read(
|
||||
_blob: *mut std::ffi::c_void,
|
||||
_data: *mut std::ffi::c_void,
|
||||
_blob: *mut ffi::c_void,
|
||||
_data: *mut ffi::c_void,
|
||||
_n: ffi::c_int,
|
||||
_offset: ffi::c_int,
|
||||
) -> ffi::c_int {
|
||||
@@ -882,8 +869,8 @@ pub unsafe extern "C" fn sqlite3_blob_read(
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_blob_write(
|
||||
_blob: *mut std::ffi::c_void,
|
||||
_data: *const std::ffi::c_void,
|
||||
_blob: *mut ffi::c_void,
|
||||
_data: *const ffi::c_void,
|
||||
_n: ffi::c_int,
|
||||
_offset: ffi::c_int,
|
||||
) -> ffi::c_int {
|
||||
@@ -891,19 +878,19 @@ pub unsafe extern "C" fn sqlite3_blob_write(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_blob_bytes(_blob: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_blob_bytes(_blob: *mut ffi::c_void) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_blob_close(_blob: *mut std::ffi::c_void) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_blob_close(_blob: *mut ffi::c_void) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_stricmp(
|
||||
_a: *const std::ffi::c_char,
|
||||
_b: *const std::ffi::c_char,
|
||||
_a: *const ffi::c_char,
|
||||
_b: *const ffi::c_char,
|
||||
) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
@@ -911,9 +898,9 @@ pub unsafe extern "C" fn sqlite3_stricmp(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_create_collation_v2(
|
||||
_db: *mut sqlite3,
|
||||
_name: *const std::ffi::c_char,
|
||||
_name: *const ffi::c_char,
|
||||
_enc: ffi::c_int,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
_cmp: Option<unsafe extern "C" fn() -> ffi::c_int>,
|
||||
_destroy: Option<unsafe extern "C" fn()>,
|
||||
) -> ffi::c_int {
|
||||
@@ -923,10 +910,10 @@ pub unsafe extern "C" fn sqlite3_create_collation_v2(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_create_function_v2(
|
||||
_db: *mut sqlite3,
|
||||
_name: *const std::ffi::c_char,
|
||||
_name: *const ffi::c_char,
|
||||
_n_args: ffi::c_int,
|
||||
_enc: ffi::c_int,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
_func: Option<unsafe extern "C" fn()>,
|
||||
_step: Option<unsafe extern "C" fn()>,
|
||||
_final_: Option<unsafe extern "C" fn()>,
|
||||
@@ -938,10 +925,10 @@ pub unsafe extern "C" fn sqlite3_create_function_v2(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_create_window_function(
|
||||
_db: *mut sqlite3,
|
||||
_name: *const std::ffi::c_char,
|
||||
_name: *const ffi::c_char,
|
||||
_n_args: ffi::c_int,
|
||||
_enc: ffi::c_int,
|
||||
_context: *mut std::ffi::c_void,
|
||||
_context: *mut ffi::c_void,
|
||||
_x_step: Option<unsafe extern "C" fn()>,
|
||||
_x_final: Option<unsafe extern "C" fn()>,
|
||||
_x_value: Option<unsafe extern "C" fn()>,
|
||||
@@ -952,7 +939,7 @@ pub unsafe extern "C" fn sqlite3_create_window_function(
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_errmsg(_db: *mut sqlite3) -> *const std::ffi::c_char {
|
||||
pub unsafe extern "C" fn sqlite3_errmsg(_db: *mut sqlite3) -> *const ffi::c_char {
|
||||
if _db.is_null() {
|
||||
return sqlite3_errstr(SQLITE_NOMEM);
|
||||
}
|
||||
@@ -965,7 +952,7 @@ pub unsafe extern "C" fn sqlite3_errmsg(_db: *mut sqlite3) -> *const std::ffi::c
|
||||
|
||||
let err_msg = if (*_db).err_code != SQLITE_OK {
|
||||
if !(*_db).p_err.is_null() {
|
||||
(*_db).p_err as *const std::ffi::c_char
|
||||
(*_db).p_err as *const ffi::c_char
|
||||
} else {
|
||||
std::ptr::null()
|
||||
}
|
||||
@@ -994,7 +981,7 @@ pub unsafe extern "C" fn sqlite3_extended_errcode(_db: *mut sqlite3) -> ffi::c_i
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_complete(_sql: *const std::ffi::c_char) -> ffi::c_int {
|
||||
pub unsafe extern "C" fn sqlite3_complete(_sql: *const ffi::c_char) -> ffi::c_int {
|
||||
stub!();
|
||||
}
|
||||
|
||||
@@ -1004,7 +991,7 @@ pub unsafe extern "C" fn sqlite3_threadsafe() -> ffi::c_int {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_libversion() -> *const std::ffi::c_char {
|
||||
pub unsafe extern "C" fn sqlite3_libversion() -> *const ffi::c_char {
|
||||
c"3.42.0".as_ptr()
|
||||
}
|
||||
|
||||
@@ -1013,7 +1000,7 @@ pub unsafe extern "C" fn sqlite3_libversion_number() -> ffi::c_int {
|
||||
3042000
|
||||
}
|
||||
|
||||
fn sqlite3_errstr_impl(rc: i32) -> *const std::ffi::c_char {
|
||||
fn sqlite3_errstr_impl(rc: i32) -> *const ffi::c_char {
|
||||
const ERROR_MESSAGES: [&str; 29] = [
|
||||
"not an error", // SQLITE_OK
|
||||
"SQL logic error", // SQLITE_ERROR
|
||||
@@ -1055,18 +1042,18 @@ fn sqlite3_errstr_impl(rc: i32) -> *const std::ffi::c_char {
|
||||
const NO_MORE_ROWS_AVAILABLE: &str = "no more rows available";
|
||||
|
||||
match rc {
|
||||
SQLITE_ABORT_ROLLBACK => ABORT_ROLLBACK.as_ptr() as *const std::ffi::c_char,
|
||||
SQLITE_ROW => ANOTHER_ROW_AVAILABLE.as_ptr() as *const std::ffi::c_char,
|
||||
SQLITE_DONE => NO_MORE_ROWS_AVAILABLE.as_ptr() as *const std::ffi::c_char,
|
||||
SQLITE_ABORT_ROLLBACK => ABORT_ROLLBACK.as_ptr() as *const ffi::c_char,
|
||||
SQLITE_ROW => ANOTHER_ROW_AVAILABLE.as_ptr() as *const ffi::c_char,
|
||||
SQLITE_DONE => NO_MORE_ROWS_AVAILABLE.as_ptr() as *const ffi::c_char,
|
||||
_ => {
|
||||
let rc = rc & 0xff;
|
||||
if rc >= 0
|
||||
&& rc < ERROR_MESSAGES.len() as i32
|
||||
&& !ERROR_MESSAGES[rc as usize].is_empty()
|
||||
{
|
||||
ERROR_MESSAGES[rc as usize].as_ptr() as *const std::ffi::c_char
|
||||
ERROR_MESSAGES[rc as usize].as_ptr() as *const ffi::c_char
|
||||
} else {
|
||||
UNKNOWN_ERROR.as_ptr() as *const std::ffi::c_char
|
||||
UNKNOWN_ERROR.as_ptr() as *const ffi::c_char
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1075,7 +1062,7 @@ fn sqlite3_errstr_impl(rc: i32) -> *const std::ffi::c_char {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_wal_checkpoint(
|
||||
_db: *mut sqlite3,
|
||||
_db_name: *const std::ffi::c_char,
|
||||
_db_name: *const ffi::c_char,
|
||||
) -> ffi::c_int {
|
||||
sqlite3_wal_checkpoint_v2(
|
||||
_db,
|
||||
@@ -1089,7 +1076,7 @@ pub unsafe extern "C" fn sqlite3_wal_checkpoint(
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sqlite3_wal_checkpoint_v2(
|
||||
db: *mut sqlite3,
|
||||
_db_name: *const std::ffi::c_char,
|
||||
_db_name: *const ffi::c_char,
|
||||
_mode: ffi::c_int,
|
||||
_log_size: *mut ffi::c_int,
|
||||
_checkpoint_count: *mut ffi::c_int,
|
||||
|
||||
@@ -391,7 +391,7 @@ mod tests {
|
||||
// threshold is 1000 by default
|
||||
|
||||
fn insert(i: usize, conn: &Rc<Connection>, tmp_db: &TempDatabase) -> anyhow::Result<()> {
|
||||
log::debug!("inserting {}", i);
|
||||
debug!("inserting {}", i);
|
||||
let insert_query = format!("INSERT INTO test VALUES ({})", i);
|
||||
match conn.query(insert_query) {
|
||||
Ok(Some(ref mut rows)) => loop {
|
||||
@@ -408,13 +408,13 @@ mod tests {
|
||||
eprintln!("{}", err);
|
||||
}
|
||||
};
|
||||
log::debug!("inserted {}", i);
|
||||
debug!("inserted {}", i);
|
||||
tmp_db.io.run_once()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn count(conn: &Rc<Connection>, tmp_db: &TempDatabase) -> anyhow::Result<usize> {
|
||||
log::debug!("counting");
|
||||
debug!("counting");
|
||||
let list_query = "SELECT count(x) FROM test";
|
||||
loop {
|
||||
if let Some(ref mut rows) = conn.query(list_query).unwrap() {
|
||||
@@ -426,7 +426,7 @@ mod tests {
|
||||
Value::Integer(i) => *i as i32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
log::debug!("counted {}", count);
|
||||
debug!("counted {}", count);
|
||||
return Ok(count as usize);
|
||||
}
|
||||
StepResult::IO => {
|
||||
|
||||
Reference in New Issue
Block a user