Commit Graph

141 Commits

Author SHA1 Message Date
Nikita Sivukhin
0da3b4bfd3 fix after rebase 2025-10-28 11:27:35 +04:00
Nikita Sivukhin
180713d32a plug IndexMethod into optimizer 2025-10-28 11:27:35 +04:00
Jussi Saurio
d993ac8157 Merge 'index_method: implement basic trait and simple toy index' from Nikita Sivukhin
This PR adds `index_method` trait and implementation of toy sparse
vector index.
In order to make PR more lightweight - for now index methods are not
deeply integrated into the query planner and only necessary components
are added in order to make integration tests which uses `index_method`
API directly to work.
Primary changes introduced in this PR are:
1. `SymbolTable` extended with `index_methods` field and builtin
extensions populated with 2 native indices: `backing_btree` and
`toy_vector_sparse_ivf`
2. `Index` struct extended with `index_method` field which holds
`IndexMethodAttachment` constructed for the table with given parameters
from `IndexMethod` "factory" trait
The toy index implementation store inverted index pairs `(dimension,
rowid)` in the auxilary BTree index. This index uses special
`backing_btree` index_method which marked as `backing_btree: true` and
treated in a special way by the db core: this is real BTree index which
is not managed by the tursodb core and must be managed by index_method
created it (so it responsible for data population, creation, destruction
of this btree).

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

Closes #3846
2025-10-28 07:01:36 +02:00
Jussi Saurio
f288dfd3d0 TableMask: take tables referenced in subqueries into account
This influences valid potential join orders.
2025-10-27 16:10:49 +02:00
Jussi Saurio
580333ddd3 Add NonFromClauseSubquery struct and add a Vec of them to SelectPlan 2025-10-27 16:01:39 +02:00
Jussi Saurio
5eb74ce8e6 AST: Add Expr::SubqueryResult variant and enum SubqueryType 2025-10-27 16:01:39 +02:00
Nikita Sivukhin
05f0ee6a72 add more integration in order to properly skip backing_btree index_method 2025-10-27 17:00:26 +04:00
Jussi Saurio
691dce6b8a Make decision about UpdatePlan::ephemeral_plan _after_ optimizer
An ephemeral table is required if the b-tree key of the table (rowid)
or the index (index key) is affected by the UPDATE.
2025-10-14 14:17:28 +03:00
Jussi Saurio
bc80ac1754 require &mut ProgramBuilder argument in optimize_plan()
this will be used for ephemeral plan construction for UPDATE in
a later commit.
2025-10-14 12:18:13 +03:00
Jussi Saurio
59a1c2ae2e Disallow joining more than 63 tables
Returns an error instead of panicing
2025-10-13 13:30:03 +03:00
Jussi Saurio
74e04634aa Fix incorrectly using an equality constraint twice for index seek
Prevents something like `WHERE x = 5 AND x = 5` from becoming a two
component index key.

Closes #3656
2025-10-10 13:19:19 +03:00
Nikita Sivukhin
4313f57ecb Optimize range scans 2025-10-09 11:47:41 +03:00
PThorpe92
ae975afe49 Remove unnecessary FK resolution on schema parsing 2025-10-07 16:45:16 -04:00
Jussi Saurio
58ea9e4c3c clippy 2025-10-02 21:49:33 +03:00
Jussi Saurio
edfe0cb4fe Collate: prevent using an index if collation sequences don't match 2025-10-02 21:49:33 +03:00
Jussi Saurio
63f9913dbb Clear WhereTerm 'from_outer_join' state when LEFT JOIN is optimized to INNER JOIN
Closes #2470

In a query like `SELECT * FROM t LEFT JOIN s ON t.a=s.a WHERE s.a = 'foo'` we can
remove the LEFT JOIN because NULL values will be equal to 'foo'. In fact, we have
this optimization already.

However, there was a dumb bug where `WhereTerm`s involving this join still retained
their `from_outer_join` state, resulting in forcing the evaluation of those terms
at the original join index, which results in completely wrong bytecode if the join
optimizer decides to reorder the join as `s JOIN t` instead. Effectively it will
evaluate `t.a=s.a` after table `s` is open but table `t` is not open yet.

