Commit Graph

3699 Commits

Author SHA1 Message Date
Ihor Andrianov
2bcdd4e404 non group by cols are displayed in group by agg statements 2025-04-03 22:28:12 +03:00
Ihor Andrianov
4fd1dcdc73 small refine 2025-04-03 22:28:11 +03:00
Ihor Andrianov
36fe859d7d create if only if non aggregate columns present 2025-04-03 22:28:11 +03:00
Ihor Andrianov
352fa6fd34 cargo fmt 2025-04-03 22:28:11 +03:00
Ihor Andrianov
b47c214a5e fix aggregation functions without group by 2025-04-03 22:28:10 +03:00
Pekka Enberg
73a35329d0 Merge 'Fix overflow position in write_page()' from Lâm Hoàng Phúc
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #1241
2025-04-03 16:33:20 +03:00
Pekka Enberg
ccbea57a4d Merge 'docs(readme): update discord link' from Jamie Barton
Closes #1242

Closes #1243
2025-04-03 15:35:16 +03:00
Jamie Barton
83ec159b0c docs(readme): update discord link 2025-04-03 13:09:24 +01:00
Pekka Enberg
67627e18c8 Limbo 0.0.19-pre.4 2025-04-03 13:36:01 +03:00
Pekka Enberg
4392193856 bindings/javascript: Fix package repository URLs 2025-04-03 13:34:30 +03:00
Pekka Enberg
4f34373392 Limbo 0.0.19-pre.3 2025-04-03 12:39:17 +03:00
Pekka Enberg
64bd0c141a github: Fix JavaScript publish workflow permissions
The workflow enables npm's provenance feature, which requires write
permissions to the "id-token" on Github actions:

https://tsmx.net/npmjs-built-and-signed-on-github-actions/
2025-04-03 12:38:01 +03:00
TcMits
56fa9049c3 fix: overflow pos in write_page 2025-04-03 15:02:53 +07:00
Pekka Enberg
a5ee6493c0 Limbo 0.0.19-pre.2 2025-04-03 10:43:36 +03:00
Pekka Enberg
4342438801 scripts: Add more npm packages to update-version.py 2025-04-03 10:43:28 +03:00
Pekka Enberg
a279056e88 bindings/javascript: Drop pre-publish step
We don't want napi creating releases.
2025-04-03 10:41:15 +03:00
Pekka Enberg
7075c75b24 Limbo 0.0.19-pre.1 2025-04-03 10:03:01 +03:00
Pekka Enberg
c61063c697 github: Fix JavaScript workflow release parsing 2025-04-03 10:03:01 +03:00
Pekka Enberg
16bc28b0af sqlite3-parser: Change debug logging to trace level
SQL scanner at debug level spams the logs pretty hard when debugging...
2025-04-03 07:46:07 +03:00
Pekka Enberg
7b9c0e9231 Merge 'More VDBE cleanups' from Pekka Enberg
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #1237
2025-04-02 19:25:41 +03:00
Pekka Enberg
24063bd9c0 core/vdbe: Add newline between op functions 2025-04-02 18:57:07 +03:00
Pekka Enberg
c592e27dca core/vdbe: Move explain() to last method in Program
...it's the least interesting one and we should have `step()` at the top.
2025-04-02 18:55:35 +03:00
Pekka Enberg
ed1854c8de Merge 'Request load page on insert_into_page' from Pere Diaz Bou
We assumed page was loaded because before inserting we would move there.
`NewRowId` unfortunately moves cursor to the rightmost page causing
eviction of root page -- this arose the issue with `insert_into_page`
not loading the page we were supposed to have loaded so I added
`return_if_locked_maybe_load` which is a utility macro to check if the
page is locked and if not, load it if needed.

Closes #1138
2025-04-02 18:52:25 +03:00
Pere Diaz Bou
65c4cb1e0e Merge 'core/vdbe: Rename execute_insn_* to op_*' from Pekka Enberg
The "execute::execute_insn" prefix is noisy, let's rename the
instruction operation functions to something shorter and sweeter.

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

