Commit Graph

4060 Commits

Author SHA1 Message Date
Jussi Saurio
bf2e198a57 Merge 'Fix out of bounds access on parse_numeric_str' from Levy A.
Fixes #1361.

Closes #1362
2025-04-18 15:24:37 +03:00
Levy A.
5fd2ed0bae fix: handle empty case 2025-04-17 20:20:57 -03:00
Levy A.
32d59b8c78 refactor+fix: using a more robust pattern matching approach 2025-04-17 20:08:05 -03:00
Jussi Saurio
48bee334cf Merge 'Support xBestIndex in vtab API' from Preston Thorpe
closes #1185
## The Problem:
The underlying schema of virtual tables is hidden from the query
planner, and it currently has no way of optimizing select queries with
vtab table refs by using indexes or removing non-constant predicates.
All vtabs are currently rewound completely each time and any conditional
filtering is done in the vdbe layer instead of in the `VFilter`.
## The solution:
Add xBestIndex to the vtab module API to let extensions return some
`IndexInfo` that will allow the query planner to make better
optimizations and possibly omit conditionals
## Examples:
table `t`: vtab: (key, value)
table `t2`: table: (a,b)
### Join where vtab is outer table:
![image](https://github.com/user-
attachments/assets/87f4233f-7d32-4a5e-8f95-4bebd3549304)
Properly pushes predicate to VFilter, which receives the idx_str
`key_eq` arg, telling it that there is a useable where clause on the key
"index"
### Join where vtab is inner table:
![image](https://github.com/user-
attachments/assets/f8fcf6d3-42bc-41a3-ad86-16e497ec6056)
Constraint is not sent because it is marked as unusable
### Where clause on "indexed" column:
![image](https://github.com/user-
attachments/assets/8817cc45-177c-404d-8323-4d33180e280c)
Pushed down and the predicate is omitted from the VDBE layer.
### Where clause on regular column:
![image](https://github.com/user-
attachments/assets/85595c7f-920f-4047-8388-a7dddd01778c)
No idx info received from BestIndex, VDBE handles conditional.
## TODO:
OrderBy info needs to be sent to xBestIndex and its not in a great
position in `open_loop` currently

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

