Commit Graph

8400 Commits

Author SHA1 Message Date
pedrocarlo
f656d0bc20 header ref state machine 2025-08-06 11:32:21 -03:00
Pekka Enberg
0c9216d1cc Merge 'cdc: emit entries for schema changes' from Nikita Sivukhin
This PR emit CDC entries as changes in `sqlite_schema` table for DDL
statements: `CREATE TABLE` / `CREATE INDEX` / etc.
The logic is a bit tricky as under the hood `turso` can do some implicit
DDL operations like:
1. Creating auto-indexes in case of `CREATE TABLE`
2. Deletion of all attached indices in case of `DROP TABLE`
```
turso> PRAGMA unstable_capture_data_changes_conn('full');
turso> CREATE TABLE t(x, y, z UNIQUE, q, PRIMARY KEY (x, y));
turso> CREATE INDEX t_xy ON t(x, y);
turso> CREATE TABLE q(a, b, c);
turso> ALTER TABLE q DROP COLUMN b;

turso> SELECT
change_id, 
id,
change_type, 
table_name,
bin_record_json_object(table_columns_json_array(table_name), before) AS before,
bin_record_json_object(table_columns_json_array(table_name), after) AS after
FROM turso_cdc;
┌───────────┬────┬─────────────┬───────────────┬─────────────────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────┐
│ change_id │ id │ change_type │ table_name    │ before                                                              │ after                                                               │
├───────────┼────┼─────────────┼───────────────┼─────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│         1 │  2 │           1 │ sqlite_schema │                                                                     │ {"type":"table","name":"t","tbl_name":"t","rootpage":3,"sql":"CREA… │
├───────────┼────┼─────────────┼───────────────┼─────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│         2 │  5 │           1 │ sqlite_schema │                                                                     │ {"type":"index","name":"t_xy","tbl_name":"t","rootpage":6,"sql":"C… │
├───────────┼────┼─────────────┼───────────────┼─────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│         3 │  6 │           1 │ sqlite_schema │                                                                     │ {"type":"table","name":"q","tbl_name":"q","rootpage":7,"sql":"CREA… │
├───────────┼────┼─────────────┼───────────────┼─────────────────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────┤
│         4 │  6 │           0 │ sqlite_schema │ {"type":"table","name":"q","tbl_name":"q","rootpage":7,"sql":"CREA… │ {"type":"table","name":"q","tbl_name":"q","rootpage":7,"sql":"CREA… │
└───────────┴────┴─────────────┴───────────────┴─────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────┘
```
For now, CDC capture only all explicit operations and ignore all
implicit operations. The reasoning for that is that one use case for CDC
is to apply logical changes as is with simple SQL statements - but if
implicit operations will be logged to the CDC table too - we can have
hard times using simple SQL statement (for example, creation of
`autoindices` will always work; implicit deletion of indices for `DROP
TABLE` also can lead to some troubles and force us to is `DROP INDEX IF
EXISTS ...` statements + we will need to filter out autoindices in this
case too).
Also, to simplify PR, for now `DatabaseTape` from `turso-sync` package
just ignore all schema changes from CDC table.

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

Closes #2426
2025-08-06 14:48:27 +03:00
TcMits
e93e50ad67 more tests 2025-08-06 18:29:14 +07:00
Jussi Saurio
c8d2a1a480 btree: add a few more assertions about balance state 2025-08-06 13:39:20 +03:00
Jussi Saurio
a86a0e194d refactor/btree: cleanup write/delete/balancing states
Problem:

Currently `WriteState` "owns" the balancing state machine, even
though a separate `DeleteState` can also trigger balancing, which
results in awkward back-and-forth switching between `CursorState::Write`
and `CursorState::Delete` during balancing.

Fix:

1. Extract `balance_state` as a separate state machine, since its
state transitions are exactly the same regardless of whether an
insert or a delete triggered the balancing.
2. This allows to remove the different 'Balance-xxx' variants from
`WriteState`, as well as removing `WriteInfo` and `DeleteInfo`, as
those states become just simple enums now. Each of them now has a state
called `Balancing` which just delegates work to the balancing state
machine.
3. This further allows us to remove the awkward switching between
`CursorState::Delete` and `CursorState::Write` during a balance that
happens as a result of a deletion.
2025-08-06 13:37:35 +03:00
Jussi Saurio
aaa9ed1d9f Merge 'Add regexp capture' from bit-aloo
This PR adds RegExp Capture to regexp module

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

Closes #2465
2025-08-06 12:13:19 +03:00
Jussi Saurio
8e4597d11b Merge 'Add load_insn macro for compiler hint in vdbe::execute hot path' from Preston Thorpe
The built-in `unreachable!` macro, believe it or not is just an alias
for `panic!` and does not actually provide the compiler with a hint that
the path is not reachable.
This provides a wrapper around the actual
`std::hint::unreachable_unchecked()`, to be used only in the very hot
path of `execute` where it is not possible to be the incorrect variant.

