Fix merge conflicts and adapt schema.rs to use RecordCursor

This commit is contained in:
Krishna Vishal
2025-07-12 20:49:19 +05:30
parent ea4a4708ea
commit a79fe458db
2 changed files with 70 additions and 27 deletions

View File

@@ -5,7 +5,7 @@ use crate::translate::plan::SelectPlan;
use crate::types::CursorResult;
use crate::util::{module_args_from_sql, module_name_from_sql, UnparsedFromSqlIndex};
use crate::{util::normalize_ident, Result};
use crate::{LimboError, MvCursor, Pager, SymbolTable, VirtualTable};
use crate::{LimboError, MvCursor, Pager, RefValue, SymbolTable, VirtualTable};
use core::fmt;
use fallible_iterator::FallibleIterator;
use std::cell::RefCell;
@@ -148,7 +148,7 @@ impl Schema {
pager: Rc<Pager>,
syms: &SymbolTable,
) -> Result<()> {
let mut cursor = BTreeCursor::new_table(mv_cursor, pager.clone(), 1);
let mut cursor = BTreeCursor::new_table(mv_cursor, pager.clone(), 1, 10);
let mut from_sql_indexes = Vec::with_capacity(10);
let mut automatic_indices: HashMap<String, Vec<(String, usize)>> =
@@ -178,16 +178,32 @@ impl Schema {
break;
};
let ty = row.get::<&str>(0)?;
match ty {
let mut record_cursor = cursor.record_cursor.borrow_mut();
let ty_value = record_cursor.get_value(&row, 0)?;
let RefValue::Text(ty) = ty_value else {
return Err(LimboError::ConversionError("Expected text value".into()));
};
match ty.as_str() {
"table" => {
let root_page = row.get::<i64>(3)?;
let sql = row.get::<&str>(4)?;
let root_page_value = record_cursor.get_value(&row, 3)?;
let RefValue::Integer(root_page) = root_page_value else {
return Err(LimboError::ConversionError("Expected integer value".into()));
};
let sql_value = record_cursor.get_value(&row, 4)?;
let RefValue::Text(sql_text) = sql_value else {
return Err(LimboError::ConversionError("Expected text value".into()));
};
let sql = sql_text.as_str();
let create_virtual = "create virtual";
if root_page == 0
&& sql[0..create_virtual.len()].eq_ignore_ascii_case(create_virtual)
{
let name: &str = row.get::<&str>(1)?;
let name_value = record_cursor.get_value(&row, 1)?;
let RefValue::Text(name_text) = name_value else {
return Err(LimboError::ConversionError("Expected text value".into()));
};
let name = name_text.as_str();
// a virtual table is found in the sqlite_schema, but it's no
// longer in the in-memory schema. We need to recreate it if
// the module is loaded in the symbol table.
@@ -210,36 +226,60 @@ impl Schema {
self.add_btree_table(Rc::new(table));
}
"index" => {
let root_page = row.get::<i64>(3)?;
match row.get::<&str>(4) {
Ok(sql) => {
let root_page_value = record_cursor.get_value(&row, 3)?;
let RefValue::Integer(root_page) = root_page_value else {
return Err(LimboError::ConversionError("Expected integer value".into()));
};
match record_cursor.get_value(&row, 4) {
Ok(RefValue::Text(sql_text)) => {
let table_name_value = record_cursor.get_value(&row, 2)?;
let RefValue::Text(table_name_text) = table_name_value else {
return Err(LimboError::ConversionError(
"Expected text value".into(),
));
};
from_sql_indexes.push(UnparsedFromSqlIndex {
table_name: row.get::<&str>(2)?.to_string(),
table_name: table_name_text.as_str().to_string(),
root_page: root_page as usize,
sql: sql.to_string(),
sql: sql_text.as_str().to_string(),
});
}
_ => {
// Automatic index on primary key and/or unique constraint, e.g.
// table|foo|foo|2|CREATE TABLE foo (a text PRIMARY KEY, b)
// index|sqlite_autoindex_foo_1|foo|3|
let index_name = row.get::<&str>(1)?.to_string();
let table_name = row.get::<&str>(2)?.to_string();
let root_page = row.get::<i64>(3)?;
match automatic_indices.entry(table_name) {
let index_name_value = record_cursor.get_value(&row, 1)?;
let RefValue::Text(index_name_text) = index_name_value else {
return Err(LimboError::ConversionError(
"Expected text value".into(),
));
};
let table_name_value = record_cursor.get_value(&row, 2)?;
let RefValue::Text(table_name_text) = table_name_value else {
return Err(LimboError::ConversionError(
"Expected text value".into(),
));
};
match automatic_indices.entry(table_name_text.as_str().to_string()) {
Entry::Vacant(e) => {
e.insert(vec![(index_name, root_page as usize)]);
e.insert(vec![(
index_name_text.as_str().to_string(),
root_page as usize,
)]);
}
Entry::Occupied(mut e) => {
e.get_mut().push((index_name, root_page as usize));
e.get_mut().push((
index_name_text.as_str().to_string(),
root_page as usize,
));
}
};
}
}
}
}
_ => {}
};
drop(record_cursor);
drop(row);
if matches!(cursor.next()?, CursorResult::IO) {

View File

@@ -9,7 +9,9 @@ use crate::storage::sqlite3_ondisk::read_varint;
use crate::storage::wal::DummyWAL;
use crate::storage::{self, header_accessor};
use crate::translate::collate::CollationSeq;
use crate::types::{compare_records_generic, ImmutableRecord, Text, TextSubtype};
use crate::types::{
compare_immutable, compare_records_generic, ImmutableRecord, Text, TextSubtype,
};
use crate::util::normalize_ident;
use crate::vdbe::registers_to_ref_values;
use crate::{
@@ -4730,9 +4732,10 @@ pub fn op_idx_insert(
// Cursor is pointing at a record; if the index has a rowid, exclude it from the comparison since it's a pointer to the table row;
// UNIQUE indexes disallow duplicates like (a=1,b=2,rowid=1) and (a=1,b=2,rowid=2).
let existing_key = if cursor.has_rowid() {
&record.get_values()[..record.count().saturating_sub(1)]
let count = cursor.record_cursor.borrow_mut().count(record);
record.get_values()[..count.saturating_sub(1)].to_vec()
} else {
record.get_values()
record.get_values().to_vec()
};
let inserted_key_vals = &record_to_insert.get_values();
if existing_key.len() != inserted_key_vals.len() {
@@ -4740,7 +4743,7 @@ pub fn op_idx_insert(
}
let conflict = compare_immutable(
existing_key,
existing_key.as_slice(),
inserted_key_vals,
cursor.key_sort_order(),
&cursor.collations,