Closes #1264
2025-04-17 23:17:01 +03:00
Jussi Saurio
bef2058f1c Merge 'Fix post balance validation ' from Pere Diaz Bou
Closes #1360
2025-04-17 22:48:51 +03:00
PThorpe92
d02900294e Remove 2nd shell in vtab tests, fix expr translation in main loop 2025-04-17 14:01:45 -04:00
PThorpe92
a25a02efe1 Improve xBestIndex call site and allow for proper handling of join and where constraints 2025-04-17 14:01:45 -04:00
PThorpe92
245e7f94f6 Store packed field on ConstraintInfo to optimize planning for vfilter 2025-04-17 14:01:45 -04:00
PThorpe92
95a2fdc096 Fix array from ptr in bestindex ffi method in proc macro 2025-04-17 14:01:45 -04:00
PThorpe92
d53c60e071 Prevent double allocations for VFilter args in vdbe 2025-04-17 14:01:45 -04:00
PThorpe92
e17fd7edc4 Add comments and address PR review 2025-04-17 14:01:44 -04:00
PThorpe92
528a9b6c7e Clean up allocations in main loop and fix ext tests 2025-04-17 14:01:44 -04:00
PThorpe92
7d271edf8a Remove unused function in core/util.rs 2025-04-17 14:01:44 -04:00
PThorpe92
6f2c6c6a61 Actually skip omitted predicates in open loop 2025-04-17 14:01:44 -04:00
PThorpe92
de27c2fe4c Properly handle pushing predicates for query optimization from xBestIndex 2025-04-17 14:01:37 -04:00
PThorpe92
0f34a813ff Add can_pushdown_predicate fn to evaluate ast expressions for constness 2025-04-17 13:53:28 -04:00
PThorpe92
853af16946 Implement xBestIndex for virtual table api to improve query planning 2025-04-17 13:53:27 -04:00
Pere Diaz Bou
262c630c16 fix validation with overflow cells 2025-04-17 18:28:42 +02:00
Jussi Saurio
30c488e35d Merge 'Feat: add support for descending indexes' from Jussi Saurio
### Feat:
- Adds support for descending indexes
### Testing:
- Augments existing compound key index seek fuzz test to test for
various combinations of ascending and descending indexed columns. To
illustrate, the test runs 10000 queries like this on 8 different tables
with all different asc/desc permutations of a three-column primary key
index:
```sql
query: SELECT * FROM t WHERE x = 2826  LIMIT 5
query: SELECT * FROM t WHERE x = 671 AND y >= 2447 ORDER BY x ASC, y DESC LIMIT 5
query: SELECT * FROM t WHERE x = 2412 AND y = 589 AND z >= 894 ORDER BY x DESC LIMIT 5
query: SELECT * FROM t WHERE x = 1217 AND y = 1437 AND z <= 265 ORDER BY x ASC, y ASC, z DESC LIMIT 5
query: SELECT * FROM t WHERE x < 138 ORDER BY x DESC LIMIT 5
query: SELECT * FROM t WHERE x = 1312 AND y = 2757 AND z > 39 ORDER BY x DESC, y ASC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x = 1829 AND y >= 1629 ORDER BY x ASC, y ASC LIMIT 5
query: SELECT * FROM t WHERE x = 2047 ORDER BY x DESC LIMIT 5
query: SELECT * FROM t WHERE x = 893 AND y > 432 ORDER BY y DESC LIMIT 5
query: SELECT * FROM t WHERE x = 1865 AND y = 784 AND z <= 785 ORDER BY x DESC, y DESC, z DESC LIMIT 5
query: SELECT * FROM t WHERE x = 213 AND y = 1475 AND z <= 2870 ORDER BY x ASC, y ASC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x >= 1780 ORDER BY x ASC LIMIT 5
query: SELECT * FROM t WHERE x = 1983 AND y = 602 AND z = 485 ORDER BY y ASC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x = 2311 AND y >= 31 ORDER BY y DESC LIMIT 5
query: SELECT * FROM t WHERE x = 81 AND y >= 1037 ORDER BY x ASC, y DESC LIMIT 5
query: SELECT * FROM t WHERE x < 2698 ORDER BY x ASC LIMIT 5
query: SELECT * FROM t WHERE x = 1503 AND y = 554 AND z >= 185 ORDER BY x DESC, y DESC, z DESC LIMIT 5
query: SELECT * FROM t WHERE x = 619 AND y > 1414 ORDER BY x DESC, y ASC LIMIT 5
query: SELECT * FROM t WHERE x >= 865 ORDER BY x DESC LIMIT 5
query: SELECT * FROM t WHERE x = 1596 AND y = 622 AND z = 62 ORDER BY x DESC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x = 1555 AND y = 1257 AND z < 1929 ORDER BY x ASC, y ASC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x > 2598  LIMIT 5
query: SELECT * FROM t WHERE x = 302 AND y = 2476 AND z < 2302 ORDER BY z DESC LIMIT 5
query: SELECT * FROM t WHERE x = 2197 AND y = 2195 AND z > 2089 ORDER BY y ASC, z DESC LIMIT 5
query: SELECT * FROM t WHERE x = 1030 AND y = 1717 AND z < 987  LIMIT 5
query: SELECT * FROM t WHERE x = 2899 AND y >= 382 ORDER BY y DESC LIMIT 5
query: SELECT * FROM t WHERE x = 62 AND y = 2980 AND z < 1109 ORDER BY x DESC, y DESC, z DESC LIMIT 5
query: SELECT * FROM t WHERE x = 550 AND y > 221 ORDER BY y DESC LIMIT 5
query: SELECT * FROM t WHERE x = 376 AND y = 1874 AND z < 206 ORDER BY y DESC, z ASC LIMIT 5
query: SELECT * FROM t WHERE x = 859 AND y = 2157 ORDER BY x DESC LIMIT 5
query: SELECT * FROM t WHERE x = 2166 AND y = 2079 AND z < 301 ORDER BY x DESC, y ASC LIMIT 5
```
the queries are run against both sqlite and limbo.

