Commit Graph

7023 Commits

Author SHA1 Message Date
Nikita Sivukhin
2e23230e79 extend raw WAL API with few more methods
- try_wal_watermark_read_page - try to read page from the DB with given WAL watermark value
- wal_changed_pages_after - return set of unique pages changed after watermark WAL position
2025-08-04 16:55:50 +04:00
Nikita Sivukhin
83b1e99a61 fix compilation 2025-08-04 12:53:07 +04:00
Nikita Sivukhin
0adb40534c hind dangerous methods behind conn_raw_api feature 2025-08-04 12:40:28 +04:00
Pekka Enberg
deec70e541 Merge 'Improve SQLite3 TCL test suite' from Pekka Enberg
Add more stubs in tester.tcl so that the test suite does not bail out
early.

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

Closes #2405
2025-08-04 08:43:14 +03:00
Pekka Enberg
ca14799da5 Merge 'Make completions idempotent' from Preston Thorpe
Closes #2417
2025-08-04 08:42:42 +03:00
Pekka Enberg
3691b51039 Merge 'perf/btree: skip seek in move_to_rightmost() if we are already on rightmost page' from Jussi Saurio
## Background
When we get a new rowid using `op_new_rowid()`, we move to the end of
the btree to look at what the maximum rowid currently is, and then
increment it by one.
This requires a btree seek.
## Problem
If we were already on the rightmost page, this is a lot of unnecessary
work, including potentially a few page reads from disk (although to be
fair the ancestor pages are very likely to be in cache at this point.)
## Fix
Cache the rightmost page id whenever we enter it in
`move_to_rightmost()`, and invalidate it whenever we do a balancing
operation.
## Local benchmark results
```sql
Insert rows in batches/limbo_insert_1_rows
                        time:   [23.333 µs 27.718 µs 35.801 µs]
                        change: [-7.7924% +0.8805% +12.841%] (p = 0.91 > 0.05)
                        No change in performance detected.
Insert rows in batches/limbo_insert_10_rows
                        time:   [38.204 µs 38.381 µs 38.568 µs]
                        change: [-8.7188% -7.4786% -6.1955%] (p = 0.00 < 0.05)
                        Performance has improved.
Insert rows in batches/limbo_insert_100_rows
                        time:   [158.39 µs 165.06 µs 178.37 µs]
                        change: [-21.000% -18.789% -15.666%] (p = 0.00 < 0.05)
                        Performance has improved.

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

Closes #2409
2025-08-04 08:41:51 +03:00
PThorpe92
79629daff4 Make completions idempotent 2025-08-02 21:48:39 -04:00
Jussi Saurio
130e1f80ea fix/vdbe: call seek_to_last() only once in op_new_rowid 2025-08-02 14:18:58 +03:00
Jussi Saurio
63a5ef596b perf/btree: skip seek in move_to_rightmost() if we are already on rightmost page 2025-08-02 13:56:59 +03:00
Pekka Enberg
a4dcbeb392 Update PERF.md 2025-08-02 13:37:42 +03:00
Jussi Saurio
3b0c8b08fe Merge 'perf/pager: dont clear page cache on commit' from Jussi Saurio
This should be safe to do as:
1. page cache is private per connection
2. since this connection wrote the flushed pages/frames, they are up to
date from its perspective
3. multiple concurrent statements inside one connection are not
snapshot-transactional even in sqlite

Reviewed-by: Pekka Enberg <penberg@iki.fi>

Closes #2407
2025-08-02 13:35:57 +03:00
Jussi Saurio
4497d22d3f perf/pager: dont clear page cache on commit 2025-08-02 13:09:36 +03:00
Pekka Enberg
5037e2dc0d testing/sqlite3: Update all.test 2025-08-02 13:00:18 +03:00
Pekka Enberg
779b8e0149 testing/sqlite3: Import more join test cases 2025-08-02 12:59:11 +03:00
Pekka Enberg
c7497d55b6 testing/sqlite3: Disable select9.test
...it seems to run forever.
2025-08-02 12:59:11 +03:00
Pekka Enberg
a380e0775d testing/sqlite3: Improve tester.tcl
Improve tester.tcl by adding stubs so that we can run more of the test
suite without the test harness giving up.
2025-08-02 12:59:11 +03:00
Pekka Enberg
bca9994cf6 Merge 'Rename liblimbo_sqlite3 to libturso_sqlite3' from Pekka Enberg
Closes #2403
2025-08-02 12:34:19 +03:00
Pekka Enberg
12455c6531 Merge 'core: Fold HeaderRef to pager module' from Pekka Enberg
Closes #2401
2025-08-02 12:34:13 +03:00
Pekka Enberg
4aea9372bd Rename liblimbo_sqlite3 to libturso_sqlite3 2025-08-02 11:24:40 +03:00
Pekka Enberg
2c05a3e787 Merge 'perf/vdbe: remove eager cloning in op_comparison' from Jussi Saurio
Shaves off about 100-200ms of runtime from TPC-H `19.sql`

Closes #2385
2025-08-02 10:01:47 +03:00
Pekka Enberg
598fdade3e core: Fold HeaderRef to pager module 2025-08-02 09:50:25 +03:00
Pekka Enberg
9a82e269cd Merge 'Update cargo-dist to the latest official version' from Hiroaki Yutani
https://github.com/tursodatabase/turso/pull/1256 switched cargo-dist to
Astral's forked version, but, recently, the official repository got a
new maintainer and started to be maintained again.
Their latest release, [v0.29.0](https://github.com/axodotdev/cargo-
dist/releases/tag/v0.29.0), now includes the features originally added
to Astral's version. So, probably it's a good time to switch back to the
official cargo-dist. That said, as there's no significant changes from
Astral's version, it's also fine to hold the current one.

Closes #2398
2025-08-02 09:46:26 +03:00
Jussi Saurio
43c1afe4b6 Merge 'bindings/rust: Enhance API by removing verbosity' from Diego Reis
While working on #2151 I saw myself forced to do things like:
```rust
assert_eq!(
                6,
                *result
                    .next()
                    .await?
                    .unwrap()
                    .get_value(0)?
                    .as_integer()
                    .unwrap()
            );
