Commit Graph

423 Commits

Author SHA1 Message Date
psvri
e616bd5361 Implement Not 2025-01-20 00:21:23 +05:30
Pekka Enberg
f5e5428d45 Merge 'Syntactic improvements' from Jorge López Tello
This is a purely syntactic PR. It doesn't change behavior, just rewrites
some loops and removes unneeded parts, like lifetime annotations and
references. Mainly because the Clippy and IDE warnings get annoying.
Don't worry about the number of commits, I just separated based on type
of change.

Closes #732
2025-01-19 12:17:28 +02:00
Pekka Enberg
3e28541b53 Merge 'Fix null compare operations not giving null' from Vrishabh
In limbo when we do any compare operations like `Eq, gt, lt, gte, lte`
with nulls , we were actually giving the result as true where as sqlite3
gives null. This is because if we had a null, we were incorrectly going
to conditional branch and not increment program by 1. Also the sqlite
generates `ZeroOrNull` op in these cases
(https://github.com/sqlite/sqlite/blob/version-3.45.3/src/expr.c#L4644)
but we were generating a Integer instruction. The below outputs can give
a clearer picture.
This PR aims to fix this.
sqlite3 output
```
SQLite version 3.48.0
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> select 8 = null;

sqlite> select 8 > null;

sqlite> explain select 8 > null;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     6     0                    0
1     Integer        1     1     0                    0
2     Gt             3     4     2                    64
3     ZeroOrNull     2     1     3                    0
4     ResultRow      1     1     0                    0
5     Halt           0     0     0                    0
6     Integer        8     2     0                    0
7     Null           0     3     0                    0
8     Goto           0     1     0                    0
sqlite> explain select 8 = null;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     6     0                    0
1     Integer        1     1     0                    0
2     Eq             3     4     2                    64
3     ZeroOrNull     2     1     3                    0
4     ResultRow      1     1     0                    0
5     Halt           0     0     0                    0
6     Integer        8     2     0                    0
7     Null           0     3     0                    0
8     Goto           0     1     0                    0
```
Limbo Output
```
Limbo v0.0.12
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database
limbo> select 8 = null;
1
limbo> select 8 > null;
1
limbo> explain select 8 > null;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     8     0                    0   Start at 8
1     Integer            8     2     0                    0   r[2]=8
2     Null               0     3     0                    0   r[3]=NULL
3     Integer            1     1     0                    0   r[1]=1
4     Gt                 2     3     6                    0   if r[2]>r[3] goto 6
5     Integer            0     1     0                    0   r[1]=0
6     ResultRow          1     1     0                    0   output=r[1]
7     Halt               0     0     0                    0
8     Transaction        0     0     0                    0
9     Goto               0     1     0                    0
limbo> explain select 8 = null;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     8     0                    0   Start at 8
1     Integer            8     2     0                    0   r[2]=8
2     Null               0     3     0                    0   r[3]=NULL
3     Integer            1     1     0                    0   r[1]=1
4     Eq                 2     3     6                    0   if r[2]==r[3] goto 6
5     Integer            0     1     0                    0   r[1]=0
6     ResultRow          1     1     0                    0   output=r[1]
7     Halt               0     0     0                    0
8     Transaction        0     0     0                    0
9     Goto               0     1     0                    0
limbo>
```
Limbo Output with this PR
```
Limbo v0.0.12
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database
limbo> select 8 = null;

limbo> select 8 > null;

limbo> explain select 8 > null;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     8     0                    0   Start at 8
1     Integer            8     2     0                    0   r[2]=8
2     Null               0     3     0                    0   r[3]=NULL
3     Integer            1     1     0                    0   r[1]=1
4     Gt                 2     3     6                    0   if r[2]>r[3] goto 6
5     ZeroOrNull         2     1     3                    0   ((r[2]=NULL)|(r[3]=NULL)) ? r[1]=NULL : r[1]=0
6     ResultRow          1     1     0                    0   output=r[1]
7     Halt               0     0     0                    0
8     Transaction        0     0     0                    0
9     Goto               0     1     0                    0
limbo>  explain select 8 = null;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     8     0                    0   Start at 8
1     Integer            8     2     0                    0   r[2]=8
2     Null               0     3     0                    0   r[3]=NULL
3     Integer            1     1     0                    0   r[1]=1
4     Eq                 2     3     6                    0   if r[2]==r[3] goto 6
5     ZeroOrNull         2     1     3                    0   ((r[2]=NULL)|(r[3]=NULL)) ? r[1]=NULL : r[1]=0
6     ResultRow          1     1     0                    0   output=r[1]
7     Halt               0     0     0                    0
8     Transaction        0     0     0                    0
9     Goto               0     1     0                    0
```

Closes #733
2025-01-19 09:09:12 +02:00
Pekka Enberg
cdcc98540a cargo fmt 2025-01-19 08:52:01 +02:00
Krishna Vishal
5cf78b7d54 chore: clippy remove unused imports 2025-01-19 07:18:31 +05:30
Krishna Vishal
acad562c07 Remove unnecessary Result 2025-01-19 06:50:00 +05:30
Krishna Vishal
fa0503f0ce 1. Changes to extension.py
2. chore: cargo fmt
2025-01-19 04:58:05 +05:30
Krishna Vishal
6173aeeb3b 1. Fix merge conflicts
2. change tests for extensions to return error instead of null (Preston)
2025-01-19 04:39:25 +05:30
Krishna Vishal
ca097b1972 Remove unused import 2025-01-19 04:35:21 +05:30
Krishna Vishal
027803aabf Refactor code 2025-01-19 04:35:21 +05:30
Krishna Vishal
68553904c7 Converted the unconditional unwrap to a match which handles the case when the function is COUNT and args are None and replaces the args. Solves https://github.com/tursodatabase/limbo/issues/725 2025-01-19 04:35:21 +05:30
psvri
e16b3491c4 Fix null compares giving incorrect results 2025-01-19 00:44:38 +05:30
Jorge López
50852f36f8 syntactic changes: semantics, call is_empty instead of manually checking the size 2025-01-18 19:20:12 +01:00
Jorge López
3da813b260 syntactic changes: use if let .. else instead of checking for is_none() and calling unwrap() 2025-01-18 19:20:12 +01:00
Jorge López
218a2e6dda syntactic changes: remove unneeded mut, lifetimes,references that get instantaneously dereferenced and casts 2025-01-18 18:43:47 +01:00
Jorge López
2cc8cb9ad8 syntactic changes: use assert_eq!() instead of assert!() for equality comparisons 2025-01-18 18:37:50 +01:00
Jorge López
f160206cdd syntactic changes: replace unwrap() with ? in functions that return Result<...> 2025-01-18 18:33:43 +01:00
Jorge López
86a4714711 syntactic changes: remove unneeded paths when the type is already imported 2025-01-18 18:29:12 +01:00
psvri
b966351e1f Implement IsNot operator 2025-01-18 22:49:09 +05:30
psvri
5a13f0790f Implement is operator 2025-01-18 15:57:26 +05:30
PThorpe92
fc82461eff Complete percentile extension, enable col+delimeter args 2025-01-17 21:15:09 -05:00
PThorpe92
0c737d88f7 Support aggregate functions in Extensions 2025-01-17 14:13:57 -05:00
psvri
3e9f3ae652 Fix all args not being passed to external functions 2025-01-16 23:15:01 +05:30
Levy A.
9b8722f38e refactor: more well rounded implementation
`?0` parameters are now handled by the parser.
2025-01-15 16:53:26 -03:00
Levy A.
5de2694834 feat: more parameter support
add `Statement::{parameter_index, parameter_name, parameter_count,
bind_at}`. some refactoring is still needed, this is quite a rough
iteration
2025-01-15 16:51:04 -03:00
Levy A.
08c8c655e9 feat: initial implementation of Statement::bind 2025-01-15 16:51:04 -03:00
Pekka Enberg
bdc06f2d66 Merge 'Implement ShiftRight' from Vrishabh
This PR adds support for ShiftRight operator and Opcode.

Closes #703
2025-01-15 18:53:23 +02:00
Pekka Enberg
7c549bc978 Merge 'Expr: fix recursive binary operation logic' from Jussi Saurio
I believe this closes #682
```
limbo> CREATE TABLE proficient_barrett (imaginative_etrebilal BLOB,lovely_wilson BLOB);
INSERT INTO proficient_barrett VALUES (X'656E67726F7373696E675F636861636F', X'776F6E64726F75735F626F75726E65');
limbo> SELECT * FROM proficient_barrett
WHERE (
    (
        (
            (
                imaginative_etrebilal != X'6661766F7261626C655F636F726573'
                OR
                (imaginative_etrebilal > X'656E67726F7373696E675F6368616439')
            )
            AND
            (
                imaginative_etrebilal = X'656E676167696E675F6E6163696F6E616C'
                OR
                TRUE
            )
        )
        OR
        FALSE
    )
    AND
    (
        imaginative_etrebilal > X'656E67726F7373696E675F63686164F6'
        OR
        TRUE
    )
);
engrossing_chaco|wondrous_bourne
```
@PThorpe92 I don't think we need the `parent_op` machinery at all, we
just need to not jump to the `jump_target_when_true` label given by the
parent if we are evaluating the first condition of an AND.
related: https://github.com/tursodatabase/limbo/pull/633

Reviewed-by: Preston Thorpe <cory.pride83@gmail.com>

Closes #698
2025-01-15 18:32:59 +02:00
psvri
d3f28c51f4 Implement ShiftRight 2025-01-15 21:21:51 +05:30
psvri
5b4d82abbf Implement ShiftLeft 2025-01-15 18:54:07 +05:30
Jussi Saurio
84ef8a8951 translate_condition_expr(): unify how the AND and OR cases look 2025-01-15 14:24:40 +02:00
Jussi Saurio
f8b3b06163 Expr: fix recursive binary operation logic 2025-01-15 14:12:08 +02:00
Pekka Enberg
ca2333d0c4 Merge 'Add load_extension function, resolve shared lib extensions' from Preston Thorpe
This PR adds the `load_extension` function, and allows for platform
agnostic arguments: e.g. `select
load_extension('target/debug/liblimbo_uuid');` omitting the file
extension.

Closes #680
2025-01-15 09:14:34 +02:00
Pekka Enberg
256c0d4604 Merge 'Add support for rowid keyword' from Kould
https://github.com/tursodatabase/limbo/issues/241
support keyword `rowid`
check if rowid exists when creating table
```shell
explain SELECT rowid FROM users WHERE rowid = 1;

addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     12    0                    0   Start at 12
1     OpenReadAsync      0     2     0                    0   table=users, root=2
2     OpenReadAwait      0     0     0                    0
3     RewindAsync        0     0     0                    0
4     RewindAwait        0     11    0                    0   Rewind table users
5       RowId            0     2     0                    0   r[2]=users.rowid
6       Ne               2     3     9                    0   if r[2]!=r[3] goto 9
7       RowId            0     1     0                    0   r[1]=users.rowid
8       ResultRow        1     1     0                    0   output=r[1]
9     NextAsync          0     0     0                    0
10    NextAwait          0     5     0                    0
11    Halt               0     0     0                    0
12    Transaction        0     0     0                    0
13    Integer            1     3     0                    0   r[3]=1
14    Goto               0     1     0                    0
```

Closes #596
2025-01-14 21:10:20 +02:00
PThorpe92
23d9d09b70 Add load_extension function, resolve shared lib extensions 2025-01-14 12:01:07 -05:00
Kould
1bf651bd37 chore: rollback using rowid(sqlite3 unsupported) 2025-01-14 22:56:49 +08:00
Kould
5305a9d0fd feat: support keyword rowid 2025-01-14 22:41:40 +08:00
Jussi Saurio
fcfee24c50 Remove mark_last_insn_constant() from places where it is not safe to do so 2025-01-14 16:06:49 +02:00
PThorpe92
9c208dc866 Add tests for first extension 2025-01-14 07:27:35 -05:00
PThorpe92
98eff6cf7a Enable passing arguments to external functions 2025-01-14 07:20:50 -05:00
PThorpe92
3412a3d4c2 Rough design for extension api/draft extension 2025-01-14 07:20:48 -05:00
Levy A.
2f2c96fa2c chore: cargo fmt 2025-01-13 21:31:33 -03:00
Levy A.
eff5de50c5 refactor: make translate_* functions accept ProgramBuilder
simplifies function signatures and allows attaching more context to
ProgramStatus on `translate::translate`, useful for query parameters.
2025-01-13 20:41:56 -03:00
Pekka Enberg
c7ea2393b3 Merge 'Store cursor types in program state and remove trait Cursor' from Jussi Saurio
I was planning on starting work on index insertion, but realized we need
to know whether our cursor refers to a table or an index etc., so it
resulted in this refactoring work.
- `cursor_ref` now contains what _type_ of cursor it is (table, index,
pseudo, sorter)
- `program.cursors` is now `program.btree_table_cursors`,
`program.btree_index_cursors` etc and they are unboxed because dynamic
dispatch is no longer necessary
- Cursor trait removed -- 95% of the shit was btree specific anyway, so
I just moved them to `BTreeCursor`. In certain instructions in the VDBE
we expect a btree cursor and in others we expect a pseudo/sorter etc,
lets make that explicit.
- I also removed `BTreeCursor::get_new_rowid()` specific tests that
required macros to generate a mock implementation of the `Cursor` trait
-- main reason is I couldn't figure out how to reimplement this without
the trait, and the second reason is that I don't think we really need
those tests, AND the proc macro is constantly failing in my editor as
well and screwing up `rust-analyzer`

Closes #655
2025-01-13 18:40:46 +02:00
Pekka Enberg
1e94dbffcc Merge branch 'main' into json-error-position 2025-01-13 18:21:37 +02:00
Jussi Saurio
9909539b9d Store cursor type (table,index,pseudo,sorter) when allocating cursor 2025-01-11 17:04:16 +02:00
Jussi Saurio
e782f30ffe Add expect_arguments_min!() and use expect_arguments_* macros more universally 2025-01-11 09:55:07 +02:00
Peter Sooley
b5fed15997 implement json_error_position 2025-01-10 11:12:30 -08:00
Kacper Madej
7efa87ff31 Merge branch 'main' into right-arrow-json 2025-01-10 19:25:56 +07:00
Jussi Saurio
1bcdf99eab core/optimizer: do expression rewriting on all expressions 2025-01-10 10:04:07 +02:00