Closes #2459
2025-08-06 12:05:33 +03:00
Jussi Saurio
9cf8a9b533 Merge 'refactor/btree: don't clone WriteState during balancing' from Jussi Saurio
## Beef
Removes cloning of `WriteState` in `balance_non_root()` and removes the
`Clone` implementation from `WriteState`.  Not only is it unnecessary to
clone the state, but even having the `Clone` implementation available is
a real regression risk in `insert_into_page()` as it will deep clone
vectors that we require stable raw pointers to in `fill_cell_payload()`
## Details
In removing the cloning of `WriteState` in `balance_non_root()`, this
replaces the `next_write_state` logic with a plain loop, which ends up
looking like a lot of changes, but it's really not. Main things that
were changed:
- Loop and mutate state instead of create new state and return
- Make `WriteInfo` an `Option` in `WriteState` for ergonomics so it can
be `.take()`:n instead of `.clone()`:d
- Clone a `Rc<Pager>` in `balance_non_root()` so that we can call
`pager.do_allocate_page()` directly instead of `self.allocate_page()`
which is just a facade for the pager method, and would violate borrowing
rules.
- assign `let usable_space = self.usable_space()` at the beginning of
the balance loop for similar reasons.
- Make the balance debug validation methods static so they don't require
a reference to self, for similar reasons

Reviewed-by: Nikita Sivukhin (@sivukhin)
Reviewed-by: Avinash Sajjanshetty (@avinassh)

Closes #2466
2025-08-06 12:03:23 +03:00
TcMits
b7962e25f7 minor 2025-08-06 15:48:23 +07:00
TcMits
436d21c81d create turso_parser crate 2025-08-06 15:42:51 +07:00
Jussi Saurio
5f3cfaac60 refactor/btree: don't clone WriteState in balance_non_root() 2025-08-06 11:30:09 +03:00
Jussi Saurio
a15d7dd2e7 refactor/btree: don't clone WriteState in balance() 2025-08-06 11:30:09 +03:00
Jussi Saurio
3d635ecd67 Merge 'refactor/btree: don't clone WriteState in insert_into_page()' from Jussi Saurio
## Problem
We currently clone `WriteState` in every loop iteration of
`insert_into_page()`, which was probably done for borrow checker
reasons, but since `WriteState` has expanded to include buffers that
must not be moved in memory or dropped, it has necessitated a really
annoying workaround of wrapping the buffers in `Arc<Mutex>>` which is
just completely wasteful.
## Fix
Do not clone `WriteState` in `insert_into_page()`, and instead work with
the borrow checker a bit more. Note that `WriteState` still _implements_
`Clone` because it's also cloned in `balance_non_root()` - that can be a
separate refactor.

Reviewed-by: Avinash Sajjanshetty (@avinassh)
Reviewed-by: Nikita Sivukhin (@sivukhin)

Closes #2464
2025-08-06 11:29:55 +03:00
Jussi Saurio
406cbb9e78 Merge 'Coll seq' from Glauber Costa
Implement the CollSeq vdbe opcode.

Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #2454
2025-08-06 11:28:27 +03:00
Pekka Enberg
2913dc4dd4 Turso 0.1.4-pre.2 2025-08-06 10:52:32 +03:00
bit-aloo
84316d9206 fix python lint 2025-08-06 12:02:20 +05:30
Pekka Enberg
ba37e1dc9a testing/javascript: Enable some passing sync test cases 2025-08-06 09:25:22 +03:00
Pekka Enberg
185b7016dd testing/javascript: Enable Statement.all() raw mode test case 2025-08-06 09:23:16 +03:00
Pekka Enberg
3a5e7f8fb6 testing/javascript: Enable Statement.all() test case 2025-08-06 09:22:48 +03:00
Pekka Enberg
53acd22950 serverless: Fix Statement.all() in expanded mode 2025-08-06 09:22:35 +03:00
Pekka Enberg
6ad50f4581 bindings/javascript: Fix prepare() error message format 2025-08-06 09:13:22 +03:00
Pekka Enberg
53ac67a2be testing/javascript: Add pragma() after close() test case 2025-08-06 09:10:03 +03:00
Pekka Enberg
2a36d133e3 serverless: Improve pragma() after close() error 2025-08-06 09:09:47 +03:00
Jussi Saurio
1c1f55fdfb refactor/btree: remove cloning of WriteState in insert_into_page() 2025-08-06 08:50:56 +03:00
Jussi Saurio
c3a32b63bf refactor/btree: remove unnecessary ref of self in overwrite_content() 2025-08-06 08:45:34 +03:00
Jussi Saurio
6dd08c21e4 refactor/btree: remove unnecessary mut ref of self in rowid() 2025-08-06 08:44:52 +03:00
Jussi Saurio
fc95282c57 Merge 'core/btree: fix re-entrancy bug in insert_into_page()' from Jussi Saurio
## Background
We currently clone `WriteState` on every iteration of
`insert_into_page()`,
presumably for _Borrow Checker Reasons (tm)_.
## Problem
There was a bug in `WriteState::Insert` handling where if
`fill_cell_payload()`
returned IO, the `fill_cell_payload_state` was not updated in
`write_info.state`, leading to an infinite loop of allocating new pages.
Further, the `new_payload` vector was also always deep-cloned.
## Fix
Update the state if `fill_cell_payload()` returns IO. Because of
`WriteState` cloning we also need to `Arc<Mutex>` wrap the vector so
that the underlying data buffer doesn't get cloned the next time
`WriteState` gets cloned, since `fill_cell_payload` relies on raw
pointers to work. Left a couple of prominent FIXMEs about this.
## Notes
This bug was surfaced by, but not caused by,
https://github.com/tursodatabase/turso/pull/2400.

