Commit Graph

6572 Commits

Author SHA1 Message Date
stano
4ceea1a473 Update limbo -> turso in manual.md 2025-07-26 15:58:22 +03:00
Pekka Enberg
cc5d4dc3ba Merge 'support doubly qualified identifiers' from Glauber Costa
Closes #2271
2025-07-26 11:31:42 +03:00
Pekka Enberg
2ae5e7bd76 Merge 'mark detach as supported' from Glauber Costa
Honestly, I didn't even notice we had a compat entry for it because it
seems so trivial. But it was done as part of ATTACH.

Closes #2272
2025-07-26 11:31:07 +03:00
Glauber Costa
02e57c81f7 mark detach as supported
Honestly, I didn't even notice we had a compat entry for it because it
seems so trivial. But it was done as part of ATTACH.
2025-07-25 15:35:13 -05:00
Glauber Costa
b5927dcfd5 support doubly qualified identifiers 2025-07-25 14:52:45 -05:00
Pekka Enberg
273c2923f0 Merge 'Fix get_column_name() when a column name doesn't exist' from meteorgan
we would encounter a panic in `display.rs` when a column name does not
exist.
```
turso> select * from (select 1);

thread 'main' panicked at core/translate/display.rs:252:50:
called `Option::unwrap()` on a `None` value
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
after this PR:
```
turso> select * from (select 1);
2025-07-25T15:52:24.241294Z DEBUG ThreadId(01) run_cmd:translate:optimize_plan: turso_core::translate::optimizer: 51: plan_sql="SELECT subquery_0.0 FROM (SELECT 1 FROM) AS subquery_0"
2025-07-25T15:52:24.242036Z DEBUG ThreadId(01) step:begin_read_tx:begin_read_tx: turso_core::storage::wal: 552: begin_read_tx(min_frame=1, max_frame=0, lock=0, max_frame_in_wal=0)
2025-07-25T15:52:24.242349Z DEBUG ThreadId(01) step:commit_txn:end_read_tx:end_read_tx: turso_core::storage::wal: 566: end_read_tx(lock=0)
┌───┐
│ . │
├───┤
│ 1 │
└───┘
```

Closes #2269
2025-07-25 21:38:09 +03:00
Pekka Enberg
c7996652fe Merge 'bindings/javascript: Switch to napi v3' from Diego Reis
Switch to napi [v3](https://napi.rs/blog/announce-v3).
With the exception of `Statement.iterate()`,  the behavior is preserved.
I had to temporarily remove it because the trait `Generator` doesn't
supports the new lifetime scoped values, I already brought this issue in
napi's discord server and it should be fixed soon.

Closes #2262
2025-07-25 20:19:37 +03:00
Diego Reis
220a548f57 workflow: Fix macOS universal binary build 2025-07-25 14:01:39 -03:00
meteorgan
b5a18d7dc9 fix get_column_name() when column name doesn't exist 2025-07-25 23:49:31 +08:00
Pekka Enberg
e0e3c52535 Merge 'Simplify sum() aggregation logic' from bit-aloo
This refactors AggContext::Sum by removing the extra bool flag and
simplifying type handling during aggregation:

Closes #2265
2025-07-25 17:57:58 +03:00
Diego Reis
0f95cf7751 bind/js: Switch to napi v3 2025-07-25 11:45:57 -03:00
Pekka Enberg
308f20a5cf turso-serverless: Fix wrong error import
```
  Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/penberg/src/tursodatabase/turso/packages/turso-serverless/dist/error' imported from /Users/penberg/src/tursodatabase/turso/packages/turso-serverless/dist/protocol.js

  Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/penberg/src/tursodatabase/turso/packages/turso-serverless/dist/error' imported from /Users/penberg/src/tursodatabase/turso/packages/turso-serverless/dist/protocol.js
      at finalizeResolution (node:internal/modules/esm/resolve:275:11)
      at moduleResolve (node:internal/modules/esm/resolve:860:10)
      at defaultResolve (node:internal/modules/esm/resolve:984:11)
      at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:780:12)
      at #cachedDefaultResolve (node:internal/modules/esm/loader:704:25)
      at ModuleLoader.resolve (node:internal/modules/esm/loader:687:38)
      at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:305:38)
      at ModuleJob._link (node:internal/modules/esm/module_job:137:49)

  ✘ integration-tests/serverless.test.mjs exited with a non-zero exit code: 1
