Commit graph

11942 commits

Author SHA1 Message Date
Jussi Saurio
8b45877ce5 Pass experimental feature flags from JS/python bindings 2025-12-22 13:16:42 +02:00
Jussi Saurio
e1f10bb09e mark attach as experimental 2025-12-22 09:40:22 +02:00
Pekka Enberg
f598dfa13d
Merge 'core/mvcc: set_null_flag(false) when seek is called' from Pere Diaz Bou
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Rust / cargo-fmt-check (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
## Description
BTreeCursor sets null flag to false once `seek` is called. This PR does
the same for MVCC
## Motivation and context
join.test failed with some cases due to this bug
## Description of AI Usage
I asked AI to find the issue but I ended showing the agent why he did
things wrong and that he should be ashamed

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

Closes #4296
2025-12-22 09:15:24 +02:00
Pekka Enberg
6fcf66be3d
Merge 'pyturso: fix panic' from Nikita Sivukhin
`resume` was not re-entrant and panicked in case when was called after
operation completion.
```
thread '<unnamed>' panicked at sync/sdk-kit/src/turso_async_operation.rs:59:20:
`async fn` resumed after completion
...
```
This PR makes `resume` method for `PyTursoAsyncOperation` re-entrant
(like in the c-api) and also convert exception type in the sync module

Closes #4315
2025-12-22 09:09:37 +02:00
Pekka Enberg
d3714f4120
Merge 'Mark triggers as experimental' from Jussi Saurio
Closes #4022

Closes #4318
2025-12-22 09:08:54 +02:00
Preston Thorpe
d6ceda8dcb
Merge 'fix(core/translate): apply affinity conversion to hash join build and probe keys' from Nuno Gonçalves
## Description
This PR adds missing affinity conversion to hash joins by applying
affinity conversion to build and probe keys before hashing.
```
turso> CREATE TABLE x(a INTEGER);
turso> CREATE TABLE y(b TEXT);
turso> INSERT INTO x VALUES (2),(3);
turso> INSERT INTO y VALUES ('02'),('2'),('2.0'),('3x'),('3.5');
turso> SELECT a, b
  FROM x JOIN y ON a = b
  ORDER BY a, b;
┌───┬─────┐
│ a │ b   │
├───┼─────┤
│ 2 │ 02  │
├───┼─────┤
│ 2 │ 2   │
├───┼─────┤
│ 2 │ 2.0 │
└───┴─────┘
```
## Motivation and context
Fixes #3482.
Currently, Turso returns an empty result set:
```
turso> CREATE TABLE x(a INTEGER);
turso> CREATE TABLE y(b TEXT);
turso> INSERT INTO x VALUES (2),(3);
turso> INSERT INTO y VALUES ('02'),('2'),('2.0'),('3x'),('3.5');
turso> SELECT a, b
  FROM x JOIN y ON a = b
  ORDER BY a, b;
turso>
```
Expected behavior:
```
sqlite> CREATE TABLE x(a INTEGER);
sqlite> CREATE TABLE y(b TEXT);
sqlite> INSERT INTO x VALUES (2),(3);
sqlite> INSERT INTO y VALUES ('02'),('2'),('2.0'),('3x'),('3.5');
sqlite> SELECT a, b
   ...>   FROM x JOIN y ON a = b
   ...>   ORDER BY a, b;
2|02
2|2
2|2.0
```
## Description of AI Usage
This PR was developed with assistance from Claude Sonnet 4.5 through
code completions.

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

Closes #4317
2025-12-21 21:08:29 -05:00
Preston Thorpe
ca0f86c8d8
Merge 'Set all testing dbs to WAL journal mode' from Preston Thorpe
Set the testing DB's to WAL mode permanently so we don't keep making
changes to these every time we open them with `make test`

Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #4321
2025-12-21 21:07:37 -05:00
PThorpe92
9954b096cc
Set all testing dbs to WAL journal mode 2025-12-21 21:02:02 -05:00
Jussi Saurio
ad609dd04f
Merge 'fix/core: fix transaction issues' from Jussi Saurio
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Rust / cargo-fmt-check (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
## Transaction fixes
- return BUSY_SNAPSHOT instead of BUSY when transaction tries to
      promote from read to write and its snapshot is stale. this is
      a case where retrying with busy_timeout will never help.
- fix bug in begin_read_tx() where it would not allow to use a
      readmark that is lower than shared_max (causes an enormous amount
of busy errors / contention)
 - fix another bug in begin_read_tx() where it would not decrement
shared lock if it needed to abort due to stale header values
- validate shared state again after deciding to use read0 lock -
otherwise we might miss frames (another TOCTOU issue)
- implement sqlite's exponential backoff algorithm for begin_read_tx()
      to improve multiple threads' ability to acquire write lock
## Fix deadlock
use with_shared() instead of with_shared_mut() for lock ops
using shared_mut() is unnecessary because the locks use atomics, and
in fact using shared_mut() can cause a deadlock, example:
- Thread 1 calls with_shared_mut() at in try_begin_read_tx
   to claim/update a read mark slot. This waits for readers to release
   their shared read locks.
- Thread 2 tries to use with_shared_mut() in end_read_tx() and also
  can't proceed
## Perf/throughput test adjustment
If `BusySnapshot` is returned, explicitly ROLLBACK and restart the
transaction
## Review guide
I've interactive rebased this to 10 commits that are fairly sensible, so
feel free to read one-by-one.

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

Closes #4289
2025-12-21 22:50:33 +02:00
Jussi Saurio
2bf7ec5136 mark triggers as experimental 2025-12-21 21:18:15 +02:00
Nuno Gonçalves
734ba9a1bf chore(format): cargo fmt 2025-12-21 17:15:11 +00:00
Nuno Gonçalves
1b386147c1 fix(core/translate): apply affinity conversion to hash join build and probe keys 2025-12-21 16:59:46 +00:00
Jussi Saurio
492e4cfcd3 quick script to run thrpt benchmark N times 2025-12-21 18:38:08 +02:00
Jussi Saurio
a69191e365 perf/thrpt: rollback+restart if BusySnapshot error is returned 2025-12-21 18:38:05 +02:00
Jussi Saurio
6e58378471 rename with_shared_mut to with_shared_mut_dangerous 2025-12-21 18:38:01 +02:00
Jussi Saurio
acc1a89872 fix/wal: use with_shared() instead of with_shared_mut() for lock ops
using shared_mut() is unnecessary because the locks use atomics, and
in fact using shared_mut() can cause a deadlock, example:

- Thread 1 calls with_shared_mut() at in try_begin_read_tx
   to claim/update a read mark slot. This waits for readers to release
   their shared read locks.
- Thread 2 tries to use with_shared_mut() in end_read_tx() and also
  can't proceed
2025-12-21 18:37:58 +02:00
Jussi Saurio
18f6e1a350 Update tests for BusySnapshot error
- Handle "snapshot is stale" in fuzz tests as retriable error
- Test that stale snapshot returns BusySnapshot, not Busy
2025-12-21 18:37:47 +02:00
Jussi Saurio
97be13a6be Implement progressive backoff in begin_read_tx
Extract try_begin_read_tx with TryBeginReadResult::Retry for transient
conditions. begin_read_tx now retries with SQLite's quadratic backoff:
immediate retries for first 5 attempts, yield for 6-9, then quadratic
microsecond delays matching SQLite's formula.
2025-12-21 18:37:34 +02:00
Jussi Saurio
aead47f2a8 Return BusySnapshot instead of Busy for stale snapshot in begin_write_tx
BusySnapshot indicates the transaction's snapshot is permanently stale
and must be rolled back. Unlike Busy, retrying with busy_timeout will
never help - the caller must rollback and restart the transaction.
2025-12-21 18:35:03 +02:00
Jussi Saurio
139b398e49 Fix begin_read_tx validation and unlock on retry
- Add lock-0 re-validation after acquiring read_locks[0]
- Remove incorrect best_mark == shared_max requirement (stale mark is fine)
- Add current_slot_mark validation to detect slot modification race
- Unlock read lock before returning Busy on validation failure
- Use shared_max instead of best_mark for max_frame (bug fix)
2025-12-21 18:34:06 +02:00
Jussi Saurio
6938f334ab Add yield_now() and sleep() to IO trait
Used for progressive backoff in contended lock acquisition.
2025-12-21 18:29:52 +02:00
Jussi Saurio
cabea235ce Add BusySnapshot error type
Distinct from Busy: indicates the transaction's snapshot is permanently
stale and must be rolled back. Retrying with busy_timeout will not help.
2025-12-21 18:29:39 +02:00
Nikita Sivukhin
fc21324c61 fix test 2025-12-21 15:47:19 +04:00
Nikita Sivukhin
f94f38623d uvx ruff check --fix 2025-12-21 14:29:10 +04:00
Nikita Sivukhin
0270505210 fix exception type 2025-12-21 14:28:52 +04:00
Nikita Sivukhin
03c95fb1ad fix async operation resume API usage in python bindings 2025-12-21 14:24:42 +04:00
Nikita Sivukhin
7a79adc958 make resume re-entrant 2025-12-21 14:24:05 +04:00
Nikita Sivukhin
1393482f1f add concurrency test in python 2025-12-21 12:10:23 +04:00
Nikita Sivukhin
367083a4b5 fix bug in sync server implementation 2025-12-21 11:54:54 +04:00
Preston Thorpe
07390ede53
Merge 'sim: fix apply_snapshot for create table, create index, drop column' from Jussi Saurio
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Rust / cargo-fmt-check (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
have to leave for train soon, so claude summary:
### Bugfix 1: track CREATE TABLE, CREATE INDEX, DROP INDEX as sequential
operations
Closes #4303
Changes in runner/env.rs:
  1. Renamed RowOperation to TxOperation
  2. Added CreateTable, CreateIndex and DropIndex variants
  3. Added corresponding record_* methods to both TransactionTables and
ShadowTablesMut
  4. Updated apply_snapshot() to handle CreateTable, CreateIndex, and
DropIndex operations in order
  5. Removed the index sync loop at the end of apply_snapshot() since
operations are now tracked properly
  Changes in model/mod.rs:
  1. Updated Shadow for Create to call record_create_table() before
applying the change
  2. Updated Shadow for CreateIndex to call record_create_index() before
applying the change
  3. Updated Shadow for DropIndex to call record_drop_index() before
applying the change
  The core fix is that CreateTable and CreateIndex operations are now
recorded as they happen, so when apply_snapshot() replays operations in
order, subsequent operations like AlterTable find the table already
created in committed_tables.
### Bugfix 2: track table name changes in txn so ADD COLUMN && DROP
COLUMN work properly
When processing AddColumn and DropColumn operations, the code looks up
tables in transaction_tables.current_tables using the table name stored
in the operation. However, transaction_tables.current_tables has tables
with their final names (after all renames), while operations store the
name at the time they were recorded.
      In the failing case:
      1. DropColumn was recorded with table_name =
"stellar_katerina_672"
      2. RenameTable changed the name to "captivating_eco_1159"
      3. At commit, when processing DropColumn, we looked for
"stellar_katerina_672" but the table was now named
"captivating_eco_1159"
      The fix: Build a mapping from old names → final names by scanning
all RenameTable operations first, then use the final name when looking
up in transaction_tables.current_tables.
Closes #4305

Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #4304
2025-12-20 13:55:18 -05:00
Preston Thorpe
71944c9d49
Merge 'Revert "Merge 'fix stack overflow in long unary expressions' from "' from Jussi Saurio
This reverts commit b40cdb1bfd, reversing
changes made to cd22c4dc48.
Closes #4306
Closes #4302
Reopens #4197

Closes #4307
2025-12-20 13:43:40 -05:00
Preston Thorpe
a10051dde4
Merge 'Fix RTRIM ignoring trailing tabs' from Krishna Vishal
`str::trim_end()` removes trailing tabs too. Replaced it with
`trim_end_matches(' ')`. Rust `str::trim` functions seem problematic
because they remove non-ascii whitespace and others.
Behavior now:
```
turso> select 'x' || char(9) = 'x' collate rtrim;
┌─────────────────────────────────────┐
│ 'x' || char (9) = 'x' COLLATE rtrim │
├─────────────────────────────────────┤
│                                   0 │
└─────────────────────────────────────┘
```
Closes: #3480

Reviewed-by: Mikaël Francoeur (@LeMikaelF)

Closes #3891
2025-12-20 10:33:59 -05:00
Preston Thorpe
90e6ed0ba4
Merge 'Fix incorrect conversion from TEXT to INTEGER when text is a number followed by a trailing non-breaking space' from Krishna Vishal
This PR fixes incorrect conversion from TEXT to INTEGER when text is a
number followed by a trailing non-breaking space.
This happens because `str::trim()` trims non-breaking space and unicode
whitespace while SQLite only trims ASCII whitespace.
Closes: https://github.com/tursodatabase/turso/issues/3679

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

Closes #3878
2025-12-20 10:33:15 -05:00
Jussi Saurio
3428359a73 Revert "Merge 'fix stack overflow in long unary expressions' from "
This reverts commit b40cdb1bfd, reversing
changes made to cd22c4dc48.
2025-12-20 10:09:34 +02:00
Jussi Saurio
84244cf5f8 sim: fix stale name in TxOperation::DropColumn
When processing AddColumn and DropColumn operations, the code looks up tables in transaction_tables.current_tables using the table name stored in the operation. However, transaction_tables.current_tables has tables with their final names (after all renames), while operations store the name at the time they were recorded.

  In the failing case:
  1. DropColumn was recorded with table_name = "stellar_katerina_672"
  2. RenameTable changed the name to "captivating_eco_1159"
  3. At commit, when processing DropColumn, we looked for "stellar_katerina_672" but the table was now named "captivating_eco_1159"

  The fix: Build a mapping from old names → final names by scanning all RenameTable operations first, then use the final name when looking up in transaction_tables.current_tables.
2025-12-20 09:52:58 +02:00
Jussi Saurio
87f9cb71c7 sim: fix apply_snapshot for create table and create index
have to leave for train soon, so claude summary:

Changes in runner/env.rs:
  1. Renamed RowOperation to TxOperation
  2. Fixed the CreateTable variant to store the full Table instead of separate fields
  3. Added CreateIndex and DropIndex variants
  4. Added corresponding record_* methods to both TransactionTables and ShadowTablesMut
  5. Updated apply_snapshot() to handle CreateTable, CreateIndex, and DropIndex operations in order
  6. Removed the index sync loop at the end of apply_snapshot() since operations are now tracked properly

  Changes in model/mod.rs:
  1. Updated Shadow for Create to call record_create_table() before applying the change
  2. Updated Shadow for CreateIndex to call record_create_index() before applying the change
  3. Updated Shadow for DropIndex to call record_drop_index() before applying the change

  The core fix is that CreateTable and CreateIndex operations are now recorded as they happen, so when apply_snapshot() replays operations in order, subsequent operations like AlterTable find the table already created in committed_tables.
2025-12-20 07:51:24 +02:00
Preston Thorpe
2a4eb02095
Merge 'Sync fixes' from Nikita Sivukhin
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Rust / cargo-fmt-check (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
This PR introduces few sync fixes relevant to the partial sync feature:
1. Make `try_wal_watermark_read_page` async - this is important as now
db file can be partial and require extra network IO for fetching missing
pages
2. Do not panic if requested page doesn't exist on server - this can be
valid case if db on the server has smaller size
3. Maintain clean db file size in order to avoid reads outside of the
file (this can happen, when we revert new pages allocated only in the
WAL and need to fetch their previous state if there is one)

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

Closes #4297
2025-12-19 17:56:01 -05:00
Preston Thorpe
edf6756225
Merge 'fix(core): prevent ALTER COLUMN from resulting in tables with only generated columns' from Nuno Gonçalves
## Description
This PR prevents `ALTER COLUMN` from resulting in tables with only
generated columns. Currently, Turso only applies this rule in `CREATE
TABLE` but not in `ALTER COLUMN`.
Expected behavior:
```
turso> CREATE TABLE t1(a as (123));
  × Parse error: must have at least one non-generated column

turso> CREATE TABLE t2(a);
turso> ALTER TABLE t2 ALTER COLUMN a TO b AS (123);
  × Parse error: must have at least one non-generated column

turso> CREATE TABLE t3(a, b);
turso> ALTER TABLE t3 ALTER COLUMN a TO c AS (123);
turso> ALTER TABLE t3 ALTER COLUMN b TO d AS (123);
  × Parse error: must have at least one non-generated column
```
## Motivation and context
Fixes #3653.
Currently, Turso does not restrict tables from having only generated
columns when using `ALTER COLUMN`:
```
turso> create table t(a);
turso> alter table t alter column a to b as (123);
turso> select * from sqlite_schema;
┌───────┬──────┬──────────┬──────────┬─────────────────────────────┐
│ type  │ name │ tbl_name │ rootpage │ sql                         │
├───────┼──────┼──────────┼──────────┼─────────────────────────────┤
│ table │ t    │ t        │        2 │ CREATE TABLE t (b AS (123)) │
└───────┴──────┴──────────┴──────────┴─────────────────────────────┘
```
## Description of AI Usage
This PR was developed with assistance from Claude Sonnet 4.5. The AI
helped identify the root cause and assisted in debugging issues in my
initial implementation.

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

Closes #4257
2025-12-19 17:52:11 -05:00
Nuno Gonçalves
21268632eb fix(core): prevent ALTER COLUMN from resulting in tables with only generated columns 2025-12-19 21:52:36 +00:00
Preston Thorpe
3e4e25d4bb
Merge 'Remove run once from Statement' from Pedro Muniz
Some checks are pending
Build & publish @tursodatabase/database / db-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / db-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-apple-darwin - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-aarch64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-wasm32-wasip1-threads - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-pc-windows-msvc - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / sync-bindings-x86_64-unknown-linux-gnu - node@20 (push) Waiting to run
Build & publish @tursodatabase/database / Test DB bindings on Linux-x64-gnu - node@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Test DB bindings on browser@20 (push) Blocked by required conditions
Build & publish @tursodatabase/database / Publish (push) Blocked by required conditions
Python / configure-strategy (push) Waiting to run
Python / test (push) Blocked by required conditions
Python / lint (push) Waiting to run
Python / linux (x86_64) (push) Waiting to run
Python / macos-arm64 (aarch64) (push) Waiting to run
Python / sdist (push) Waiting to run
Python / Release (push) Blocked by required conditions
Rust / simulator (push) Waiting to run
Rust / test-limbo (push) Waiting to run
Rust / test-sqlite (push) Waiting to run
Rust / cargo-fmt-check (push) Waiting to run
Rust / build-native (blacksmith-4vcpu-ubuntu-2404) (push) Waiting to run
Rust / build-native (macos-latest) (push) Waiting to run
Rust / build-native (windows-latest) (push) Waiting to run
Rust / clippy (push) Waiting to run
Rust Benchmarks+Nyrkiö / bench (push) Waiting to run
Rust Benchmarks+Nyrkiö / clickbench (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h-criterion (push) Waiting to run
Rust Benchmarks+Nyrkiö / tpc-h (push) Waiting to run
Rust Benchmarks+Nyrkiö / vfs-bench-compile (push) Waiting to run
## Description
- Move `Statement` to different file
- remove run once from `Statement`
- add helper functions to demonstrate explicit blocking behaviour
- we were not checking for naming conflicts correctly in create view and
create table, so me and Claude fixed that as well
- made adjustments some adjustments to `print_query_result` in the cli
`run_once` does not even have the most up-to-date error handling as we
have in  `Program::abort`, so we really should not be using it
I guess these recent changes uncovered some subtle bugs we had that
masked the error. It did not help as well that most tcl tests expect any
error and not an error pattern, so maybe we were erroring before for
some weird reason in the cli?
Closes #2388
<!--
Please include a summary of the changes and the related issue.
-->
## Motivation and context
We should avoid having an API that actually drives the IO in Statement,
but as we have many Sync IO hacks, this is currently not possible. Due
to our embedded nature IO should be driven by the user of the library,
so we should be pushing IO stepping away from Core and towards bindings
in my opinion. I think we can accomplish this by providing blocking/busy
looping and async Statements in Core. We already almost have this
differentiation with `step_with_waker`.  Such an api would also make it
easier for us use async in core in the future.
This refactor of hiding the IO stepping behind helpers is to hopefully
mitigate future refactors with async, and to fix many places that do not
run statements to completions.
<!--
Please include relevant motivation and context.
Link relevant issues here.
-->
## Description of AI Usage
None. Didn't want to risk AI doing something wrong, so I did the
refactor by hand
**EDIT:** asked it to help me slightly to help with `print_query_result`
<!--
Please disclose how AI was used to help create this PR. For example, you
can share prompts,
specific tools, or ways of working that you took advantage of. You can
also share whether the
creation of the PR was mainly driven by AI, or whether it was used for
assistance.
This is a good way of sharing knowledge to other contributors about how
we can work more efficiently with
AI tools. Note that the use of AI is encouraged, but the committer is
still fully responsible for understanding
and reviewing the output.
-->

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

Closes #4290
2025-12-19 15:32:03 -05:00
pedrocarlo
2bc976f3d9 add proper name checks for create table, view 2025-12-19 17:20:46 -03:00
pedrocarlo
32401f52a1 clippy 2025-12-19 17:20:46 -03:00
pedrocarlo
eaadaee5c3 refactor more of the core tester to use helpers 2025-12-19 17:20:46 -03:00
pedrocarlo
e986247890 convert sqlite.rs + core tester to use helpers 2025-12-19 17:20:46 -03:00
pedrocarlo
06326e6d16 for now use the _io() for rust bindings for implementing future. But in the future we would remove this and the let the user advance io 2025-12-19 17:20:46 -03:00
pedrocarlo
1c737cfac5 refactor simulator to use new helpers 2025-12-19 17:20:46 -03:00
pedrocarlo
880b04eaba add internal method to acquire IO from statement for sdk kit 2025-12-19 17:20:46 -03:00
pedrocarlo
07ea1b071c refactor rest of cli to use helper 2025-12-19 17:20:46 -03:00
pedrocarlo
31d8981b4f refactor print_query_result to avoid macro and to be easier to understand 2025-12-19 17:20:46 -03:00
pedrocarlo
10577dd6c5 adjust run_one_step_blocking 2025-12-19 17:20:46 -03:00