This PR fixes that issue by clearing `from_outer_join` properly from the relevant
`WhereTerm`s.
2025-10-01 00:33:22 +03:00
Nikita Sivukhin
a32ed53bd8 remove optimization
- even if index search will return only 1 row - it will call next in the loop - and we incorrecty can process same row values multiple times
- the following query failed with this optimization:

turso> CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT, k TEXT, c0 INT);
turso> CREATE UNIQUE INDEX idx_p1_0 ON t(c0);
turso> insert into t values (null, 'uu', -1);
turso> insert into t values (null, 'uu', -2);
turso> UPDATE t SET c0 = NULL WHERE c0 = -1;
turso> SELECT * FROM t
┌────┬────┬────┐
│ id │ k  │ c0 │
├────┼────┼────┤
│  1 │ uu │    │
├────┼────┼────┤
│  2 │ uu │    │
└────┴────┴────┘
2025-09-30 16:37:41 +04:00
Diego Reis
90f4d69774 fix(3301): Remove identifier assert assumption
Not every identifier should be double-quoted
2025-09-29 22:33:21 -03:00
Nikita Sivukhin
f3f9219795 completely remove usage of enum variants 2025-09-26 13:01:49 +04:00
Pavan Nambi
f1ac855441 Merge branch 'main' into cdc_fail_autoincrement 2025-09-22 21:11:26 +05:30
Jussi Saurio
c0fc2ad234 fix optimizer tests 2025-09-22 10:18:03 +03:00
Jussi Saurio
eada24b508 Store in-memory index definitions most-recently-seen-first
This solves an issue where an INSERT statement conflicts with
multiple indices. In that case, sqlite iterates the linked list
`pTab->pIndex` in order and handles the first conflict encountered.
The newest parsed index is always added to the head of the list.

To be compatible with this behavior, we also need to put the most
recently parsed index definition first in our indexes list for a given
table.
2025-09-22 10:11:50 +03:00
Pavan Nambi
47194d7658 Merge branch 'tursodatabase:main' into cdc_fail_autoincrement 2025-09-21 16:03:38 +05:30
PThorpe92
21f6455190 Fix clippy warnings and tests 2025-09-20 14:38:50 -04:00
PThorpe92
635273f782 Prevent using a partial index as a scan driver 2025-09-20 14:38:48 -04:00
PThorpe92
51f970a263 Support partial indexes in INSERT/UPDATE/DELETE 2025-09-20 14:38:48 -04:00
PThorpe92
ffd1f87682 Centralize most of the AST traversal by binding columns and rewriting exprs together 2025-09-18 18:38:03 -04:00
Pavan-Nambi
020921f803 Merge remote-tracking branch 'upstream/main' into cdc_fail_autoincrement 2025-09-18 19:27:19 +05:30
Preston Thorpe
bcafb288ad Merge 'Fix is_nonnull returns true on 1 / 0' from Lâm Hoàng Phúc
turso:
```sh
turso> CREATE TABLE t (x PRIMARY KEY, y, z);
turso> INSERT INTO t VALUES (37, -70, -196792117);
turso> SELECT * FROM t WHERE  (1 / 0) >= -3289742039 < t.x;
┌────┬─────┬────────────┐
│ x  │ y   │ z          │
├────┼─────┼────────────┤
│ 37 │ -70 │ -196792117 │
└────┴─────┴────────────┘
turso>
```
sqlite:
```sh
sqlite> CREATE TABLE t (x PRIMARY KEY, y, z);
sqlite> INSERT INTO t VALUES (37, -70, -196792117);
sqlite> SELECT * FROM t WHERE  (1 / 0) >= -3289742039 < t.x;
sqlite>
```
related: https://github.com/tursodatabase/turso/actions/runs/17765571409
/job/50488042583?pr=3147#step:8:855

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Reviewed-by: Preston Thorpe <preston@turso.tech>

