From 6cc1b778b4ddb3cd9131511fea038e0e294279d4 Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Sun, 2 Feb 2025 20:02:59 +0400 Subject: [PATCH 1/3] add test with rowid=-1 - now limbo attempts to add with overflow and panic in this case --- .../functions/test_function_rowid.rs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/integration/functions/test_function_rowid.rs b/tests/integration/functions/test_function_rowid.rs index 54b72c680..9eb5ef133 100644 --- a/tests/integration/functions/test_function_rowid.rs +++ b/tests/integration/functions/test_function_rowid.rs @@ -81,3 +81,25 @@ fn test_last_insert_rowid_basic() -> anyhow::Result<()> { do_flush(&conn, &tmp_db)?; Ok(()) } + +#[test] +fn test_integer_primary_key() -> anyhow::Result<()> { + let _ = env_logger::try_init(); + let tmp_db = TempDatabase::new("CREATE TABLE test_rowid (id INTEGER PRIMARY KEY);"); + let conn = tmp_db.connect_limbo(); + + for query in &[ + "INSERT INTO test_rowid VALUES (-1)", + "INSERT INTO test_rowid VALUES (NULL)", + ] { + let mut insert_query = conn.query(query)?.unwrap(); + loop { + match insert_query.step()? { + StepResult::IO => tmp_db.io.run_once()?, + StepResult::Done => break, + _ => unreachable!(), + } + } + } + Ok(()) +} From e63d84ed506f7682c318450b94926ef4be5ca9af Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Sun, 2 Feb 2025 20:10:38 +0400 Subject: [PATCH 2/3] refine assertions --- .../functions/test_function_rowid.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/integration/functions/test_function_rowid.rs b/tests/integration/functions/test_function_rowid.rs index 9eb5ef133..72045e2ab 100644 --- a/tests/integration/functions/test_function_rowid.rs +++ b/tests/integration/functions/test_function_rowid.rs @@ -101,5 +101,22 @@ fn test_integer_primary_key() -> anyhow::Result<()> { } } } + let mut rowids = Vec::new(); + let mut select_query = conn.query("SELECT * FROM test_rowid")?.unwrap(); + loop { + match select_query.step()? { + StepResult::Row(row) => { + if let Value::Integer(id) = row.values[0] { + rowids.push(id); + } + } + StepResult::IO => tmp_db.io.run_once()?, + StepResult::Interrupt | StepResult::Done => break, + StepResult::Busy => panic!("Database is busy"), + } + } + assert_eq!(rowids.len(), 2); + assert!(rowids[0] > 0); + assert!(rowids[1] == -1); Ok(()) } From 2b9220992d655c8ad955c874832ed3e771667914 Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Sun, 2 Feb 2025 20:10:58 +0400 Subject: [PATCH 3/3] fix attempt to add with overflow crash in case of rowid auto-generation --- core/vdbe/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/vdbe/mod.rs b/core/vdbe/mod.rs index 5636ab0d3..16156347a 100644 --- a/core/vdbe/mod.rs +++ b/core/vdbe/mod.rs @@ -2496,7 +2496,11 @@ fn get_new_rowid(cursor: &mut BTreeCursor, mut rng: R) -> Result {} CursorResult::IO => return Ok(CursorResult::IO), } - let mut rowid = cursor.rowid()?.unwrap_or(0) + 1; + let mut rowid = cursor + .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 + .unwrap_or(u64::MAX); // in case of overflow - use u64::MAX if rowid > i64::MAX.try_into().unwrap() { let distribution = Uniform::from(1..=i64::MAX); let max_attempts = 100;