diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 002459955..d4f58151a 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -2501,22 +2501,28 @@ impl BTreeCursor { /// Search for a key in an Index Btree. Looking up indexes that need to be unique, we cannot compare the rowid pub fn key_exists_in_index(&mut self, key: &ImmutableRecord) -> Result> { return_if_io!(self.do_seek(SeekKey::IndexKey(key), SeekOp::GE)); - if let Some(record) = self.record().as_ref() { - // get existing record, excluding the rowid - assert!(record.len() > 0); - let existing_key = &record.get_values()[..record.count() - 1]; - let inserted_key_vals = &key.get_values(); - if existing_key - .iter() - .zip(inserted_key_vals.iter()) - .all(|(a, b)| a == b) - { - return Ok(CursorResult::Ok(true)); // duplicate + + let record_opt = self.record(); + match record_opt.as_ref() { + Some(record) => { + // Existing record found — compare prefix + let existing_key = &record.get_values()[..record.count().saturating_sub(1)]; + let inserted_key_vals = &key.get_values(); + if existing_key + .iter() + .zip(inserted_key_vals.iter()) + .all(|(a, b)| a == b) + { + return Ok(CursorResult::Ok(true)); // duplicate + } + } + None => { + // Cursor not pointing at a record — table is empty or past last + return Ok(CursorResult::Ok(false)); } - } else { - return Err(LimboError::InvalidArgument("Expected Record key".into())); } - Ok(CursorResult::Ok(false)) // no matching key found + + Ok(CursorResult::Ok(false)) // not a duplicate } pub fn exists(&mut self, key: &OwnedValue) -> Result> { diff --git a/core/translate/index.rs b/core/translate/index.rs index c9a474cab..32d7cd2e9 100644 --- a/core/translate/index.rs +++ b/core/translate/index.rs @@ -62,13 +62,13 @@ pub fn translate_create_index( unique: unique_if_not_exists.0, }); - // Allocate the necessary cursors. + // Allocate the necessary cursors: // - // 1. sqlite_schema_cursor_id - for the sqlite_schema table - // 2. btree_cursor_id - for the index btree - // 3. table_cursor_id - for the table we are creating the index on - // 4. sorter_cursor_id - for the sorter - // 5. pseudo_cursor_id - for the pseudo table to store the sorted index values + // 1. sqlite_schema_cursor_id - sqlite_schema table + // 2. btree_cursor_id - new index btree + // 3. table_cursor_id - table we are creating the index on + // 4. sorter_cursor_id - sorter + // 5. pseudo_cursor_id - pseudo table to store the sorted index values let sqlite_table = schema.get_btree_table(SQLITE_TABLEID).unwrap(); let sqlite_schema_cursor_id = program.alloc_cursor_id( Some(SQLITE_TABLEID.to_owned()), @@ -292,7 +292,7 @@ fn create_idx_stmt_to_sql( unique_if_not_exists: (bool, bool), cols: &[((usize, &Column), SortOrder)], ) -> String { - let mut sql = String::new(); + let mut sql = String::with_capacity(128); sql.push_str("CREATE "); if unique_if_not_exists.0 { sql.push_str("UNIQUE ");