Commit Graph

6350 Commits

Author SHA1 Message Date
Pekka Enberg
55b5e45231 Merge 'bindings/rust: Return number of rows changed from Connection::execute()' from Rohith Suresh
Fixes #1904
This PR changes the existing behaviour of Connection.execute to not
return 0, but the number of rows that have been changed by the operation
within. The changes are:
1. Adds a getter for n_change and the execute function now returns the
n_change value
2. Integration test  to test the behaviour

Closes #1987
2025-07-20 09:49:51 +03:00
Pekka Enberg
744f636c33 Merge 'bindings/java: Make TursoDB and TursoDB factory thread-safe' from Mikaël Francoeur
This PR makes `TursoDB` and `TursoDBFactory` thread-safe. I also used
the opportunity to do some minor improvements.

Reviewed-by: Kim Seon Woo (@seonWKim)

Closes #2070
2025-07-20 09:48:53 +03:00
Pekka Enberg
4be6772e8e Merge 'implement Debug for Database' from Glauber Costa
Very useful in printing data structures containing databases, like maps
Example output:
Connecting to Database { path: "sq.db", open_flags: OpenFlags(1),
db_state: "initialized", mv_store: "none", init_lock: "unlocked",
wal_state: "present", page_cache: "( capacity 100000, used: 0 )" }

Reviewed-by: Pedro Muniz (@pedrocarlo)
Reviewed-by: bit-aloo (@Shourya742)

