Commit Graph

3483 Commits

Author SHA1 Message Date
Jussi Saurio
cff4d7e16d Merge 'BTreeTable::to_sql: wrap special column names in brackets' from Nils Koch
Closes #2055

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

Closes #2126
2025-07-21 00:22:49 +03:00
Jussi Saurio
81d8dc7e3d Merge 'Fix column order for multi-row insertion' from Nikita Sivukhin
Column order handled incorrectly for multi-rows insert case
```sql
turso> CREATE TABLE t(x, y, z);
turso> INSERT INTO t(z, x) VALUES (1, 2), (3, 4);
turso> SELECT * FROM t;
┌───┬───┬───┐
│ x │ y │ z │
├───┼───┼───┤
│   │ 2 │   │
├───┼───┼───┤
│   │ 4 │   │
└───┴───┴───┘
```

Closes #2109
2025-07-21 00:02:43 +03:00
Jussi Saurio
9936748132 Merge 'Avoid redundant decoding of record headers when reading sorted chunk files' from Iaroslav Zeigerman
Currently, each record header is decoded at least twice: once to
determine the record size within the read buffer (in order to construct
the `ImmutableRecord` instance), and again later when decoding the
record for comparison. This redundant decoding can have a noticeable
negative impact on performance when records are wide (eg. contain
multiple columns).
This update modifies the (de)serialization format for sorted chunk files
by prepending a record size varint to each record payload. As a result,
only a single varint needs to be decoded to determine the record size,
eliminating the need to decode the full record header during reads.

Closes #2176
2025-07-20 23:54:54 +03:00
Nils Koch
05a9acf8c5 wrap special column names with [] in BTreeTable to_sql 2025-07-20 21:20:59 +01:00
Pere Diaz Bou
90f71ccd4e Merge 'fix opcodes missing a database register' from Glauber Costa
Two of the opcodes we implement (OpenRead and Transaction) should have
an opcode specifying the database to use, but they don't.
Add it, and for now always use 0 (the main database).

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

Closes #2191
2025-07-20 21:01:35 +02:00
Jussi Saurio
010fb1c12a fix/pager/cacheflush: cacheflush shouldn't commit 2025-07-20 21:18:45 +03:00
Glauber Costa
65312baee6 fix opcodes missing a database register
Two of the opcodes we implement (OpenRead and Transaction) should have
an opcode specifying the database to use, but they don't.

Add it, and for now always use 0 (the main database).
2025-07-20 12:27:26 -05:00
Nikita Sivukhin
e733365057 fix code generation for insert command 2025-07-20 14:22:16 +04:00
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
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
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
Iaroslav Zeigerman
10a848fbc5 address nit 2025-07-19 18:40:43 +02: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
Levy A.
0ea7849dca feat: IOExt utility trait 2025-07-19 01:40:42 -03:00
Iaroslav Zeigerman
5d47502e3a Avoid redundant decoding of record headers when reading sorted chunk files 2025-07-19 06:08:27 +02: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
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
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
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
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
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
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
Jussi Saurio
bbd7f32d80 Merge 'Fix rollback for TxErrors' from Diego Reis
Fixes #2153.
Not so sure if SQLite doesn't rollback in more cases, we should
definitively check this out.

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

Closes #2154
2025-07-18 10:49:29 +03:00
Jussi Saurio
7e1755ac6f Merge 'Use pread and pwrite in run_once' from Ihor Andrianov
pread and pwrite is usually less instructions then seek and read. Also
added possibility for io to retry if AGAIN error happens. And made write
to wait for Event::writable

Reviewed-by: Preston Thorpe (@PThorpe92)
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #2010
2025-07-18 10:48:26 +03:00
Iaroslav Zeigerman
28ff170e14 improve sorter settings in the fuzz test 2025-07-18 07:41:15 +02:00
Iaroslav Zeigerman
76e748146b rebase 2025-07-18 07:30:08 +02:00
Iaroslav Zeigerman
f6f1d076da verify that records remain unchanged after sorting 2025-07-18 07:28:37 +02:00
Iaroslav Zeigerman
d9751212d7 make a fuzz sorter test 2025-07-18 07:28:37 +02:00
Iaroslav Zeigerman
20bdbd5ca5 address suggestions 2025-07-18 07:28:37 +02:00
Iaroslav Zeigerman
edf2be1432 fix conflicts 2025-07-18 07:28:37 +02:00
Iaroslav Zeigerman
6a609398fe cosmetic fix 2025-07-18 07:28:37 +02:00
Iaroslav Zeigerman
a88b828268 Fix clippy 2025-07-18 07:28:36 +02:00
Iaroslav Zeigerman
fd042ac4c8 Use IOResult insteaed of CursorResult 2025-07-18 07:28:36 +02:00
Iaroslav Zeigerman
78f3bf3475 Core: Introduce external sorting 2025-07-18 07:28:36 +02:00
Diego Reis
9ade79b3ad Do not rollback in TxError
Fixes #2153. Not so sure if SQLite doesn't rollback in more cases, we
should definitively check this out.
2025-07-18 01:11:51 -03:00