Commit Graph

592 Commits

Author SHA1 Message Date
Jussi Saurio
2087393d22 Merge 'Write database header via normal pager route' from meteorgan
Closes: #1613

Closes #1634
2025-06-04 09:39:14 +03:00
Jussi Saurio
ad8c9a4c15 Merge 'Fix WAL frame checksum mismatch' from Diego Reis
Closes #1622
I did an A/B test between SQLite and Limbo and they can restart the db
from each other, indicating that there isn't something very wrong with
our file format. Turns out it was with our reset logic without
truncating the file. I assumed it's safe to don't reset if we're in
`PASSIVE` mode, given the
[docs](https://www.sqlite.org/c3ref/wal_checkpoint_v2.html) and [source
code](https://github.com/sqlite/sqlite/blob/2bd9f69d40dd240c4122c6d02f1f
f447e7b5c098/src/wal.c#L2193).
It also does some small clean ups and fixes.

Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #1647
2025-06-04 09:14:45 +03:00
Diego Reis
09f978b239 core: Tagging some comments as TODO 2025-06-03 15:09:16 -03:00
meteorgan
1554c54f2b restore comments 2025-06-03 22:06:08 +08:00
meteorgan
f2bf6251cd write database header via normal pager route 2025-06-03 22:06:08 +08:00
Diego Reis
cf038b045d core/wal: Only reset the WAL if the file is truncated 2025-06-02 23:16:30 -03:00
Diego Reis
16c81f471b core/ondisk: Stop reading WAL file if a frame mismatch salt value with header
The salts values in the WAL header are (re)generated in every checkpoint (but in PASSIVE mode), so if we find a frame with mismatch it means it's a leftover from a previous checkpoint.
2025-06-02 23:14:51 -03:00
Diego Reis
ec4eb52734 core/wal: Refactor open_shared for readability 2025-06-02 19:21:13 -03:00
pedrocarlo
9b5f5f6053 do not move_to if we are already inserting in correct place 2025-06-02 02:55:32 -03:00
pedrocarlo
c2942a5819 small fixes 2025-06-01 12:11:03 -03:00
pedrocarlo
39434fd20f return_io when restoring context 2025-06-01 03:07:16 -03:00
pedrocarlo
2ddbb7eeed adjust move_to and seek functions to make them truly reentrant + adding return_if_locked_maybe_load in some places so that we read loaded pages 2025-06-01 01:01:35 -03:00
pedrocarlo
d688cfd547 make find_cell and process_overflow_page reentrant 2025-05-31 23:31:59 -03:00
pedrocarlo
dae58be071 make move_to reentrant 2025-05-31 02:56:30 -03:00
pedrocarlo
33480540f1 make cursor seek reentrant 2025-05-30 13:25:46 -03:00
Pere Diaz Bou
da4190a23e Convert u64 rowid to i64
Rowids can be negative, therefore let's swap to i64
2025-05-30 13:07:31 +02:00
Pere Diaz Bou
dd15b7df7f remove dumb comment from pagecachekey 2025-05-29 14:12:16 +02:00
Pere Diaz Bou
93161e9fce remove lru size > 0 check on page cache fuzz 2025-05-29 14:12:16 +02:00
Pere Diaz Bou
37e834b092 remove unnecessary test 2025-05-29 14:12:16 +02:00
Pere Diaz Bou
44007075d9 remove frame_id from PageCacheKey
After reading sqlite a bit, it isn't needed because we have RWlock for
each table in the database file.
2025-05-29 14:12:16 +02:00
Jussi Saurio
85316d8419 Merge 'clear page cache on transaction failure' from Pere Diaz Bou
This is the first step towards rollback, since we still don't spill
pages with WAL, we can simply invalidate page cache in case of failure.

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #1599
2025-05-28 23:14:44 +03:00
Pere Diaz Bou
28bd24b7d4 clear page cache on transaction failure
This is the first step towards rollback, since we still don't spill
pages with WAL, we can simply invalidate page cache in case of failure.
2025-05-28 15:54:28 +02:00
Jussi Saurio
dad1e6293b Btree: fix cursor record state not being updated in insert_into_page()
overwrite_cell() requires that the cursor state is pointing to a valid
record, but this was not currently set properly.
2025-05-28 16:54:00 +03:00
Pekka Enberg
59d28eac93 core: Switch Completion "is_completed" to use Cell
Suggested by Jussi
2025-05-27 14:05:07 +03:00
Pekka Enberg
3250560eb8 sqlite3: Add libsql_wal_get_frame() API 2025-05-27 13:47:40 +03:00
Pekka Enberg
05df548b10 core/io: Add wait_for_completion() to I/O dispatcher 2025-05-27 13:47:40 +03:00
Pekka Enberg
eca9a5b703 core/io: Switch to Arc<Completion> 2025-05-27 11:28:49 +03:00
Pekka Enberg
21535018aa core: Don't pass page to begin_read_wal_frame()
Make `begin_read_wal_frame()` a bit more generic by not requiring a page
to be passed.
2025-05-27 10:02:36 +03:00
Jussi Saurio
3ba9f2ab97 Small cleanups to pager/wal/vdbe - mostly naming
- Instead of using a confusing CheckpointStatus for many different things,
  introduce the following statuses:
    * PagerCacheflushStatus - cacheflush can result in either:
      - the WAL being written to disk and fsynced
      - but also a checkpoint to the main BD file, and fsyncing the main DB file

      Reflect this in the type.
    * WalFsyncStatus - previously CheckpointStatus was also used for this, even
      though fsyncing the WAL doesn't checkpoint.
    * CheckpointStatus/CheckpointResult is now used only for actual checkpointing.

- Rename HaltState to CommitState (program.halt_state -> program.commit_state)
- Make WAL a non-optional property in Pager
  * This gets rid of a lot of if let Some(...) boilerplate
  * For ephemeral indexes, provide a DummyWAL implementation that does nothing.
- Rename program.halt() to program.commit_txn()
- Add some documentation comments to structs and functions
2025-05-26 10:37:34 +03:00
Jussi Saurio
b5ac095716 Fix off-by-one error in max_frame after WAL load 2025-05-25 19:34:51 +03:00
Jussi Saurio
385c0d8987 clippy stfu part 2: electric boogaloo 2025-05-25 10:32:23 +03:00
Jussi Saurio
64ef3f1343 simplify condition 2025-05-25 10:22:46 +03:00
Jussi Saurio
20e65c0125 bump max_loops to 100k 2025-05-25 10:21:41 +03:00
Jussi Saurio
fc45e0ec0d Reconstruct WAL frame cache when WAL is opened
Currently we are simply unable to read any WAL frames from disk
once a fresh process w/ Limbo is opened, since we never try to read
anything from disk unless we already have it in our in-memory
frame cache.

This commit implements a crude way of reading entire WAL into memory
as a single buffer and reconstructing the frame cache.
2025-05-24 18:29:44 +03:00
Jussi Saurio
70433e100d Merge 'btree: fix infinite looping in backwards iteration of btree table' from Jussi Saurio
Closes #1562
Existing "fuzz test" (not really fuzz, but kinda) didn't catch this due
to `LIMIT 3` clause

Closes #1563
2025-05-23 21:46:16 +03:00
Jussi Saurio
1a937462b3 Merge 'core/pragma: Add support for update user_version' from Diego Reis
It also changes the type from u32 to i32 since
sqlite supports negative values

Closes #1559
2025-05-23 17:00:55 +03:00
Jussi Saurio
cbb56a182e Fix bug: backwards iteration of table btree hangs 2025-05-23 14:23:18 +03:00
Diego Reis
2f8042da22 core/pragma: Add support for update user_version
It also changes the type from u32 to i32 since
sqlite supports negative values
2025-05-22 20:38:27 -03:00
Zaid Humayun
4312d371fb addresses comment https://github.com/tursodatabase/limbo/pull/1548#discussion_r2102606810 by @jussisaurio
this commit changes the btree_destroy() signature to return an Option<usize>. This more closely resembles Rust semantics instead of passing a pointer to a usize.
However, I'm unsure if I'm handling the cursor result correctly
2025-05-23 00:46:05 +05:30
Zaid Humayun
4072a41c9c Drop Table now uses an ephemeral table as a scratch table
Now when dropping a table, an ephemeral table is created as a scratch table. If a root page of some other table is moved into the page occupied by the root page of the table being dropped, that row is first written into an ephemeral table. Then on a next pass, it is deleted from the schema table and then re-inserted with the new root page.

This happens during AUTOVACUUM when deleting a root page will force the last root page to move into the slot being vacated by the root page of the table being deleted
2025-05-22 19:39:46 +05:30
Pere Diaz Bou
b135bf449f reduce attempts for fuzz_long overflow 2025-05-21 15:40:42 +02:00
Pere Diaz Bou
7143e43dd4 clippy 2025-05-21 15:27:15 +02:00
Pere Diaz Bou
a69f85be84 cacheflush clear cache 2025-05-21 14:20:11 +02:00
Pere Diaz Bou
4704cdd24f validate_btree pin pages 2025-05-21 14:20:11 +02:00
Pere Diaz Bou
ddb166f0f0 custom hashmap for page cache 2025-05-21 14:19:56 +02:00
Pere Diaz Bou
c365d79cb1 minimum capacity 10 in page cache 2025-05-21 14:19:56 +02:00
Pere Diaz Bou
b76961ce35 balance mark dirty from start 2025-05-21 14:19:56 +02:00
Pere Diaz Bou
591c674e86 Introduce PageRef wrapper BTreePage.
One problem we have with PageRef, is that this Page reference can be
unloaded, this means if we read the page again instead of loading the
page onto the same reference, we will have split brain of references.

To solve this we wrap PageRef in `BTreePage` so that if a page is seen
as unloaded, we will replace BTreePage::page with the newest version of
the page.
2025-05-21 14:19:41 +02:00
Pere Diaz Bou
35f7317724 add default page cache 2025-05-21 14:11:21 +02:00
Pere Diaz Bou
15d24bd818 Start transactions in fuzz tests to flush pages
Previously, fuzz tests increase the size of page cache indefinitely,
therefore the was no problem of reaching the capacity of a page cache.
By adding transactions to fuzz tests we allow pages to remove dirty
flags once insert is finished.
2025-05-21 14:11:20 +02:00