Reviewed-by: Pere Diaz Bou (@pereman2)
Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #1330
2025-04-16 15:38:59 +03:00
Pekka Enberg
7a3fc33592 Limbo 0.0.19 2025-04-16 15:23:02 +03:00
Pekka Enberg
c7935f4fb7 Update CHANGELOG.md 2025-04-16 15:21:48 +03:00
Jussi Saurio
95bc644244 tests/fuzz: make compound key fuzz test a bit stricter with ordering 2025-04-16 14:10:25 +03:00
Pekka Enberg
38dab4c184 Limbo 0.0.19-pre.5 2025-04-16 14:00:17 +03:00
Jussi Saurio
1189b7a288 codegen: add support for descending indexes 2025-04-16 13:58:12 +03:00
Jussi Saurio
b1073da4a5 btree: add support fo descending indexes 2025-04-16 13:58:12 +03:00
Jussi Saurio
af09025088 schema: keep track of primary key column sort order 2025-04-16 13:58:12 +03:00
Jussi Saurio
8757510606 test/fuzz: revamp compound key seek fuzz test to include desc indexes and be more efficient 2025-04-16 13:58:12 +03:00
Jussi Saurio
bde808f731 Merge 'Test: write tests for file backed db' from Pedro Muniz
First attempt at closing #1212. Also with this PR, I added the option of
using `with` syntax for `TestLimboShell`. It automatically closes the
shell on error, and facilitates error handling overall. If this is
merged, I can update the other python tests to use `with` as well.

Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #1230
2025-04-16 11:16:18 +03:00
Jussi Saurio
1d9c6d6981 Merge 'btree: move some blocks of code to more reasonable places' from Jussi Saurio
Reviewed-by: Preston Thorpe (@PThorpe92)

Closes #1343
2025-04-16 11:13:15 +03:00
Jussi Saurio
913367409e Merge 'Parse hex integers 2' from Anton Harniakou
Continuation of #1329

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