Closes #3167
2025-09-17 06:55:55 -04:00
TcMits
6606bf12d3 is_nonnull returns true on 1 / 0 2025-09-17 14:50:15 +07:00
Piotr Rzysko
9ff2133ff2 Rewrite window function expressions in the optimizer
Currently, this is effectively a no-op because, at the optimization
stage, window function expressions are in the form
win_func(subquery_column1, subquery_column2, ...).

Nevertheless, expressions are rewritten to maintain consistency with
aggregates, which also hold cloned expressions from sources like result
columns. This ensures future changes in the optimizer won’t break window
function handling.
2025-09-13 11:12:44 +02:00
Piotr Rzysko
6224cdbbd3 Support WalkControl in walk_expr_mut
Now walk_expr_mut can use WalkControl to skip parts of the expression
tree. This makes it consistent with walk_expr.
2025-09-13 10:49:14 +02:00
Pavan-Nambi
7191f1cc1c Merge remote-tracking branch 'upstream/main' into cdc_fail_autoincrement 2025-09-12 15:17:12 +05:30
Jussi Saurio
e3bd00883b Fix creation of automatic indexes
indexes with the naming scheme "sqlite_autoindex_<tblname>_<number>"
are automatically created when a table is created with UNIQUE or
PRIMARY KEY definitions.

these indexes must map to the table definition SQL in definition order,
i.e. sqlite_autoindex_foo_1 must be the first instance of UNIQUE or
PRIMARY KEY and so on.

this commit fixes our autoindex creation / parsing so that this invariant
is upheld.
2025-09-11 14:11:30 +03:00
Jussi Saurio
e0ca0cf8af Enable access path optimizer for DELETE 2025-09-10 14:54:51 +03:00
Pavan-Nambi
6728384b47 Merge remote-tracking branch 'origin/main' into cdc_fail_autoincrement 2025-09-10 07:30:22 +05:30
Pavan-Nambi
b833e71c20 inserting ain't working
hell yeah

concurrency tests passing now woosh

finally write tests passed

Most of the cdc tests are passing yay

autoincremeent draft

remove shared schema code that broke transactions

sequnce table should reset if table is drop

fmt

fmt

fmt
2025-09-09 20:07:52 +05:30
Jussi Saurio
2d1d284279 optimizer: convert outer join to inner join if possible 2025-09-08 23:21:34 +03:00
Jussi Saurio
f6ede79de7 Do not consume non-join WHERE terms in left joins 2025-09-08 09:35:11 +03:00
TcMits
b0f4dd49d5 use match_ignore_ascii_case macro 2025-09-03 12:01:52 +07:00
TcMits
4ddfdb2a62 finish 2025-08-27 14:58:35 +07:00
TcMits
50bdaec6d0 merge main 2025-08-27 13:36:54 +07:00
Pekka Enberg
26ba09c45f Revert "Merge 'Remove double indirection in the Parser' from Pedro Muniz"
This reverts commit 71c1b357e4, reversing
changes made to 6bc568ff69 because it
actually makes things slower.
2025-08-26 14:58:21 +03:00
pedrocarlo
d3240844ec refactor Core to remove the double indirection 2025-08-25 22:59:31 -03:00
Glauber Costa
38def26704 Add expr_compiler
To be used in DBSP-based projections. This will compile an expression
to VDBE bytecode and execute it.

To do that we need to add a new type of Expression, which we call a
Register.

This is a way for us to pass parameters to a DBSP program which will be
not columns or literals, but inputs from the DBSP deltas.
2025-08-25 17:48:17 +03:00
TcMits
399f10fe9a refactor parser fmt 2025-08-23 19:16:26 +07:00
Levy A.
4ba1304fb9 complete parser integration 2025-08-21 15:23:59 -03:00
Levy A.
186e2f5d8e switch to new parser 2025-08-21 15:19:16 -03:00
Jussi Saurio
5da76c9125 Allow index in UPDATE for point queries (i.e. max 1 row affected) 2025-08-14 15:58:01 +03:00
Jussi Saurio
cd3b4bccd3 Fix UPDATE: Do not use an index for iteration if that index is going to be updated
Closes #2598
2025-08-14 15:35:00 +03:00