Closes #1235
2025-04-02 17:25:12 +02:00
Pekka Enberg
265457f175 Merge 'Don't emit Transaction for simple SELECT statements' from Diego Reis
First step to close #1226.
Before:
![image](https://github.com/user-
attachments/assets/990bc6e2-a8f1-44db-9f82-f70a430663c1)
After:
![image](https://github.com/user-
attachments/assets/a587e207-d10f-487b-97b1-47b46f5dceff)
Reusing the same register is a bit trickier, I'm understanding how
SQLite does this optimization to apply here as well.
EDIT: Now we reuse the register and have the same number of bytecodes as
SQLite.
![image](https://github.com/user-
attachments/assets/bd7d769b-a680-4e77-ac2d-a3f1728bfdb7)

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

Closes #1227
2025-04-02 18:12:20 +03:00
Pekka Enberg
3420955db7 core/vdbe: Rename execute_insn_* to op_*
The "execute::execute_insn" prefix is noisy, let's rename the
instruction operation functions to something shorter and sweeter.
2025-04-02 18:02:02 +03:00
Pere Diaz Bou
5dedc68fda remove arc import 2025-04-02 16:56:34 +02:00
Pekka Enberg
ee203e30ba Merge 'Remove RWLock from Shared wal state' from Pere Diaz Bou
Fixes #780
WalShared state can be shared without having to wrap everything with a
lock, and instead use atomics on some places and rwlock on others -- for
now.
## Results:
From:
----
```
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [34.125 ns 34.218 ns 34.324 ns]
Execute `SELECT 1`/sqlite_execute_select_1
                        time:   [28.124 ns 28.254 ns 28.385 ns]
```
To:
----
```bash
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [31.919 ns 32.113 ns 32.327 ns]
Execute `SELECT 1`/sqlite_execute_select_1
                        time:   [29.662 ns 29.900 ns 30.139 ns]

```
And with `begin_read_tx` inlined:
----
```bash
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [30.543 ns 30.585 ns 30.632 ns]
```

Closes #1225
2025-04-02 17:47:45 +03:00
Pere Diaz Bou
e85fb86ff4 Request load page on insert_into_page
We assumed page was loaded because before inserting we would move there. `NewRowId` unfortunately moves cursor to the rightmost page causing eviction of root page -- this arose the issue with `insert_into_page` not loading the page we were supposed to have loaded so I added `return_if_locked_maybe_load` which is a utility macro to check if the page is locked and if not, load it if needed.
2025-04-02 16:24:53 +02:00
Pere Diaz Bou
46814d2bd7 ignore warning mut_from_ref 2025-04-02 16:18:36 +02:00
Pere Diaz Bou
e2d00a9f96 inline start transactions from pager and wal
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [30.543 ns 30.585 ns 30.632 ns]
2025-04-02 16:18:36 +02:00
Pere Diaz Bou
2a49fe9bd2 Remove RWLock from Shared wal state
WalShared state can be shared without having to wrap everything with a
lock, and instead use atomics on some places and rwlock on others -- for
now.

## Results:
From:
----
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [34.125 ns 34.218 ns 34.324 ns]
Execute `SELECT 1`/sqlite_execute_select_1
                        time:   [28.124 ns 28.254 ns 28.385 ns]

To:
----
Gnuplot not found, using plotters backend
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [31.919 ns 32.113 ns 32.327 ns]
Execute `SELECT 1`/sqlite_execute_select_1
                        time:   [29.662 ns 29.900 ns 30.139 ns]
2025-04-02 16:18:36 +02:00
Pekka Enberg
cd5ef7c7db Merge 'Reuse register in binary expressions if they're equal ' from Diego Reis
Alongside with #1227, this PR closes #1226
Before:
![image](https://github.com/user-attachments/assets/d9fd4ff4-957d-46cd-
abe0-63d0b2c4acdb)
After:
![image](https://github.com/user-
attachments/assets/2ce4b8f1-f8f8-423a-8d35-d947de2794cb)