Closes #2175
2025-07-20 09:46:09 +03:00
Pekka Enberg
068a7bbe43 Merge 'implement pragma application_id' from Glauber Costa
Just for completeness, because it is easy.

Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #2180
2025-07-20 09:22:20 +03:00
Pekka Enberg
01c7d66447 Merge 'use wasm32-wasip1 target instead of wasm32-wasi' from Nils Koch
In Rust 1.84.0, the support for the named target `wasm32-wasi` was
removed in favor of `wasm32-wasip1` ([Release
Notes](https://releases.rs/docs/1.84.0/#compatibility-notes)).
I missed that in https://github.com/tursodatabase/turso/pull/1807.
I got the following error when I tried to run `make`:
```
> make
Checking Rust version...
Rust version 1.88.0 is acceptable.
Checking wasm32-wasi target...
Installing wasm32-wasi target...
error: toolchain '1.88.0-aarch64-apple-darwin' does not support target 'wasm32-wasi'; did you mean 'wasm32-wasip1'?
note: you can see a list of supported targets with `rustc --print=target-list`
note: if you are adding support for a new target to rustc itself, see https://rustc-dev-guide.rust-lang.org/building/new-target.html
make: *** [check-wasm-target] Error 1
```

Reviewed-by: bit-aloo (@Shourya742)

Closes #2177
2025-07-20 09:21:28 +03:00
Pekka Enberg
b6eaf3262d Merge 'implement write side of pragma schema_version' from Glauber Costa
It is insane that SQLite even allows this.
They actually don't if "defensive mode" is enabled:
"It is always safe to read the schema_version, but changing the
schema_version can cause problems. For this reason, attempts to change
the value of schema_version are a silent no-op when defensive mode is
enabled for a database connection.
Warning: Misuse of this pragma can result in database corruption."
We also update the compat table, which was not updated to reflect the
read version of this pragma being implemented.

Closes #2181
2025-07-20 09:20:23 +03:00
RS2007
cd31119972 Fix: cargo clippy warning 2025-07-20 07:28:14 +05:30
RS2007
adf70dc855 Return number of rows changed from Connection.execute 2025-07-20 07:27:38 +05:30
Glauber Costa
6506b3147d implement pragma application_id
Just for completeness, because it is easy.
2025-07-19 20:44:06 -05:00
Glauber Costa
024d79fc0d implement write side of pragma schema_version
It is insane that SQLite even allows this.
They actually don't if "defensive mode" is enabled:

"It is always safe to read the schema_version, but changing the
schema_version can cause problems. For this reason, attempts to change
the value of schema_version are a silent no-op when defensive mode is
enabled for a database connection.

Warning: Misuse of this pragma can result in database corruption."

We also update the compat table, which was not updated to reflect
the read version of this pragma being implemented.
2025-07-19 20:39:30 -05:00
Glauber Costa
4749ce95c1 implement Debug for Database
Very useful in printing data structures containing databases, like maps

Example output:

Connecting to Database { path: "sq.db", open_flags: OpenFlags(1), db_state: "initialized", mv_store: "none", init_lock: "unlocked", wal_state: "present", page_cache: "( capacity 100000, used: 0 )" }
2025-07-19 09:29:46 -05:00
Nils Koch
bab8001a9c use wasm32-wasip1 target instead of wasm32-wasi 2025-07-19 13:16:46 +01:00
Pekka Enberg
d1fdc7dbc8 Merge 'Simplify blocking operations – add io.block(fn) for IO trait implementors' from Levy A.
This PR make it simpler to block async operations instead of creating
sync equivalent functions. eg.: `get_page_size` and
`get_page_size_async`. All functions should be async by default, and
making them block should more explicit.
Also makes it easier to grep for top-level uses of blocking code without
needing to "go to definition".

Closes #2173
2025-07-19 12:20:07 +03:00
Pekka Enberg
16958f1a44 Turso 0.1.3-pre.3 2025-07-19 08:44:22 +03:00
Levy A.
0ea7849dca feat: IOExt utility trait 2025-07-19 01:40:42 -03:00
Jussi Saurio
67f3e54782 Merge 'sorter: fix sorter panic on SortedChunkIOState::WaitingForRead' from Jussi Saurio
Closes #2165
The following sequence of events is possible:
- init_chunk_heap() called
- flush() gets called, and all chunks start writing to disk
- chunk A status is WriteComplete, so chunk.read() gets called on chunk
A
- chunk A sets its status to WaitingForRead
- some other chunk B is still in WaitingForWrite status after flush()
- for this reason, init_chunk_heap() returns IOResult::IO
- init_chunk_heap() is called again
- we panic because chunk A is in WaitingForRead status
So - we just allow WaitingForRead status in init_chunk_heap() instead.
This panic was caught thanks to Pedro's IO latency enhancement to the
sim!

Reviewed-by: Iaroslav Zeigerman (@izeigerman)

Closes #2166
2025-07-18 23:32:46 +03:00
Pekka Enberg
fd6fda07ac Merge 'bindings/rust: Initial support for transactions API' from Diego Reis
Closes #2121
There are two important things to point out:
1. The support is incomplete since we yet don't support savepoints in
core.
2. When a txn drops we should call `_finish()` on it, but since async
drop is [unstable](https://github.com/rust-lang/rust/issues/126482) the
best solution that I came up was just forcing the user to explicitly
call `finish()` before any drops.

Closes #2151
2025-07-18 21:02:18 +03:00
Pekka Enberg
c2a8a6f178 Merge 'improve handling of double quotes' from Glauber Costa
I ended up hitting #1974 today and wanted to fix it. I worked with
Claude to generate a more comprehensive set of queries that could fail
aside from just the insert query described in the issue. He got most of
them right - lots of cases were indeed failing. The ones that were
gibberish, he told me I was absolutely right for pointing out they were
bad.
But alas. With the test cases generated, we can work on fixing it. The
place where the assertion was hit, all we need to do there is return
true (but we assert that this is indeed a string literal, it shouldn't
be anything else at this point).
There are then just a couple of places where we need to make sure we
handle double quotes correctly. We already tested for single quotes in a
couple of places, but never for double quotes.
There is one funny corner case where you can just select "col" from tbl,
and if there is no column "col" on the table, that is treated as a
string literal. We handle that too.
Fixes #1974

Closes #2152
2025-07-18 20:55:37 +03:00
Glauber Costa
cbdd5c5fc7 improve handling of double quotes
I ended up hitting #1974 today and wanted to fix it. I worked with
Claude to generate a more comprehensive set of queries that could fail
aside from just the insert query described in the issue. He got most of
them right - lots of cases were indeed failing. The ones that were
gibberish, he told me I was absolutely right for pointing out they were
bad.

But alas. With the test cases generated, we can work on fixing it. The
place where the assertion was hit, all we need to do there is return
true (but we assert that this is indeed a string literal, it shouldn't
be anything else at this point).

There are then just a couple of places where we need to make sure we
handle double quotes correctly. We already tested for single quotes in a
couple of places, but never for double quotes.

There is one funny corner case where you can just select "col" from tbl,
and if there is no column "col" on the table, that is treated as a
string literal. We handle that too.

Fixes #1974
2025-07-18 10:39:02 -05:00
Glauber Costa
523f8f9c67 add .dbconfig option
Currently ignored. The reason we are adding it is so that we have
an output that can fit in a single line. This is so we can use it in
tests, and have a predictable output pattern for both sqlite and turso.
2025-07-18 10:25:06 -05:00
Diego Reis
b3c8255032 Fix clippy warnings 2025-07-18 11:26:10 -03:00
Diego Reis
f9d024b68a bind/rust: Use Rusqlite compatible consumer API
Methods like commit, rollback and finish should "consume" a transaction,
so it cannot be used after calling any of them (Pretty neat, rust!)
2025-07-18 11:25:24 -03:00
Diego Reis
92cddb6437 bind/rust: Add more tests for Transaction 2025-07-18 11:25:24 -03:00
Diego Reis
0b96c24196 wip: Basic support for Transaction in Rust binding 2025-07-18 11:25:24 -03:00
Jussi Saurio
2aca28a86b Merge 'claude sonnet forgot to run clippy when implementing mcp server' from Jussi Saurio
Closes #2169
2025-07-18 17:19:59 +03:00
Jussi Saurio
1f55726acf claude sonnet forgot to run clippy when implementing mcp server 2025-07-18 17:15:39 +03:00
Pekka Enberg
81d386d6c4 Merge 'bindings/js: support iterator, and more kinds of params' from Mikaël Francoeur
This PR fixes 3 tests that check param binding and iteration.
-----
as part of https://github.com/tursodatabase/turso/issues/1900

Closes #2097
2025-07-18 16:25:01 +03:00
Pekka Enberg
ac157f6dcc Merge 'Add a native MCP server' from Glauber Costa
The SQLite command line has facilities to ingest things like csv, and
other formats. But here we are, in 2025, and I asked Claude if Turso's
CLI should, in the same vein, have a native MCP server.
Claude told me: "You're absolutely right!" "That's a great insight!"
"That's a fantastic idea!" and then proceeded to help me with the
boilerplate for this beautiful server.
Rust has a crate, mcp_server, that implements an mcp_server trait.
However, that depends on Tokio, and I think that would bloat our binary
too much.
I have also considered implementing an MCP server that operates on a
directory and allows to list many SQLite files, but figured that would
be a good job for a more advanced and specialized server, not for the
one that comes by default with the CLI. Let's go for simple.

Closes #2148
2025-07-18 16:05:57 +03:00
Jussi Saurio
4d15725b6f sorter: fix sorter panic on SortedChunkIOState::WaitingForRead
The following sequence of events is possible:

- init_chunk_heap() called
- chunk A status is WriteComplete, so chunk.read() gets called on chunk A
- some other chunk B is in WaitingForWrite status after flush()
- init_chunk_heap() returns IOResult::IO
- init_chunk_heap() is called again
- we panic because chunk A is in WaitingForRead status

So - we just allow WaitingForRead status in init_chunk_heap() instead.

This panic was caught thanks to Pedro's IO latency enhancement to the sim!
2025-07-18 14:18:51 +03:00
Jussi Saurio
bca1e56f49 Merge 'Remove find_cell, allow overwrite of index interior cell' from Jussi Saurio
Currently we are using `find_cell` which does a binary search on every
insert, even if the cursor is already in the correct place.
1. Remove `find_cell` and use `seek` when inserting instead of
`move_to`.
2. After removing `find_cell`, we now need to be more mindful of when we
do actually require a seek before insertion. This is signified by the
addition of `InsertFlags::REQUIRE_SEEK`. Previously some inserts worked
by accident because we always happened to be on the correct page --
`find_cell()´ only binary searches a single page.
3. After removing `find_cell` we also need to call `next()` after
`Insn::NewRowid`, because `NewRowid` positions us at the old maximum
rowid, and we need to be positioned after it.
4. After removing `find_cell` we also need to leave the cursor
positioned correctly during seeks where we don't find a match.
5. Allow overwrite of an index interior cell, which Closes #1975.

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

Closes #1988
2025-07-18 14:09:39 +03:00
Jussi Saurio
40df1725c5 Fix restore_context() not advancing when required 2025-07-18 13:48:23 +03:00
Jussi Saurio
2a2ab16c52 fix moved_before handling in cursor.insert 2025-07-18 13:48:23 +03:00
Jussi Saurio
28c050dd27 seek before insert to ensure correct location in fuzz test 2025-07-18 13:48:23 +03:00
Jussi Saurio
fdeb15bb9d btree/delete: rightmost_cell_was_dropped logic is not needed since a) if we balance, we seek anyway, and b) if we dont balance, we retreat anyway 2025-07-18 13:48:23 +03:00
Jussi Saurio
55151a8061 Fix cases where Insn::Insert needs to seek to ensure correct insertion 2025-07-18 13:48:23 +03:00
Jussi Saurio
9ee6988fc5 VDBE: NewRowid needs to call next() in case op_not_exists() is not called afterwards 2025-07-18 13:48:23 +03:00
Jussi Saurio
4f0ef663e2 btree: add target cell tracking for EQ seeks 2025-07-18 13:48:23 +03:00
Jussi Saurio
2b23495943 btree: allow overwriting index interior cell 2025-07-18 13:48:23 +03:00
Jussi Saurio
e33ff667dc btree: use seek() when inserting -- replaces find_cell() 2025-07-18 13:48:23 +03:00
Jussi Saurio
9201030e67 Ephemeral UNION indexes don't need to be UNIQUE 2025-07-18 13:48:23 +03:00
Jussi Saurio
f7068ce23a Merge 'Fix parent page stack location after interior node replacement' from Jussi Saurio
Another fix extracted from running simulations on the #1988 branch.
## What
When interior cell replacement happens as described in #2108, we use the
`cursor.prev()` method to locate the largest key in the left subtree.
There was an error during backwards traversal in the `get_prev_record()`
method where the parent's cell index was set as `i32::MAX` but not
properly set to `cell_count + 1` (indicating that rightmost pointer has
been visited).
This meant that if the child page we took the replacement cell from
underflowed and needed balancing, the parent page would now have
`i32::MAX` as its cell index and crash at the point where we determine
based on the parent page which page is going to undergo balancing.
## Fix
This PR fixes the issue by setting the cell index of the parent properly
when visiting the rightmost child. This way the balance procedure will
correctly detect that the rightmost child page is going to undergo
balancing.
### Trivia
The reason `i32::MAX` is used is that the cell count of the page is not
necessarily known at the time it is pushed to the stack.

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

Closes #2163
2025-07-18 13:48:06 +03:00
Jussi Saurio
aeab89bd75 Fix parent page stack location after interior node replacement
Another fix extracted from running simulations on the #1988 branch.

When interior cell replacement happens as described in #2108,
we use the `cursor.prev()` method to locate the largest key in the
left subtree.

There was an error during backwards traversal in the `get_prev_record()`
method where the parent's cell index was set as `i32::MAX` but not properly
set to `cell_count + 1` (indicating that rightmost pointer has been visited).

The reason `i32::MAX` is used is that the cell count of the page is not
necessarily known at the time it is pushed to the stack.

This PR fixes the issue by setting the cell index of the parent properly
when visiting the rightmost child.
2025-07-18 13:30:01 +03:00
Jussi Saurio
b1ebc1c82f Merge 'sim: show seed in 'execute_interaction()' trace' from Jussi Saurio
This helps e.g. when you hit some infinite loop

Closes #2161
2025-07-18 12:27:48 +03:00
Jussi Saurio
086a269a65 Merge 'sim: change --disable-create-index flag to --enable-create-index (default false)' from Jussi Saurio
Closes #2160
2025-07-18 12:27:35 +03:00
Jussi Saurio
0af2443061 Merge 'sim: add order by to some queries' from Jussi Saurio
Closes #2159
2025-07-18 12:27:30 +03:00
Pekka Enberg
02f4bc39b3 Merge 'Reanimate MVCC' from Pekka Enberg
Bit-rot happened. Bring MVCC back from the dead.

Closes #2136
2025-07-18 11:22:49 +03:00
Jussi Saurio
687d126e25 sim: change --disable-create-index flag to --enable-create-index (default false) 2025-07-18 11:21:24 +03:00
Jussi Saurio
5b2d7315eb sim: show seed in 'execute_interaction()' trace 2025-07-18 11:21:04 +03:00
Jussi Saurio
9722aab8a1 clappy 2025-07-18 11:01:57 +03:00
Jussi Saurio
347a9152a6 Merge 'Replace verbose IO Completion methods with helpers' from Preston Thorpe
one of the last remnants of some original verbosity

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

Closes #2156
2025-07-18 10:52:17 +03:00