```
Just to get a simple value from a row, now with this PR users can just
do:
```rust
assert_eq!(6, result.get::<i32>(0)?);
```
(Thanks libsql devs, this is so much better!)

Closes #2377
2025-08-02 09:39:27 +03:00
Jussi Saurio
c6b178483b Merge 'io_uring: setup plumbing for Fixed opcodes' from Preston Thorpe
This PR by itself is uninteresting and doesn't do anything. But I am
heavily trying to avoid massive PR's, and this is very merge-able
😄

Closes #2396
2025-08-02 09:37:48 +03:00
Jussi Saurio
be1456f7cb Merge 'use state machine for NoConflict opcode' from Mikaël Francoeur
This will save some work when yielding to IO. Previously, on every
invocation, if the record was a packed record, we parsed it and iterated
through the values to check for nulls. Now, the pre-seeking work is done
only once.

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

Closes #2394
2025-08-02 09:37:00 +03:00
Jussi Saurio
37a565021e Merge 'state_machine: remove State associated type' from Pere Diaz Bou
Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #2395
2025-08-02 09:36:43 +03:00
Preston Thorpe
97b236f217 Merge 'Fix numeric overflow in numeric string parsing in logical comparision' from
Closes #2077-
This PR fixes an integer overflow bug that causes results from Turso to
differ from SQLite.
-Commit 1: Fixes incorrect logic that failed to detect integer overflow
when parsing long numeric strings.
-Commit 2: Handles the case where a parsed numeric string is stored as a
float and classified as PureInteger, but lies outside the integer range.
Previously, `parsed_value.as_integer()` would return None, causing Turso
to fall back to text comparison against numeric values. This caused
**another** erroneous result, as shown below.
`$> SELECT (-104614899632619 || 45597) > CAST(0 AS NUMERIC); -- tursodb
= 1(wrong), sqlite = 0`
 Now, if Turso fails to convert a very long numeric string to an
integer, it tries to convert it to a float. This is in line with the
`static void applyNumericAffinity` function in sqlite3
**Before**
<img width="623" height="238" alt="Screenshot 2025-08-01 at 12 11 49 PM"
src="https://github.com/user-attachments/assets/796d6ff6-768b-40ef-
ac83-e0c55fff6bd9" />
**After**
`SELECT (104614899632619 || 45597) > CAST(0 AS NUMERIC); -- tursodb = 1,
sqlite = 1`
`SELECT (-104614899632619 || 45597) > CAST(0 AS NUMERIC); -- tursodb =
0, sqlite = 0`

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

Closes #2397
2025-08-01 21:39:30 -04:00
rajajisai
d2d7adff9e Including test for parsing large numeric strings as number when an operand is numerican when doing logical comparision 2025-08-01 16:30:32 -07:00
Mikaël Francoeur
81412b4a17 use state machine for NoConflict opcode 2025-08-01 17:29:57 -04:00
Hiroaki Yutani
b0de38bbce Update cargo-dist to the latest official version 2025-08-02 04:35:52 +09:00
rajajisai
f6d43df46f Merge branch 'tursodatabase:main' into issue/2077 2025-08-01 15:20:36 -04:00
Diego Reis
31eb4403ad Add integration tests for query_row and get 2025-08-01 16:00:32 -03:00
Diego Reis
8a47b9d5a4 Address PR's comments 2025-08-01 16:00:32 -03:00
Diego Reis
572d3bd4ce Simplify Rust API verbosity by implementing Row.get() and
Statement.query_row()
2025-08-01 16:00:32 -03:00
Diego Reis
adb81dd6ce Separate Row and Rows in its own file 2025-08-01 16:00:32 -03:00
Diego Reis
d8af28ddf0 Implement FromValue to common Rust's types
One step further to help to simplify the API for users.

This is in core and not in Rust bind because, in core,
this could benefit a broader set of users/developers
2025-08-01 16:00:30 -03:00
rajajisai
d09dd4170b Format code 2025-08-01 11:59:57 -07:00
Preston Thorpe
15e43185bb Merge 'Single quotes inside a string literal have to be doubled in ' from Diego Reis
Close #2390
Single quotes inside a string literal have to be doubled

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

Closes #2392
2025-08-01 14:57:46 -04:00
PThorpe92
b8ed4358f1 register buffers sparse on ring initiate to support fixed operations 2025-08-01 14:56:43 -04:00
PThorpe92
9289dd7e9a Implement register_fixed_buffer for io_uring IO backend 2025-08-01 14:55:35 -04:00
PThorpe92
3048e4fa97 Add optional register_fixed_buffer method to IO trait 2025-08-01 14:54:26 -04:00
Mikaël Francoeur
444a7bb5ac wrap doc 2025-08-01 14:53:46 -04:00
Pere Diaz Bou
f9e1d9bb40 state_machine: remove State associated type 2025-08-01 20:04:27 +02:00
rajajisai
30c059483e Parse value as float if it cannot be parsed as integer(when the value cannot fit in i64) 2025-08-01 10:49:40 -07:00
rajajisai
7e84148883 Fix integer overflow check in number parser 2025-08-01 10:10:02 -07:00
Pekka Enberg
d161c2652c Merge 'core/mvcc: Move commit_txn() to generic state machinery ' from Pere Diaz Bou
Unfortunately it seems we are never reaching the point to remove state
machines, so might as well make it easier to make.
There are two points that must be highlighted:
1. There is a `StateTransition` trait implemented like:
```rust
pub trait StateTransition {
    type State;
    type Context;

