mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-18 09:04:19 +01:00
Convert u64 rowid to i64
Rowids can be negative, therefore let's swap to i64
This commit is contained in:
@@ -331,7 +331,7 @@ pub struct Connection {
|
|||||||
auto_commit: Cell<bool>,
|
auto_commit: Cell<bool>,
|
||||||
mv_transactions: RefCell<Vec<crate::mvcc::database::TxID>>,
|
mv_transactions: RefCell<Vec<crate::mvcc::database::TxID>>,
|
||||||
transaction_state: Cell<TransactionState>,
|
transaction_state: Cell<TransactionState>,
|
||||||
last_insert_rowid: Cell<u64>,
|
last_insert_rowid: Cell<i64>,
|
||||||
last_change: Cell<i64>,
|
last_change: Cell<i64>,
|
||||||
total_changes: Cell<i64>,
|
total_changes: Cell<i64>,
|
||||||
syms: RefCell<SymbolTable>,
|
syms: RefCell<SymbolTable>,
|
||||||
@@ -550,11 +550,11 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_insert_rowid(&self) -> u64 {
|
pub fn last_insert_rowid(&self) -> i64 {
|
||||||
self.last_insert_rowid.get()
|
self.last_insert_rowid.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_last_rowid(&self, rowid: u64) {
|
fn update_last_rowid(&self, rowid: i64) {
|
||||||
self.last_insert_rowid.set(rowid);
|
self.last_insert_rowid.set(rowid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ mod tests;
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct RowID {
|
pub struct RowID {
|
||||||
pub table_id: u64,
|
pub table_id: u64,
|
||||||
pub row_id: u64,
|
pub row_id: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RowID {
|
impl RowID {
|
||||||
pub fn new(table_id: u64, row_id: u64) -> Self {
|
pub fn new(table_id: u64, row_id: i64) -> Self {
|
||||||
Self { table_id, row_id }
|
Self { table_id, row_id }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,7 +415,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
|
|||||||
row_id: 0,
|
row_id: 0,
|
||||||
}..RowID {
|
}..RowID {
|
||||||
table_id,
|
table_id,
|
||||||
row_id: u64::MAX,
|
row_id: i64::MAX,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.map(|entry| *entry.key())
|
.map(|entry| *entry.key())
|
||||||
@@ -425,7 +425,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
|
|||||||
pub fn get_row_id_range(
|
pub fn get_row_id_range(
|
||||||
&self,
|
&self,
|
||||||
table_id: u64,
|
table_id: u64,
|
||||||
start: u64,
|
start: i64,
|
||||||
bucket: &mut Vec<RowID>,
|
bucket: &mut Vec<RowID>,
|
||||||
max_items: u64,
|
max_items: u64,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@@ -441,7 +441,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
|
|||||||
|
|
||||||
let end_id = RowID {
|
let end_id = RowID {
|
||||||
table_id,
|
table_id,
|
||||||
row_id: u64::MAX,
|
row_id: i64::MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.rows
|
self.rows
|
||||||
@@ -452,7 +452,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_next_row_id_for_table(&self, table_id: u64, start: u64) -> Option<RowID> {
|
pub fn get_next_row_id_for_table(&self, table_id: u64, start: i64) -> Option<RowID> {
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
"getting_next_id_for_table(table_id={}, range_start={})",
|
"getting_next_id_for_table(table_id={}, range_start={})",
|
||||||
table_id,
|
table_id,
|
||||||
@@ -465,7 +465,7 @@ impl<Clock: LogicalClock> MvStore<Clock> {
|
|||||||
|
|
||||||
let max_bound = RowID {
|
let max_bound = RowID {
|
||||||
table_id,
|
table_id,
|
||||||
row_id: u64::MAX,
|
row_id: i64::MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.rows
|
self.rows
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ pub use database::MvStore;
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::mvcc::clock::LocalClock;
|
use crate::mvcc::clock::LocalClock;
|
||||||
use crate::mvcc::database::{MvStore, Row, RowID};
|
use crate::mvcc::database::{MvStore, Row, RowID};
|
||||||
use std::sync::atomic::AtomicU64;
|
use std::sync::atomic::AtomicI64;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
static IDS: AtomicU64 = AtomicU64::new(1);
|
static IDS: AtomicI64 = AtomicI64::new(1);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_non_overlapping_concurrent_inserts() {
|
fn test_non_overlapping_concurrent_inserts() {
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ struct DestroyInfo {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum DeleteSavepoint {
|
enum DeleteSavepoint {
|
||||||
Rowid(u64),
|
Rowid(i64),
|
||||||
Payload(ImmutableRecord),
|
Payload(ImmutableRecord),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,14 +230,14 @@ enum PayloadOverflowWithOffset {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum BTreeKey<'a> {
|
pub enum BTreeKey<'a> {
|
||||||
TableRowId((u64, Option<&'a ImmutableRecord>)),
|
TableRowId((i64, Option<&'a ImmutableRecord>)),
|
||||||
IndexKey(&'a ImmutableRecord),
|
IndexKey(&'a ImmutableRecord),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BTreeKey<'_> {
|
impl BTreeKey<'_> {
|
||||||
/// Create a new table rowid key from a rowid and an optional immutable record.
|
/// Create a new table rowid key from a rowid and an optional immutable record.
|
||||||
/// The record is optional because it may not be available when the key is created.
|
/// The record is optional because it may not be available when the key is created.
|
||||||
pub fn new_table_rowid(rowid: u64, record: Option<&ImmutableRecord>) -> BTreeKey<'_> {
|
pub fn new_table_rowid(rowid: i64, record: Option<&ImmutableRecord>) -> BTreeKey<'_> {
|
||||||
BTreeKey::TableRowId((rowid, record))
|
BTreeKey::TableRowId((rowid, record))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ impl BTreeKey<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the rowid, if present. Index will never be present.
|
/// Get the rowid, if present. Index will never be present.
|
||||||
fn maybe_rowid(&self) -> Option<u64> {
|
fn maybe_rowid(&self) -> Option<i64> {
|
||||||
match self {
|
match self {
|
||||||
BTreeKey::TableRowId((rowid, _)) => Some(*rowid),
|
BTreeKey::TableRowId((rowid, _)) => Some(*rowid),
|
||||||
BTreeKey::IndexKey(_) => None,
|
BTreeKey::IndexKey(_) => None,
|
||||||
@@ -263,7 +263,7 @@ impl BTreeKey<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Assert that the key is an integer rowid and return it.
|
/// Assert that the key is an integer rowid and return it.
|
||||||
fn to_rowid(&self) -> u64 {
|
fn to_rowid(&self) -> i64 {
|
||||||
match self {
|
match self {
|
||||||
BTreeKey::TableRowId((rowid, _)) => *rowid,
|
BTreeKey::TableRowId((rowid, _)) => *rowid,
|
||||||
BTreeKey::IndexKey(_) => panic!("BTreeKey::to_rowid called on IndexKey"),
|
BTreeKey::IndexKey(_) => panic!("BTreeKey::to_rowid called on IndexKey"),
|
||||||
@@ -313,7 +313,7 @@ impl WriteInfo {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
enum CursorHasRecord {
|
enum CursorHasRecord {
|
||||||
Yes {
|
Yes {
|
||||||
rowid: Option<u64>, // not all indexes and btrees have rowids, so this is optional.
|
rowid: Option<i64>, // not all indexes and btrees have rowids, so this is optional.
|
||||||
},
|
},
|
||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ enum OverflowState {
|
|||||||
/// Holds a Record or RowId, so that these can be transformed into a SeekKey to restore
|
/// Holds a Record or RowId, so that these can be transformed into a SeekKey to restore
|
||||||
/// cursor position to its previous location.
|
/// cursor position to its previous location.
|
||||||
enum CursorContext {
|
enum CursorContext {
|
||||||
TableRowId(u64),
|
TableRowId(i64),
|
||||||
|
|
||||||
/// If we are in an index tree we can then reuse this field to save
|
/// If we are in an index tree we can then reuse this field to save
|
||||||
/// our cursor information
|
/// our cursor information
|
||||||
@@ -496,12 +496,12 @@ impl BTreeCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_index_rowid_from_record(&self) -> Option<u64> {
|
pub fn get_index_rowid_from_record(&self) -> Option<i64> {
|
||||||
if !self.has_rowid() {
|
if !self.has_rowid() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let rowid = match self.get_immutable_record().as_ref().unwrap().last_value() {
|
let rowid = match self.get_immutable_record().as_ref().unwrap().last_value() {
|
||||||
Some(RefValue::Integer(rowid)) => *rowid as u64,
|
Some(RefValue::Integer(rowid)) => *rowid as i64,
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
"index where has_rowid() is true should have an integer rowid as the last value"
|
"index where has_rowid() is true should have an integer rowid as the last value"
|
||||||
),
|
),
|
||||||
@@ -1450,7 +1450,7 @@ impl BTreeCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Specialized version of move_to() for table btrees.
|
/// Specialized version of move_to() for table btrees.
|
||||||
fn tablebtree_move_to(&mut self, rowid: u64, seek_op: SeekOp) -> Result<CursorResult<()>> {
|
fn tablebtree_move_to(&mut self, rowid: i64, seek_op: SeekOp) -> Result<CursorResult<()>> {
|
||||||
let iter_dir = seek_op.iteration_direction();
|
let iter_dir = seek_op.iteration_direction();
|
||||||
'outer: loop {
|
'outer: loop {
|
||||||
let page = self.stack.top();
|
let page = self.stack.top();
|
||||||
@@ -1706,7 +1706,7 @@ impl BTreeCursor {
|
|||||||
/// of iterating cells in order.
|
/// of iterating cells in order.
|
||||||
fn tablebtree_seek(
|
fn tablebtree_seek(
|
||||||
&mut self,
|
&mut self,
|
||||||
rowid: u64,
|
rowid: i64,
|
||||||
seek_op: SeekOp,
|
seek_op: SeekOp,
|
||||||
) -> Result<CursorResult<CursorHasRecord>> {
|
) -> Result<CursorResult<CursorHasRecord>> {
|
||||||
assert!(self.mv_cursor.is_none());
|
assert!(self.mv_cursor.is_none());
|
||||||
@@ -2969,7 +2969,7 @@ impl BTreeCursor {
|
|||||||
let (rowid, _) = read_varint(÷r_cell[n_bytes_payload..])?;
|
let (rowid, _) = read_varint(÷r_cell[n_bytes_payload..])?;
|
||||||
new_divider_cell
|
new_divider_cell
|
||||||
.extend_from_slice(&(page.get().get().id as u32).to_be_bytes());
|
.extend_from_slice(&(page.get().get().id as u32).to_be_bytes());
|
||||||
write_varint_to_vec(rowid, &mut new_divider_cell);
|
write_varint_to_vec(rowid as u64, &mut new_divider_cell);
|
||||||
} else {
|
} else {
|
||||||
// Leaf index
|
// Leaf index
|
||||||
new_divider_cell
|
new_divider_cell
|
||||||
@@ -3937,7 +3937,7 @@ impl BTreeCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rowid(&self) -> Result<Option<u64>> {
|
pub fn rowid(&self) -> Result<Option<i64>> {
|
||||||
if let Some(mv_cursor) = &self.mv_cursor {
|
if let Some(mv_cursor) = &self.mv_cursor {
|
||||||
let mv_cursor = mv_cursor.borrow();
|
let mv_cursor = mv_cursor.borrow();
|
||||||
return Ok(mv_cursor.current_row_id().map(|rowid| rowid.row_id));
|
return Ok(mv_cursor.current_row_id().map(|rowid| rowid.row_id));
|
||||||
@@ -4194,7 +4194,7 @@ impl BTreeCursor {
|
|||||||
match predecessor_cell {
|
match predecessor_cell {
|
||||||
BTreeCell::TableLeafCell(leaf_cell) => {
|
BTreeCell::TableLeafCell(leaf_cell) => {
|
||||||
cell_payload.extend_from_slice(&child_pointer.to_be_bytes());
|
cell_payload.extend_from_slice(&child_pointer.to_be_bytes());
|
||||||
write_varint_to_vec(leaf_cell._rowid, &mut cell_payload);
|
write_varint_to_vec(leaf_cell._rowid as u64, &mut cell_payload);
|
||||||
}
|
}
|
||||||
BTreeCell::IndexLeafCell(leaf_cell) => {
|
BTreeCell::IndexLeafCell(leaf_cell) => {
|
||||||
cell_payload.extend_from_slice(&child_pointer.to_be_bytes());
|
cell_payload.extend_from_slice(&child_pointer.to_be_bytes());
|
||||||
@@ -4356,7 +4356,7 @@ impl BTreeCursor {
|
|||||||
Value::Integer(i) => i,
|
Value::Integer(i) => i,
|
||||||
_ => unreachable!("btree tables are indexed by integers!"),
|
_ => unreachable!("btree tables are indexed by integers!"),
|
||||||
};
|
};
|
||||||
let _ = return_if_io!(self.move_to(SeekKey::TableRowId(*int_key as u64), SeekOp::EQ));
|
let _ = return_if_io!(self.move_to(SeekKey::TableRowId(*int_key), SeekOp::EQ));
|
||||||
let page = self.stack.top();
|
let page = self.stack.top();
|
||||||
// TODO(pere): request load
|
// TODO(pere): request load
|
||||||
return_if_locked!(page.get());
|
return_if_locked!(page.get());
|
||||||
@@ -4366,7 +4366,7 @@ impl BTreeCursor {
|
|||||||
|
|
||||||
// find cell
|
// find cell
|
||||||
let int_key = match key {
|
let int_key = match key {
|
||||||
Value::Integer(i) => *i as u64,
|
Value::Integer(i) => *i,
|
||||||
_ => unreachable!("btree tables are indexed by integers!"),
|
_ => unreachable!("btree tables are indexed by integers!"),
|
||||||
};
|
};
|
||||||
let cell_idx = self.find_cell(contents, &BTreeKey::new_table_rowid(int_key, None));
|
let cell_idx = self.find_cell(contents, &BTreeKey::new_table_rowid(int_key, None));
|
||||||
@@ -5780,7 +5780,7 @@ fn allocate_cell_space(page_ref: &PageContent, amount: u16, usable_space: u16) -
|
|||||||
/// If the record is too large to fit in the cell, it will spill onto overflow pages.
|
/// If the record is too large to fit in the cell, it will spill onto overflow pages.
|
||||||
fn fill_cell_payload(
|
fn fill_cell_payload(
|
||||||
page_type: PageType,
|
page_type: PageType,
|
||||||
int_key: Option<u64>,
|
int_key: Option<i64>,
|
||||||
cell_payload: &mut Vec<u8>,
|
cell_payload: &mut Vec<u8>,
|
||||||
record: &ImmutableRecord,
|
record: &ImmutableRecord,
|
||||||
usable_space: u16,
|
usable_space: u16,
|
||||||
@@ -5797,7 +5797,7 @@ fn fill_cell_payload(
|
|||||||
if matches!(page_type, PageType::TableLeaf) {
|
if matches!(page_type, PageType::TableLeaf) {
|
||||||
let int_key = int_key.unwrap();
|
let int_key = int_key.unwrap();
|
||||||
write_varint_to_vec(record_buf.len() as u64, cell_payload);
|
write_varint_to_vec(record_buf.len() as u64, cell_payload);
|
||||||
write_varint_to_vec(int_key, cell_payload);
|
write_varint_to_vec(int_key as u64, cell_payload);
|
||||||
} else {
|
} else {
|
||||||
write_varint_to_vec(record_buf.len() as u64, cell_payload);
|
write_varint_to_vec(record_buf.len() as u64, cell_payload);
|
||||||
}
|
}
|
||||||
@@ -6043,7 +6043,7 @@ mod tests {
|
|||||||
let mut payload: Vec<u8> = Vec::new();
|
let mut payload: Vec<u8> = Vec::new();
|
||||||
fill_cell_payload(
|
fill_cell_payload(
|
||||||
page.page_type(),
|
page.page_type(),
|
||||||
Some(id as u64),
|
Some(id as i64),
|
||||||
&mut payload,
|
&mut payload,
|
||||||
&record,
|
&record,
|
||||||
4096,
|
4096,
|
||||||
@@ -6467,7 +6467,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| {
|
|| {
|
||||||
let key = SeekKey::TableRowId(key as u64);
|
let key = SeekKey::TableRowId(key);
|
||||||
cursor.move_to(key, SeekOp::EQ)
|
cursor.move_to(key, SeekOp::EQ)
|
||||||
},
|
},
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
@@ -6481,7 +6481,7 @@ mod tests {
|
|||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| cursor.insert(&BTreeKey::new_table_rowid(key as u64, Some(&value)), true),
|
|| cursor.insert(&BTreeKey::new_table_rowid(key, Some(&value)), true),
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -6503,7 +6503,7 @@ mod tests {
|
|||||||
tracing::trace!("seeking key: {}", key);
|
tracing::trace!("seeking key: {}", key);
|
||||||
run_until_done(|| cursor.next(), pager.deref()).unwrap();
|
run_until_done(|| cursor.next(), pager.deref()).unwrap();
|
||||||
let cursor_rowid = cursor.rowid().unwrap().unwrap();
|
let cursor_rowid = cursor.rowid().unwrap().unwrap();
|
||||||
if *key as u64 != cursor_rowid {
|
if *key != cursor_rowid {
|
||||||
valid = false;
|
valid = false;
|
||||||
println!("key {} is not found, got {}", key, cursor_rowid);
|
println!("key {} is not found, got {}", key, cursor_rowid);
|
||||||
break;
|
break;
|
||||||
@@ -6535,7 +6535,7 @@ mod tests {
|
|||||||
run_until_done(|| cursor.next(), pager.deref()).unwrap();
|
run_until_done(|| cursor.next(), pager.deref()).unwrap();
|
||||||
let cursor_rowid = cursor.rowid().unwrap().unwrap();
|
let cursor_rowid = cursor.rowid().unwrap().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*key as u64, cursor_rowid,
|
*key, cursor_rowid,
|
||||||
"key {} is not found, got {}",
|
"key {} is not found, got {}",
|
||||||
key, cursor_rowid
|
key, cursor_rowid
|
||||||
);
|
);
|
||||||
@@ -7152,7 +7152,7 @@ mod tests {
|
|||||||
let mut payload: Vec<u8> = Vec::new();
|
let mut payload: Vec<u8> = Vec::new();
|
||||||
fill_cell_payload(
|
fill_cell_payload(
|
||||||
page.page_type(),
|
page.page_type(),
|
||||||
Some(i as u64),
|
Some(i as i64),
|
||||||
&mut payload,
|
&mut payload,
|
||||||
&record,
|
&record,
|
||||||
4096,
|
4096,
|
||||||
@@ -7231,7 +7231,7 @@ mod tests {
|
|||||||
let mut payload: Vec<u8> = Vec::new();
|
let mut payload: Vec<u8> = Vec::new();
|
||||||
fill_cell_payload(
|
fill_cell_payload(
|
||||||
page.page_type(),
|
page.page_type(),
|
||||||
Some(i as u64),
|
Some(i),
|
||||||
&mut payload,
|
&mut payload,
|
||||||
&record,
|
&record,
|
||||||
4096,
|
4096,
|
||||||
@@ -7244,7 +7244,10 @@ mod tests {
|
|||||||
insert_into_cell(page, &payload, cell_idx, 4096).unwrap();
|
insert_into_cell(page, &payload, cell_idx, 4096).unwrap();
|
||||||
assert!(page.overflow_cells.is_empty());
|
assert!(page.overflow_cells.is_empty());
|
||||||
total_size += payload.len() as u16 + 2;
|
total_size += payload.len() as u16 + 2;
|
||||||
cells.push(Cell { pos: i, payload });
|
cells.push(Cell {
|
||||||
|
pos: i as usize,
|
||||||
|
payload,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
if page.cell_count() == 0 {
|
if page.cell_count() == 0 {
|
||||||
@@ -7630,14 +7633,14 @@ mod tests {
|
|||||||
tracing::trace!("before insert {}", i);
|
tracing::trace!("before insert {}", i);
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| {
|
|| {
|
||||||
let key = SeekKey::TableRowId(i as u64);
|
let key = SeekKey::TableRowId(i);
|
||||||
cursor.move_to(key, SeekOp::EQ)
|
cursor.move_to(key, SeekOp::EQ)
|
||||||
},
|
},
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| cursor.insert(&BTreeKey::new_table_rowid(i as u64, Some(&value)), true),
|
|| cursor.insert(&BTreeKey::new_table_rowid(i, Some(&value)), true),
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -7707,7 +7710,7 @@ mod tests {
|
|||||||
|
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| {
|
|| {
|
||||||
let key = SeekKey::TableRowId(i as u64);
|
let key = SeekKey::TableRowId(i);
|
||||||
cursor.move_to(key, SeekOp::EQ)
|
cursor.move_to(key, SeekOp::EQ)
|
||||||
},
|
},
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
@@ -7715,7 +7718,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| cursor.insert(&BTreeKey::new_table_rowid(i as u64, Some(&value)), true),
|
|| cursor.insert(&BTreeKey::new_table_rowid(i, Some(&value)), true),
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -7729,7 +7732,7 @@ mod tests {
|
|||||||
// Delete records with 500 <= key <= 3500
|
// Delete records with 500 <= key <= 3500
|
||||||
for i in 500..=3500 {
|
for i in 500..=3500 {
|
||||||
let mut cursor = BTreeCursor::new_table(None, pager.clone(), root_page);
|
let mut cursor = BTreeCursor::new_table(None, pager.clone(), root_page);
|
||||||
let seek_key = SeekKey::TableRowId(i as u64);
|
let seek_key = SeekKey::TableRowId(i);
|
||||||
|
|
||||||
let found = run_until_done(|| cursor.seek(seek_key.clone(), SeekOp::EQ), pager.deref())
|
let found = run_until_done(|| cursor.seek(seek_key.clone(), SeekOp::EQ), pager.deref())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -7788,14 +7791,14 @@ mod tests {
|
|||||||
);
|
);
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| {
|
|| {
|
||||||
let key = SeekKey::TableRowId(i as u64);
|
let key = SeekKey::TableRowId(i as i64);
|
||||||
cursor.move_to(key, SeekOp::EQ)
|
cursor.move_to(key, SeekOp::EQ)
|
||||||
},
|
},
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
run_until_done(
|
run_until_done(
|
||||||
|| cursor.insert(&BTreeKey::new_table_rowid(i as u64, Some(&value)), true),
|
|| cursor.insert(&BTreeKey::new_table_rowid(i as i64, Some(&value)), true),
|
||||||
pager.deref(),
|
pager.deref(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -7812,7 +7815,7 @@ mod tests {
|
|||||||
else {
|
else {
|
||||||
panic!("expected Some(rowid) but got {:?}", cursor.has_record.get());
|
panic!("expected Some(rowid) but got {:?}", cursor.has_record.get());
|
||||||
};
|
};
|
||||||
assert_eq!(rowid, i as u64, "got!=expected");
|
assert_eq!(rowid, i as i64, "got!=expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8096,7 +8099,7 @@ mod tests {
|
|||||||
]))]);
|
]))]);
|
||||||
fill_cell_payload(
|
fill_cell_payload(
|
||||||
page_type,
|
page_type,
|
||||||
Some(i),
|
Some(i as i64),
|
||||||
&mut payload,
|
&mut payload,
|
||||||
&record,
|
&record,
|
||||||
pager.usable_space() as u16,
|
pager.usable_space() as u16,
|
||||||
|
|||||||
@@ -642,7 +642,7 @@ impl PageContent {
|
|||||||
|
|
||||||
/// Read the rowid of a table interior cell.
|
/// Read the rowid of a table interior cell.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn cell_table_interior_read_rowid(&self, idx: usize) -> Result<u64> {
|
pub fn cell_table_interior_read_rowid(&self, idx: usize) -> Result<i64> {
|
||||||
debug_assert!(self.page_type() == PageType::TableInterior);
|
debug_assert!(self.page_type() == PageType::TableInterior);
|
||||||
let buf = self.as_ptr();
|
let buf = self.as_ptr();
|
||||||
const INTERIOR_PAGE_HEADER_SIZE_BYTES: usize = 12;
|
const INTERIOR_PAGE_HEADER_SIZE_BYTES: usize = 12;
|
||||||
@@ -651,7 +651,7 @@ impl PageContent {
|
|||||||
let cell_pointer = self.read_u16(cell_pointer) as usize;
|
let cell_pointer = self.read_u16(cell_pointer) as usize;
|
||||||
const LEFT_CHILD_PAGE_SIZE_BYTES: usize = 4;
|
const LEFT_CHILD_PAGE_SIZE_BYTES: usize = 4;
|
||||||
let (rowid, _) = read_varint(&buf[cell_pointer + LEFT_CHILD_PAGE_SIZE_BYTES..])?;
|
let (rowid, _) = read_varint(&buf[cell_pointer + LEFT_CHILD_PAGE_SIZE_BYTES..])?;
|
||||||
Ok(rowid)
|
Ok(rowid as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the left child page of a table interior cell.
|
/// Read the left child page of a table interior cell.
|
||||||
@@ -673,7 +673,7 @@ impl PageContent {
|
|||||||
|
|
||||||
/// Read the rowid of a table leaf cell.
|
/// Read the rowid of a table leaf cell.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn cell_table_leaf_read_rowid(&self, idx: usize) -> Result<u64> {
|
pub fn cell_table_leaf_read_rowid(&self, idx: usize) -> Result<i64> {
|
||||||
debug_assert!(self.page_type() == PageType::TableLeaf);
|
debug_assert!(self.page_type() == PageType::TableLeaf);
|
||||||
let buf = self.as_ptr();
|
let buf = self.as_ptr();
|
||||||
const LEAF_PAGE_HEADER_SIZE_BYTES: usize = 8;
|
const LEAF_PAGE_HEADER_SIZE_BYTES: usize = 8;
|
||||||
@@ -684,7 +684,7 @@ impl PageContent {
|
|||||||
let (_, nr) = read_varint(&buf[pos..])?;
|
let (_, nr) = read_varint(&buf[pos..])?;
|
||||||
pos += nr;
|
pos += nr;
|
||||||
let (rowid, _) = read_varint(&buf[pos..])?;
|
let (rowid, _) = read_varint(&buf[pos..])?;
|
||||||
Ok(rowid)
|
Ok(rowid as i64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The cell pointer array of a b-tree page immediately follows the b-tree page header.
|
/// The cell pointer array of a b-tree page immediately follows the b-tree page header.
|
||||||
@@ -911,12 +911,12 @@ pub enum BTreeCell {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableInteriorCell {
|
pub struct TableInteriorCell {
|
||||||
pub _left_child_page: u32,
|
pub _left_child_page: u32,
|
||||||
pub _rowid: u64,
|
pub _rowid: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableLeafCell {
|
pub struct TableLeafCell {
|
||||||
pub _rowid: u64,
|
pub _rowid: i64,
|
||||||
/// Payload of cell, if it overflows it won't include overflowed payload.
|
/// Payload of cell, if it overflows it won't include overflowed payload.
|
||||||
pub _payload: &'static [u8],
|
pub _payload: &'static [u8],
|
||||||
/// This is the complete payload size including overflow pages.
|
/// This is the complete payload size including overflow pages.
|
||||||
@@ -981,7 +981,7 @@ pub fn read_btree_cell(
|
|||||||
let (rowid, _) = read_varint(&page[pos..])?;
|
let (rowid, _) = read_varint(&page[pos..])?;
|
||||||
Ok(BTreeCell::TableInteriorCell(TableInteriorCell {
|
Ok(BTreeCell::TableInteriorCell(TableInteriorCell {
|
||||||
_left_child_page: left_child_page,
|
_left_child_page: left_child_page,
|
||||||
_rowid: rowid,
|
_rowid: rowid as i64,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
PageType::IndexLeaf => {
|
PageType::IndexLeaf => {
|
||||||
@@ -1015,7 +1015,7 @@ pub fn read_btree_cell(
|
|||||||
let (payload, first_overflow_page) =
|
let (payload, first_overflow_page) =
|
||||||
read_payload(&page[pos..pos + to_read], payload_size as usize);
|
read_payload(&page[pos..pos + to_read], payload_size as usize);
|
||||||
Ok(BTreeCell::TableLeafCell(TableLeafCell {
|
Ok(BTreeCell::TableLeafCell(TableLeafCell {
|
||||||
_rowid: rowid,
|
_rowid: rowid as i64,
|
||||||
_payload: payload,
|
_payload: payload,
|
||||||
first_overflow_page,
|
first_overflow_page,
|
||||||
payload_size,
|
payload_size,
|
||||||
|
|||||||
@@ -1486,7 +1486,7 @@ impl SeekOp {
|
|||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum SeekKey<'a> {
|
pub enum SeekKey<'a> {
|
||||||
TableRowId(u64),
|
TableRowId(i64),
|
||||||
IndexKey(&'a ImmutableRecord),
|
IndexKey(&'a ImmutableRecord),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1189,7 +1189,7 @@ pub fn op_vupdate(
|
|||||||
if *conflict_action == 5 {
|
if *conflict_action == 5 {
|
||||||
// ResolveType::Replace
|
// ResolveType::Replace
|
||||||
if let Some(conn) = program.connection.upgrade() {
|
if let Some(conn) = program.connection.upgrade() {
|
||||||
conn.update_last_rowid(new_rowid as u64);
|
conn.update_last_rowid(new_rowid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.pc += 1;
|
state.pc += 1;
|
||||||
@@ -1934,7 +1934,7 @@ pub fn op_row_id(
|
|||||||
let record = record.as_ref().unwrap();
|
let record = record.as_ref().unwrap();
|
||||||
let rowid = record.get_values().last().unwrap();
|
let rowid = record.get_values().last().unwrap();
|
||||||
match rowid {
|
match rowid {
|
||||||
RefValue::Integer(rowid) => *rowid as u64,
|
RefValue::Integer(rowid) => *rowid,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -2019,7 +2019,7 @@ pub fn op_seek_rowid(
|
|||||||
let mut cursor = state.get_cursor(*cursor_id);
|
let mut cursor = state.get_cursor(*cursor_id);
|
||||||
let cursor = cursor.as_btree_mut();
|
let cursor = cursor.as_btree_mut();
|
||||||
let rowid = match state.registers[*src_reg].get_owned_value() {
|
let rowid = match state.registers[*src_reg].get_owned_value() {
|
||||||
Value::Integer(rowid) => Some(*rowid as u64),
|
Value::Integer(rowid) => Some(*rowid),
|
||||||
Value::Null => None,
|
Value::Null => None,
|
||||||
other => {
|
other => {
|
||||||
return Err(LimboError::InternalError(format!(
|
return Err(LimboError::InternalError(format!(
|
||||||
@@ -2143,7 +2143,7 @@ pub fn op_seek(
|
|||||||
return_if_io!(cursor.rewind());
|
return_if_io!(cursor.rewind());
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Value::Integer(rowid) => Some(*rowid as u64),
|
Value::Integer(rowid) => Some(*rowid),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(LimboError::InternalError(format!(
|
return Err(LimboError::InternalError(format!(
|
||||||
"{}: the value in the register is not an integer",
|
"{}: the value in the register is not an integer",
|
||||||
@@ -3865,7 +3865,7 @@ pub fn op_insert(
|
|||||||
// NOTE(pere): Sending moved_before == true is okay because we moved before but
|
// NOTE(pere): Sending moved_before == true is okay because we moved before but
|
||||||
// if we were to set to false after starting a balance procedure, it might
|
// if we were to set to false after starting a balance procedure, it might
|
||||||
// leave undefined state.
|
// leave undefined state.
|
||||||
return_if_io!(cursor.insert(&BTreeKey::new_table_rowid(key as u64, Some(record)), true));
|
return_if_io!(cursor.insert(&BTreeKey::new_table_rowid(key, Some(record)), true));
|
||||||
// Only update last_insert_rowid for regular table inserts, not schema modifications
|
// Only update last_insert_rowid for regular table inserts, not schema modifications
|
||||||
if cursor.root_page() != 1 {
|
if cursor.root_page() != 1 {
|
||||||
if let Some(rowid) = cursor.rowid()? {
|
if let Some(rowid) = cursor.rowid()? {
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ fn get_new_rowid<R: Rng>(cursor: &mut BTreeCursor, mut rng: R) -> Result<CursorR
|
|||||||
.rowid()?
|
.rowid()?
|
||||||
.unwrap_or(0) // if BTree is empty - use 0 as initial value for rowid
|
.unwrap_or(0) // if BTree is empty - use 0 as initial value for rowid
|
||||||
.checked_add(1) // add 1 but be careful with overflows
|
.checked_add(1) // add 1 but be careful with overflows
|
||||||
.unwrap_or(u64::MAX); // in case of overflow - use u64::MAX
|
.unwrap_or(i64::MAX); // in case of overflow - use u64::MAX
|
||||||
if rowid > i64::MAX.try_into().unwrap() {
|
if rowid > i64::MAX.try_into().unwrap() {
|
||||||
let distribution = Uniform::from(1..=i64::MAX);
|
let distribution = Uniform::from(1..=i64::MAX);
|
||||||
let max_attempts = 100;
|
let max_attempts = 100;
|
||||||
|
|||||||
@@ -306,3 +306,11 @@ do_execsql_test_on_specific_db {:memory:} insert_from_select_union {
|
|||||||
SELECT * FROM t;
|
SELECT * FROM t;
|
||||||
} {1|100
|
} {1|100
|
||||||
2|200}
|
2|200}
|
||||||
|
|
||||||
|
do_execsql_test_on_specific_db {:memory:} negative-primary-integer-key {
|
||||||
|
CREATE TABLE t(a INTEGER PRIMARY KEY);
|
||||||
|
insert into t values (-2),(13);
|
||||||
|
select * from t order by a asc;
|
||||||
|
} {-2
|
||||||
|
13}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ fn test_integer_primary_key() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(rowids.len(), 2);
|
assert_eq!(rowids.len(), 2);
|
||||||
assert!(rowids[0] > 0);
|
assert!(rowids[0] == -1);
|
||||||
assert!(rowids[1] == -1);
|
assert!(rowids[1] == 0);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user