Closes #1234
2025-04-02 17:02:35 +03:00
Pekka Enberg
0d3e92d42f Merge 'VDBE with indirect function dispatch' from Pere Diaz Bou
This PR is unapologetically stolen from @vmg's implementation in Vitess
implemented here https://github.com/vitessio/vitess/pull/12369. If you
want a more in depth explanation of how this works you can read the
[blog post he carefully
wrote](https://planetscale.com/blog/faster-interpreters-in-go-catching-
up-with-cpp).
In limbo we have a huge problem with [register
spilling](https://en.wikipedia.org/wiki/Register_allocation), this can
be easily observed with the prolog of `Program::step` before:
```llvm
start:
    %e.i.i304.i = alloca [0 x i8], align 8
    %formatter.i305.i = alloca [64 x i8], align 8
    %buf.i306.i = alloca [24 x i8], align 8
    %formatter.i259.i = alloca [64 x i8], align 8
    ..................... these are repeated for hundreds of lines
.....................
    %formatter.i52.i = alloca [64 x i8], align 8
    %buf.i53.i = alloca [24 x i8], align 8
    %formatter.i.i = alloca [64 x i8], align 8
    %buf.i.i = alloca [24 x i8], align 8
    %_87.i = alloca [48 x i8], align 8
    %_82.i = alloca [24 x i8], align 8
    %_73.i = alloca [24 x i8], align 8
    %_66.i8446 = alloca [24 x i8], align 8
    %_57.i = alloca [24 x i8], align 8
    %_48.i = alloca [24 x i8], align 8
```
After these changes we completely remove the need of register spilling
(yes that is the complete prolog):
```llvm
start:
    %self1 = alloca [80 x i8], align 8
    %pager = alloca [8 x i8], align 8
    %mv_store = alloca [8 x i8], align 8
    store ptr %0, ptr %mv_store, align 8
    store ptr %1, ptr %pager, align 8
    %2 = getelementptr inbounds i8, ptr %state, i64 580
    %3 = getelementptr inbounds i8, ptr %state, i64 576
    %4 = getelementptr inbounds i8, ptr %self, i64 16
    %5 = getelementptr inbounds i8, ptr %self, i64 8
    %6 = getelementptr inbounds i8, ptr %self1, i64 8
    br label %bb1, !dbg !286780
```
When it comes to branch prediction, we don't really fix a lot because
thankfully rust already compiles `match` expressions to a jump table:
```llvm
%insn = getelementptr inbounds [0 x %"vdbe::insn::Insn"], ptr %self657,
i64 0, i64 %index, !dbg !249527
%332 = load i8, ptr %insn, align 8, !dbg !249528, !range !38291,
!noundef !14
switch i8 %332, label %default.unreachable26674 [
    i8 0, label %bb111
    i8 1, label %bb101
    i8 2, label %bb100
    i8 3, label %bb110
    ...
    i8 104, label %bb5
    i8 105, label %bb16
    i8 106, label %bb14
], !dbg !249530
```
Some results
----
```
function dispatch:
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [29.498 ns 29.548 ns 29.601 ns]
                        change: [-3.6125% -3.3592% -3.0804%] (p = 0.00 <
0.05)

main:
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [33.789 ns 33.832 ns 33.878 ns]
```

Closes #1233
2025-04-02 17:01:58 +03:00
Pere Diaz Bou
66f70d571d fmt 2025-04-02 13:14:26 +00:00
Pere Diaz Bou
f5221589f0 remove wrong usage of feature = json 2025-04-02 15:00:51 +02:00
Pere Diaz Bou
7e4b57f2e2 VDBE with direct function dispatch
This PR is unapologetically stolen from @vmg's implementation in Vitess
implemented here https://github.com/vitessio/vitess/pull/12369. If you
want a more in depth explanation of how this works you can read the
[blog post he carefully
wrote](https://planetscale.com/blog/faster-interpreters-in-go-catching-up-with-cpp).

In limbo we have a huge problem with [register
spilling](https://en.wikipedia.org/wiki/Register_allocation), this can
be easily observed with the prolog of `Program::step` before:
```llvm
start:
    %e.i.i304.i = alloca [0 x i8], align 8
    %formatter.i305.i = alloca [64 x i8], align 8
    %buf.i306.i = alloca [24 x i8], align 8
    %formatter.i259.i = alloca [64 x i8], align 8
    ..................... these are repeated for hundreds of lines
.....................
    %formatter.i52.i = alloca [64 x i8], align 8
    %buf.i53.i = alloca [24 x i8], align 8
    %formatter.i.i = alloca [64 x i8], align 8
    %buf.i.i = alloca [24 x i8], align 8
    %_87.i = alloca [48 x i8], align 8
    %_82.i = alloca [24 x i8], align 8
    %_73.i = alloca [24 x i8], align 8
    %_66.i8446 = alloca [24 x i8], align 8
    %_57.i = alloca [24 x i8], align 8
    %_48.i = alloca [24 x i8], align 8
```

After these changes we completely remove the need of register spilling
(yes that is the complete prolog):
```llvm
start:
    %self1 = alloca [80 x i8], align 8
    %pager = alloca [8 x i8], align 8
    %mv_store = alloca [8 x i8], align 8
    store ptr %0, ptr %mv_store, align 8
    store ptr %1, ptr %pager, align 8
    %2 = getelementptr inbounds i8, ptr %state, i64 580
    %3 = getelementptr inbounds i8, ptr %state, i64 576
    %4 = getelementptr inbounds i8, ptr %self, i64 16
    %5 = getelementptr inbounds i8, ptr %self, i64 8
    %6 = getelementptr inbounds i8, ptr %self1, i64 8
    br label %bb1, !dbg !286780
```
When it comes to branch prediction, we don't really fix a lot because
thankfully rust already compiles `match` expressions
to a jump table:

```llvm
%insn = getelementptr inbounds [0 x %"vdbe::insn::Insn"], ptr %self657,
i64 0, i64 %index, !dbg !249527
%332 = load i8, ptr %insn, align 8, !dbg !249528, !range !38291,
!noundef !14
switch i8 %332, label %default.unreachable26674 [
    i8 0, label %bb111
    i8 1, label %bb101
    i8 2, label %bb100
    i8 3, label %bb110
    ...
    i8 104, label %bb5
    i8 105, label %bb16
    i8 106, label %bb14
], !dbg !249530
```

Some results
----
```
function dispatch:
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [29.498 ns 29.548 ns 29.601 ns]
                        change: [-3.6125% -3.3592% -3.0804%] (p = 0.00 <
0.05)

main:
Execute `SELECT 1`/limbo_execute_select_1
                        time:   [33.789 ns 33.832 ns 33.878 ns]
```
2025-04-02 14:55:37 +02:00
Diego Reis
3c531ac5ec core/expr: Reuse register in binary expressions if they're equal 2025-04-02 09:15:41 -03:00
Diego Reis
86f8719b69 core/expr: Extract binary insn emission in a separate function 2025-04-02 09:14:01 -03:00
Pekka Enberg
65ae698773 Limbo 0.0.18 2025-04-02 15:04:48 +03:00
Pekka Enberg
f7d76e0fab Update CHANGELOG.md 2025-04-02 15:04:39 +03:00
Diego Reis
fe37046536 core/emitter: Don't emit for statements that doesn't reference any tables 2025-04-02 08:59:52 -03:00
Diego Reis
6660a99003 core/emitter: Refactor the epilogue function to receive an enum 2025-04-02 08:56:19 -03:00
Pekka Enberg
e79da7375b Limbo 0.0.18-pre.5 2025-04-02 13:38:22 +03:00
Pekka Enberg
7394ad6854 Disable more b-tree fuzzers... 2025-04-02 13:38:09 +03:00
Pekka Enberg
d9562a3d82 Add update-version.py script
Simplifies version bumping.
2025-04-02 09:31:28 +03:00
Pekka Enberg
f74a10c9c1 Limbo 0.0.18-pre.4 2025-04-02 09:30:42 +03:00
Pekka Enberg
cc8340d30e Disable btree_insert_fuzz_run_random test 2025-04-02 09:15:01 +03:00
Pekka Enberg
6199c3994a Merge 'Create plan for Update queries' from Preston Thorpe
closes #1186, or at least works towards it by implementing an actual
Plan for update queries instead of translating everything inline. This
allows for actually using index's, rewriting const expressions, pushing
predicates instead of hardcoding a full scan in the translation.
### TODOs:
1.  `RETURNING` clause/result columns
2.  `OFFSET` clauses
3. on conflict
### LIMIT:
By supporting `LIMIT` directly in update queries, we'll have to put the
tests outside of the compatibility tests, maybe in the CLI tests.

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

Closes #1189
2025-04-01 17:33:32 +03:00
Pekka Enberg
149f4aa729 Merge 'Remove unnecessary balance code that crashes' from Pere Diaz Bou
Closes #1223
2025-04-01 17:31:23 +03:00