    fn transition<'a>(&mut self, context: &Self::Context) ->
Result<TransitionResult>;
    fn finalize<'a>(&mut self, context: &Self::Context) -> Result<()>;
    fn is_finalized(&self) -> bool;
}
```
where there exists `transition` which tries to move state forward, and
`finalize` which marks the state machine as "finalized" so that **no
other call to finalize will forward the state and it will panic instead.
2. Before, we would store the state of a state machine inside the
callee's struct, but I'm proposing we do something different where the
callee will return the state machine and the caller will be responsible
of advancing it. This way we don't need to track many reset operations
in case of failures or rollbacks, and instead we could simply drop a
state machine and all other nested state machines will drop in a
cascade.

Closes #2384
2025-08-01 19:28:16 +03:00
Pekka Enberg
9a1ead44f1 Merge 'bindings/javascript: Reduce VM/native crossing overhead' from Pekka Enberg
Before:
```
penberg@vonneumann perf % node perf-turso.js
cpu: Apple M1
runtime: node v22.16.0 (arm64-darwin)

benchmark                            time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------- -----------------------------
• Statement
----------------------------------------------------------------------- -----------------------------
Statement.get() bind parameters   1'525 ns/iter   (1'482 ns … 1'720 ns)  1'534 ns  1'662 ns  1'720 ns

summary for Statement
  Statement.get() bind parameters
penberg@vonneumann perf % bun perf-turso.js
cpu: Apple M1
runtime: bun 1.2.15 (arm64-darwin)

benchmark                            time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------- -----------------------------
• Statement
----------------------------------------------------------------------- -----------------------------
Statement.get() bind parameters   1'198 ns/iter   (1'157 ns … 1'495 ns)  1'189 ns  1'456 ns  1'495 ns

summary for Statement
  Statement.get() bind parameters
```
After:
```

benchmark                            time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------- -----------------------------
• Statement
----------------------------------------------------------------------- -----------------------------
Statement.get() bind parameters   1'206 ns/iter   (1'180 ns … 1'402 ns)  1'208 ns  1'365 ns  1'402 ns

summary for Statement
  Statement.get() bind parameters
penberg@vonneumann perf % bun perf-turso.js
cpu: Apple M1
runtime: bun 1.2.15 (arm64-darwin)

benchmark                            time (avg)             (min … max)       p75       p99      p999
----------------------------------------------------------------------- -----------------------------
• Statement
----------------------------------------------------------------------- -----------------------------
Statement.get() bind parameters   1'019 ns/iter     (980 ns … 1'360 ns)  1'005 ns  1'270 ns  1'360 ns

summary for Statement
  Statement.get() bind parameters
```

Closes #2391
2025-08-01 19:18:33 +03:00
Pekka Enberg
f1794b6270 bindings/javascript: Add INSERT benchmark too 2025-08-01 18:17:13 +03:00
Diego Reis
7c70ac2c4a Fix #2390
Single quotes inside a string literal have to be doubled
2025-08-01 11:37:13 -03:00
Pekka Enberg
d4633415a7 Merge 'Enable indexes by default' from Jussi Saurio
Enables indexes by default in Rust and Python bindings + the CLI, while
leaving the feature flag in place.
Comments out a single ALTER TABLE test that fails due to #2390

Closes #2389
2025-08-01 17:36:35 +03:00