Closes #1347
2025-04-16 11:13:01 +03:00
Anton Harniakou
8c797a9bd1 Use eq_ignore_ascii_case to compare strings 2025-04-15 21:48:53 +03:00
Jussi Saurio
13a703d636 Merge 'Add BeginSubrtn, NotFound and Affinity bytecodes' from Diego Reis
I'm working on an optimization of `WHERE .. IN (..)` statements that
requires these bytecodes.
```sh
sqlite> explain select * from users where first_name in ('alice', 'bob', 'charlie');
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     35    0                    0   Start at 35
1     OpenRead       0     2     0     10             0   root=2 iDb=0; users
2     Rewind         0     34    0                    0
3       Noop           0     0     0                    0   begin IN expr
4       BeginSubrtn    0     1     0                    0   r[1]=NULL <---- Here
5         Once           0     17    0                    0
6         OpenEphemeral  1     1     0     k(1,B)         0   nColumn=1; RHS of IN operator
7         String8        0     2     0     alice          0   r[2]='alice'
8         MakeRecord     2     1     3     B              0   r[3]=mkrec(r[2])
9         IdxInsert      1     3     2     1              0   key=r[3]
10        String8        0     2     0     bob            0   r[2]='bob'
11        MakeRecord     2     1     3     B              0   r[3]=mkrec(r[2])
12        IdxInsert      1     3     2     1              0   key=r[3]
13        String8        0     2     0     charlie        0   r[2]='charlie'
14        MakeRecord     2     1     3     B              0   r[3]=mkrec(r[2])
15        IdxInsert      1     3     2     1              0   key=r[3]
16        NullRow        1     0     0                    0
17      Return         1     5     1                    0
18      Column         0     1     4                    0   r[4]= cursor 0 column 1
19      IsNull         4     33    0                    0   if r[4]==NULL goto 33
20      Affinity       4     1     0     B              0   affinity(r[4]) <---- Here
21      NotFound       1     33    4     1              0   key=r[4]; end IN expr <---- Here
22      Rowid          0     5     0                    0   r[5]=users.rowid
23      Column         0     1     6                    0   r[6]= cursor 0 column 1
24      Column         0     2     7                    0   r[7]= cursor 0 column 2
25      Column         0     3     8                    0   r[8]= cursor 0 column 3
26      Column         0     4     9                    0   r[9]= cursor 0 column 4
27      Column         0     5     10                   0   r[10]= cursor 0 column 5
28      Column         0     6     11                   0   r[11]= cursor 0 column 6
29      Column         0     7     12                   0   r[12]= cursor 0 column 7
30      Column         0     8     13                   0   r[13]= cursor 0 column 8
31      Column         0     9     14                   0   r[14]= cursor 0 column 9
32      ResultRow      5     10    0                    0   output=r[5..14]
33    Next           0     3     0                    1
34    Halt           0     0     0                    0
35    Transaction    0     0     3     0              1   usesStmtJournal=0
36    Goto           0     1     0                    0
```
EDIT: [Found](https://sqlite.org/opcode.html#Found) and
[NoConflict](https://sqlite.org/opcode.html#NoConflict) can be easily
derived from `NotFound` but I wanted to be concise, I could do it in
another PR :)

Closes #1345
2025-04-15 20:25:55 +03:00
Diego Reis
2cc492844e Improve NotFound's docs clarity 2025-04-15 13:36:45 -03:00
pedrocarlo
bd5531987e adjusting memory test to use UV 2025-04-15 12:51:43 -03:00
pedrocarlo
3cd2017df4 introduce test theme 2025-04-15 12:51:43 -03:00
pedrocarlo
321def3c30 adjust stack_offset for test_limbo_cli 2025-04-15 12:51:43 -03:00
pedrocarlo
4c0bd50ac9 force terminal colors 2025-04-15 12:50:35 -03:00
pedrocarlo
d71029cda7 Overhaul in printing using rich 2025-04-15 12:50:35 -03:00
pedrocarlo
b34e7e011e Prettier console 2025-04-15 12:45:46 -03:00
pedrocarlo
dd5310a85e adjust workflow to install uv 2025-04-15 12:45:46 -03:00
pedrocarlo
bdef83dc1c update test 2025-04-15 12:45:46 -03:00
pedrocarlo
0c137d6dff Cleaner and less error prone Write Tests 2025-04-15 12:45:46 -03:00
pedrocarlo
58e091cb23 setup uv for limbo 2025-04-15 12:45:46 -03:00
pedrocarlo
862783aec7 forgot to add to test command in makefile 2025-04-15 12:45:46 -03:00
pedrocarlo
46eaa52400 write tests for file backed db 2025-04-15 12:45:45 -03:00
Jussi Saurio
2b4ff48a8b Merge 'More index utils' from Jussi Saurio
Some more helper utilities extracted out from #1351 to make the surface
area of that PR smaller

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

Closes #1353
2025-04-15 18:20:41 +03:00
Diego Reis
58efb90467 core: Add Affinity bytecode
Apply affinities to a range of P2 registers starting with P1.

P4 is a string that is P2 characters long. The N-th character of the string indicates the column affinity that should be used for the N-th memory cell in the range.
2025-04-15 09:52:04 -03:00
Diego Reis
c5161311fc core/vdbe: Add NotFound bytecode
If P4==0 then register P3 holds a blob constructed by MakeRecord. If P4>0 then register P3 is the first of P4 registers that form an unpacked record.

Cursor P1 is on an index btree. If the record identified by P3 and P4 is not the prefix of any entry in P1 then a jump is made to P2. If P1 does contain an entry whose prefix matches the P3/P4 record then control falls through to the next instruction and P1 is left pointing at the matching entry.

This operation leaves the cursor in a state where it cannot be advanced in either direction. In other words, the Next and Prev opcodes do not work after this operation.
2025-04-15 09:52:04 -03:00
Diego Reis
825aeb3f83 core/vdbe: Add BeginSubrtn bytecode
Basically it does the very same thing of Null, but has a different name to differentiate its usage.
2025-04-15 09:52:04 -03:00
Jussi Saurio
1fe1f0ebba ProgramBuilder: add resolve_cursor_id_safe() which doesn't unwrap 2025-04-15 15:13:39 +03:00