```
2025-07-25 17:11:13 +03:00
Pekka Enberg
b1c0ba4da0 stress: Allow multi-threading but warn about it 2025-07-25 16:53:02 +03:00
Pere Diaz Bou
805bcfe633 Merge 'Ignore WAL frames after bad checksum' from Pere Diaz Bou
SQLite basically ignores bad frames instead of panicking, let's try to
do the same.

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

Closes #1956
2025-07-25 15:31:12 +02:00
bit-aloo
4f8027990d detach the sum and total logic from using has_non_numeric flag 2025-07-25 17:59:19 +05:30
bit-aloo
f389c31ac9 remove bool from sum variant in AggContext 2025-07-25 17:55:53 +05:30
Pekka Enberg
76cf3444c6 Turso 0.1.3-pre.5 2025-07-25 13:24:33 +03:00
Pekka Enberg
c6c0db19e9 Merge 'Fix schema reparse logic' from Nikita Sivukhin
`maybe_reparse_schema` function introduced in the #2246 was incorrect as
it didn't update `schema_version` for internal schema representation and
basically updated only schema for connection which called
`maybe_reparse_schema`.
This PR fixes this issue by reading schema and cookie value within a
single transaction and updating both schema content and its version for
internal representation.

Reviewed-by: Pedro Muniz (@pedrocarlo)

Closes #2259
2025-07-25 13:24:23 +03:00
Nikita Sivukhin
020d567e78 fix clippy 2025-07-25 13:55:37 +04:00
Pekka Enberg
669b231714 Merge 'parser: Distinguish quoted identifiers and unify Id into Name enum' from bit-aloo
Closes: #1947
This PR replaces the `Name(pub String)` struct with a `Name` enum that
explicitly models how the name appeared in the source either as an
unquoted identifier (`Ident`) or a quoted string (`Quoted`).
In the process, the separate `Id` wrapper type has been coalesced into
the `Name` enum, simplifying the AST and reducing duplication in
identifier handling logic.
While this increases the size of some AST nodes (notably
`yyStackEntry`).
cc: @levydsa

Reviewed-by: Levy A. (@levydsa)
Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #2251
2025-07-25 12:08:54 +03:00
Pekka Enberg
c6d4a5c3ed Rename DatabaseIndexer to DatabaseCatalog
Avoid confusion with actual database indexes.
2025-07-25 10:36:33 +03:00
Pekka Enberg
97a2d36ae2 Merge 'Support ATTACH (read only)' from Glauber Costa
Support for attaching databases. The main difference from SQLite is that
we support an arbitrary number of attached databases, and we are not
bound to just 100ish.
We for now only support read-only databases. We open them as read-only,
but also, to keep things simple, we don't patch any of the insert
machinery to resolve foreign tables.  So if an insert is tried on an
attached database, it will just fail with a "no such table" error - this
is perfect for now.
The code in core/translate/attach.rs is written by Claude, who also
played a key part in the boilerplate for stuff like the .databases
command and extending the pragma database_list, and also aided me in the
test cases.

Closes #2235
2025-07-25 10:33:36 +03:00
Glauber Costa
988b16f962 Support ATTACH (read only)
Support for attaching databases. The main difference from SQLite is that
we support an arbitrary number of attached databases, and we are not
bound to just 100ish.

We for now only support read-only databases. We open them as read-only,
but also, to keep things simple, we don't patch any of the insert
machinery to resolve foreign tables.  So if an insert is tried on an
attached database, it will just fail with a "no such table" error - this
is perfect for now.

The code in core/translate/attach.rs is written by Claude, who also
played a key part in the boilerplate for stuff like the .databases
command and extending the pragma database_list, and also aided me in
the test cases.
2025-07-24 19:19:48 -05:00
Nikita Sivukhin
e05660133b update schema version for internal schema represenation in maybe_reparse_schema 2025-07-24 22:43:31 +04:00
Nikita Sivukhin
8b0e5b151e simplify parse_schema_rows signature 2025-07-24 22:43:31 +04:00
Nikita Sivukhin
27fcb81f48 add more complex schema changes test for raw WAL API 2025-07-24 22:43:31 +04:00
Pekka Enberg
2141293017 Merge 'Fix page_count pragma' from meteorgan
Closes: #1415
### What this PR does
1. Removes database initialization from the `read_tx` function.
2. Adds checks for database initialization when executing `.schema`,
`.indexes`, `.tables` and `.import` commands, as they rely on
`sqlite_schema` table.
### About the second issue
I think we have another solution for the second issue: create the
`sqlite_schema` table in `Schema` only during page1 initialization,
rather than during `Schema` initialization.
#### Pros
This approach has the advantage of unifying the logic for the
`sqlite_schema` table with other user tables when running `select`
statements
#### Cons
- we still need to check error codes for commands like  `.schema`.
- this approach may increase the complexity of the `pager`
implementation.
I'd like to hear your thoughts and feedback.

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

Closes #2099
2025-07-24 19:21:35 +03:00
Pekka Enberg
5018f0b7cb Turso 0.1.3-pre.4 2025-07-24 19:12:28 +03:00
Pekka Enberg
ae2da8278f Merge 'serverless: Add DatabasError type' from Pekka Enberg
Add an explicit error type so application can actually do error
handling...

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

Closes #2256
2025-07-24 19:12:13 +03:00
Jussi Saurio
b33527c3c4 Merge 'btree: clear overflow pages when insert overwrites a cell (= UPDATE)' from Jussi Saurio
Closes #2227 , enables fixing #2225
## What
Although we cleared overflow pages on DELETE, we never did it for
INSERT/UPDATE, which means any overflow pages were left dangling and not
added to freelist.
## Why is this a problem
This means that we are not able to reuse these pages to solve #2225,
causing massive bloat in the DB when UPDATEs are executed.
## Fix
Clear overflow pages when `BTreeCursor::insert()` overwrites a cell.
Needed a new state machine for `overwrite_cell` + new `WriteState`
variants

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

Closes #2230
2025-07-24 18:59:15 +03:00
Jussi Saurio
0b627ed331 Merge 'btree/balance: support case where immediate parent page of unbalanced child page also overflows' from Jussi Saurio
Closes #2241
## What
When an index interior cell is deleted, it steals the leaf cell with the
largest key in its left subtree, deletes the old interior cell and then
replaces it with the stolen cell. This ensures the binary-search-tree
aspect of the btree remains correct. However, this can cause a situation
where both are true:
1. The leaf page is now UNDERFULL and must be rebalanced
2. The leaf's IMMEDIATE parent page is now OVERFULL and must be
rebalanced
## Why is this a problem
We simply didn't support the case where:
- Leaf page P is unbalanced and rebalancing starts on it
- Its immediate parent is ALSO unbalanced and _overflows_.
We had an assertion against this happening (see #2241)
## The fix
Allow exactly 1 overflow cell in the parent under very particular
conditions:
1. The parent page must be an index interior page
2. The parent must be positioned exactly at the divider cell whose left
child page underflows
This is the _only_ case where the immediate parent of a page about to
undergo rebalancing can have overflow cells.
## Implementation details
The parent overflow cell is folded into `cell_array` fairly early on and
`parent.overflow_cells` is cleared. However we need to be careful with
`cell_idx` for dividers other than the overflow cell because they get
shifted left on the page in `drop_cell()`. I've added a long comment
about this.
## Testing
Adds fuzz test that does inserts and deletes on an index btree and
asserts that all the expected keys are found at the end in the right
order. This test runs into this case quite frequently so I was able to
verify it.

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

Closes #2243
2025-07-24 18:48:36 +03:00
Jussi Saurio
7968be9d71 btree/insert: cell can also underflow after overwrite 2025-07-24 18:43:02 +03:00
Jussi Saurio
a4535684b3 btree: WriteState: remove CheckNeedsBalancing variant 2025-07-24 18:40:49 +03:00
Jussi Saurio
b0edd3b716 btree: WriteState: add comments 2025-07-24 18:36:07 +03:00
Pere Diaz Bou
8150a72550 check frame number is not 0
clippy

fmt

fix after rebase

clippy
2025-07-24 17:30:17 +02:00
meteorgan
c48a5ef538 we don't need read_tx return IOResult anymore 2025-07-24 23:19:33 +08:00
meteorgan
2ec40db6b5 check if db is initialized before .import 2025-07-24 23:18:29 +08:00
meteorgan
ab2bc547cd check if datbase is initialized before display schema, index and tables 2025-07-24 23:18:29 +08:00
meteorgan
08f1803a6b end read tx in op_transaction when write transaction return io 2025-07-24 23:18:29 +08:00
meteorgan
7ef50e0690 fix page_count pragma 2025-07-24 23:18:26 +08:00
Pere Diaz Bou
46f5609fce Merge 'Append WAL frames one by one' from Pere Diaz Bou
Let's make sure we don't end up in a weird situation by appending frames
one by one and we can later think of optimizations.

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

Closes #2034
2025-07-24 16:44:51 +02:00
Pekka Enberg
0f8e22a989 Merge 'pager: Clear stale page cache if database changed' from Jussi Saurio
SQLite behavior is: if another connection has modified the DB when a
read tx starts, the connection beginning the transaction must clear its
page cache due to the potentiality of there being stale versions of
pages in it. Evidence of this here:
https://github.com/sqlite/sqlite/blob/ded1959/src/pager.c#L3258-L3260
and here:
https://github.com/sqlite/sqlite/blob/master/src/wal.c#L3368-L3370
In the future, we may want to do either:
1. a more granular invalidation logic for per-conn cache, or
2. a shared versioned page cache
But right now we must follow SQLite to make our current behavior not
corrupt data
Closes #2248

Closes #2257
2025-07-24 17:22:10 +03:00
Pere Diaz Bou
ce598b772e clippy i hate you so much 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
b07e57d9d1 review fixes 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
75f9c23ed3 end txn on vdbe failures 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
674d88e140 do not clear dirty pages on cacheflush::start 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
d77c899fa6 clippy 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
5a1773edf1 clippy 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
14de7c55af set connection state to None in vdbe rollback 2025-07-24 15:29:21 +02:00
Pere Diaz Bou
c397588ad6 change connection state after finding error on I/O 2025-07-24 15:29:06 +02:00