Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Index insert #665

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
321 changes: 209 additions & 112 deletions core/storage/btree.rs

Large diffs are not rendered by default.

76 changes: 75 additions & 1 deletion core/translate/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,24 @@ pub fn translate_insert(
_ => todo!(),
};

let indexes_to_update = if let Some(indexes) = schema.indexes.get(table_name.0.as_str()) {
indexes
.iter()
.map(|index| {
(
index.clone(),
program.alloc_cursor_id(
Some(index.name.clone()),
CursorType::BTreeIndex(index.clone()),
),
program.alloc_registers(index.columns.len() + 1), // +1 for the rowid
)
})
.collect::<Vec<_>>()
} else {
vec![]
};

let column_mappings = resolve_columns_for_insert(&table, columns, values)?;
// Check if rowid was provided (through INTEGER PRIMARY KEY as a rowid alias)
let rowid_alias_index = table.columns.iter().position(|c| c.is_rowid_alias);
Expand Down Expand Up @@ -140,6 +158,14 @@ pub fn translate_insert(
});
program.emit_insn(Insn::OpenWriteAwait {});

for (index, cursor_id, _) in indexes_to_update.iter() {
program.emit_insn(Insn::OpenWriteAsync {
cursor_id: *cursor_id,
root_page: index.root_page,
});
program.emit_insn(Insn::OpenWriteAwait {});
}

// Main loop
// FIXME: rollback is not implemented. E.g. if you insert 2 rows and one fails to unique constraint violation,
// the other row will still be inserted.
Expand All @@ -156,6 +182,14 @@ pub fn translate_insert(
});
program.emit_insn(Insn::OpenWriteAwait {});

for (index, cursor_id, _) in indexes_to_update.iter() {
program.emit_insn(Insn::OpenWriteAsync {
cursor_id: *cursor_id,
root_page: index.root_page,
});
program.emit_insn(Insn::OpenWriteAwait {});
}

populate_column_registers(
&mut program,
&values[0],
Expand Down Expand Up @@ -228,13 +262,53 @@ pub fn translate_insert(
program.resolve_label(make_record_label, program.offset());
}

// Create and insert the record
// Create the records for the indexes
for (index, cursor_id, index_record_reg) in indexes_to_update.iter() {
let start_reg = program.alloc_registers(index.columns.len() + 1);
for (i, column) in index.columns.iter().enumerate() {
let col_reg = start_reg + i;
let column_index = table
.columns
.iter()
.position(|c| c.name == column.name)
.unwrap();
program.emit_insn(Insn::Copy {
src_reg: column_registers_start + column_index,
dst_reg: col_reg,
amount: 0,
});
}
program.emit_insn(Insn::Copy {
src_reg: rowid_reg,
dst_reg: start_reg + index.columns.len(),
amount: 0,
});
program.emit_insn(Insn::MakeRecord {
start_reg,
count: index.columns.len() + 1, // +1 for the rowid
dest_reg: *index_record_reg,
});
}
// Create the record for the table
program.emit_insn(Insn::MakeRecord {
start_reg: column_registers_start,
count: num_cols,
dest_reg: record_register,
});

// Insert the records for the indexes
for (_, cursor_id, index_record_reg) in indexes_to_update.iter() {
program.emit_insn(Insn::IdxInsertAsync {
cursor_id: *cursor_id,
key_reg: *index_record_reg,
flag: 0,
});
program.emit_insn(Insn::IdxInsertAwait {
cursor_id: *cursor_id,
});
}

// Insert the record for the table
program.emit_insn(Insn::InsertAsync {
cursor: cursor_id,
key_reg: rowid_reg,
Expand Down
11 changes: 7 additions & 4 deletions core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,17 +511,20 @@ pub enum CursorResult<T> {
IO,
}

#[derive(Clone, PartialEq, Debug)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum SeekOp {
EQ,
GE,
GT,
}

#[derive(Clone, PartialEq, Debug)]
pub enum SeekKey<'a> {
/// Key type for the btree cursor.
/// Tables, except WITHOUT ROWID, identify rows by their rowid.
/// In indexes (and WITHOUT ROWID tables) the key is the record.
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
pub enum BTreeKey {
TableRowId(u64),
IndexKey(&'a OwnedRecord),
IndexKey(OwnedRecord),
}

#[cfg(test)]
Expand Down
22 changes: 22 additions & 0 deletions core/vdbe/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,28 @@ pub fn insn_to_str(
0,
"".to_string(),
),
Insn::IdxInsertAsync {
cursor_id,
key_reg,
flag,
} => (
"IdxInsertAsync",
*cursor_id as i32,
*key_reg as i32,
0,
OwnedValue::build_text(Rc::new("".to_string())),
*flag as u16,
"".to_string(),
),
Insn::IdxInsertAwait { cursor_id } => (
"IdxInsertAwait",
*cursor_id as i32,
0,
0,
OwnedValue::build_text(Rc::new("".to_string())),
0,
"".to_string(),
),
Insn::DeleteAsync { cursor_id } => (
"DeleteAsync",
*cursor_id as i32,
Expand Down
10 changes: 10 additions & 0 deletions core/vdbe/insn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,16 @@ pub enum Insn {
cursor_id: usize,
},

IdxInsertAsync {
cursor_id: usize,
key_reg: usize, // In indexes, keys are records and there is no other payload.
flag: usize, // Flags used by insert, for now not used.
},

IdxInsertAwait {
cursor_id: usize,
},

DeleteAsync {
cursor_id: CursorID,
},
Expand Down
Loading