Closes #2463
2025-08-06 08:23:49 +03:00
Pekka Enberg
66b4de1ad9 testing/javascript: Enable exec() after close() test case 2025-08-06 08:08:35 +03:00
Pekka Enberg
c9cec67d94 serverless: Improve exec() after close() error 2025-08-06 08:08:19 +03:00
Pekka Enberg
9ae96838ab testing/javascript: Improve exec() after close() error 2025-08-06 08:07:15 +03:00
Jussi Saurio
839d428e36 core/btree: fix re-entrancy bug in insert_into_page()
We currently clone WriteState on every iteration of `insert_into_page()`,
presumably for Borrow Checker Reasons (tm).

There was a bug in `WriteState::Insert` handling where if `fill_cell_payload()`
returned IO, the `fill_cell_payload_state` was not updated in
`write_info.state`, leading to an infinite loop of allocating new pages.

This bug was surfaced by, but not caused by, #2400.
2025-08-06 08:01:49 +03:00
Pekka Enberg
cda3375061 testing/javascript: Enable prepare() after close() test case 2025-08-06 07:50:23 +03:00
Pekka Enberg
f53adab4a8 serverless: Improve error when prepare() called after close() 2025-08-06 07:50:12 +03:00
Pekka Enberg
79412ea2cc bindings/javascript: Improve error when prepare() called after close() 2025-08-06 07:48:15 +03:00
Jussi Saurio
cd3fe523a3 core/types: add IOResult::is_io() helper 2025-08-06 07:46:51 +03:00
rajajisai
3dd08864f9 Edit comment 2025-08-05 21:27:47 -07:00
rajajisai
9ebfed294e Including tests 2025-08-05 21:18:52 -07:00
rajajisai
f49575d547 Return error when trying to drop an index associated with UNIQUE or PRIMARY KEY constraints 2025-08-05 21:17:25 -07:00
PThorpe92
f6fb786cc9 Fix borrow method on WindowsIO 2025-08-05 22:26:19 -04:00
Preston Thorpe
cb9a74ccc6 Merge 'Remove RefCell from Buffer in IO trait methods and PageContents' from Preston Thorpe
We are doing unsafe mut borrowing in `PageContent` currently, and when
new BufferPool is merged, it will be all pointers into an arena anyway.
We just need to be sure to clone the Arc and reference the buffers in
the completion callbacks so they are ensured to live for async IO.
naturally in true spirit of all my previous PR's, I needed to introduce
one while another is open that causes an absurd amount of conflicts.

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

Closes #2456
2025-08-05 21:30:27 -04:00
PThorpe92
4010c7bf0b Make clippy happy 2025-08-05 21:24:54 -04:00
PThorpe92
00a3c7eb52 Apply PR comments, fix syntax 2025-08-05 21:17:23 -04:00
PThorpe92
d5f9e60dfc Add assert_insn for compiler hint in execute hot path 2025-08-05 18:32:27 -04:00
Nikita Sivukhin
d504f9b1ac fix turso-sync tests 2025-08-06 01:03:49 +04:00
Nikita Sivukhin
c0d5c55d5c fix tests and clippy 2025-08-06 01:03:49 +04:00
Nikita Sivukhin
9c4147e8d6 add simple integration tests 2025-08-06 01:03:49 +04:00
Nikita Sivukhin
c6a87d61c7 emit CDC entries if necessary for schema changes 2025-08-06 01:03:49 +04:00
Nikita Sivukhin
0b4c1ac802 refactor code a little bit 2025-08-06 01:03:48 +04:00
PThorpe92
53a0524050 Fix clippy warning 2025-08-05 16:24:50 -04:00
PThorpe92
f6a68cffc2 Remove RefCell from IO and Page apis 2025-08-05 16:24:49 -04:00