Commit Graph

981 Commits

Author SHA1 Message Date
Jussi Saurio
1bcdf99eab core/optimizer: do expression rewriting on all expressions 2025-01-10 10:04:07 +02:00
Pekka Enberg
317acb842b Merge 'Implement json_type' from Kacper Madej
Closes #631
2025-01-09 14:25:32 +02:00
Pekka Enberg
2bf7e31b64 Merge 'distinguish balance and balance_non_root' from Pere Diaz Bou
`balance_non_root` should be as close as possible to `balance_non_root`
in SQLite. This commits extract `balance_non_root` from `balance` and
renames `balance_leaf` to `balance` as it enables future work on a
complete `balance_non_root` procedure.

Closes #634
2025-01-09 14:24:46 +02:00
Kacper Madej
eebf9bfaac Implement json_type 2025-01-09 11:29:17 +07:00
PThorpe92
97d0fc68b2 Add macro and helper to clean up expression translations 2025-01-08 19:29:56 -05:00
PThorpe92
183797898b Add tests for nested conditional expressions 2025-01-08 17:19:37 -05:00
PThorpe92
fa0e7d5729 Support nested parenthesized conditional exprs in translator 2025-01-08 17:16:17 -05:00
Pere Diaz Bou
6802bb7e6a distinguish balance and balance_non_root
`balance_non_root` should be as close as possible to `balance_non_root`
in SQLite. This commits extract `balance_non_root` from `balance` and
renames `balance_leaf` to `balance` as it enables future work on a
complete `balance_non_root` procedure.
2025-01-08 19:05:49 +01:00
Jussi Saurio
b062a5f528 Fix bug with column being considered rowid alias based on 'primary_key' 2025-01-08 08:20:13 +02:00
Jussi Saurio
925bd62cbc fix logic bug in check_index_scan() that swapped lhs/rhs but not the comparison op 2025-01-08 08:20:13 +02:00
Jussi Saurio
4a58898863 Rename eliminate_between to rewrite_exprs and add true/false->1/0 case there 2025-01-08 08:20:13 +02:00
Pekka Enberg
bc1fd20892 Merge 'Fix precision issue in datetime tests' from Preston Thorpe
This PR fixes the issue with tests running on slow systems such as
github actions, where a couple `datetime` tests would be off by very
small margins and fail (e.g. #626)
![image](https://github.com/user-
attachments/assets/57d5a7bf-5acc-41f6-839b-034cab771dce)

Closes #627
2025-01-07 20:36:35 +02:00
PThorpe92
345107ce21 Fix precision issue in datetime tests 2025-01-07 09:57:19 -05:00
Jorge López
511c0b495d Rename LinuxIOError to UringIOError to match the IO backend renames 2025-01-07 15:19:31 +01:00
Jorge López
e5a12bdf01 Rename linux backend to io_uring and darwin to unix. Add new feature flag to IO backend selection 2025-01-07 15:19:29 +01:00
Jorge López
737533e35f Prepare Cargo.toml for upcoming rewrite from macos->unix and linux->io_uring. Make io_uring an optional dependency that is only enabled with a new default feature io-uring. 2025-01-07 15:17:24 +01:00
Jussi Saurio
731ff1480f Simplify working with labels
TLDR: no need to call either of:

program.emit_insn_with_label_dependency() -> just call program.emit_insn()
program.defer_label_resolution() -> just call program.resolve_label()

Changes:

- make BranchOffset an explicit enum (Label, Offset, Placeholder)
- remove program.emit_insn_with_label_dependency() - label dependency is automatically detected
- for label to offset mapping, use a hashmap from label(negative i32) to offset (positive u32)
- resolve all labels in program.build()
- remove program.defer_label_resolution() - all labels are resolved in build()
2025-01-07 12:53:10 +02:00
Pekka Enberg
2cd3c47691 Merge 'Nicer parse errors using miette' from Samyak Sarnayak
I noticed that the parse errors were a bit hard to read - only the
nearest token and the line/col offsets were printed.
I made a first attempt at improving the errors using
[miette](https://github.com/zkat/miette).
- Added derive for `miette::Diagnostic` to both the parser's error type
and LimboError.
- Added miette dependency to both sqlite3_parser and core. The `fancy`
feature is only enabled for the CLI. So the overhead on the libraries
(core, parser) should be minimal.
Some future improvements that can be made further:
- Add spans to AST nodes so that errors can better point to the correct
token. See upstream issue: https://github.com/gwenn/lemon-rs/issues/33
- Construct more errors with offset information. I noticed that most
parser errors are constructed with `None` as the offset.
- The messages are a bit redundant (example "syntax error at (1, 6)").
This can improved.
Comparisons.
Before:
```
❯ cargo run --package limbo --bin limbo database.db --output-mode pretty
...
limbo> selet * from a;
[2025-01-05T11:22:55Z ERROR sqlite3Parser] near "Token([115, 101, 108, 101, 116])": syntax error
Parse error: near "selet": syntax error at (1, 6)
```
<img width="969" alt="image" src="https://github.com/user-
attachments/assets/82651a77-f5ac-4eee-b208-88c6ea7fc9b7" />
After:
```
❯ cargo run --package limbo --bin limbo database.db --output-mode pretty
...
limbo> selet * from a;
[2025-01-05T12:25:52Z ERROR sqlite3Parser] near "Token([115, 101, 108, 101, 116])": syntax error

  × near "selet": syntax error at (1, 6)
   ╭────
 1 │ selet * from a
   ·     ▲
   ·     ╰── syntax error
   ╰────

```
<img width="980" alt="image" src="https://github.com/user-
attachments/assets/747a90e5-5085-41f9-b0fe-25864179ca35" />

Closes #618
2025-01-05 21:09:52 +02:00
Pekka Enberg
ba28999d05 Merge 'Add partial support for datetime() function' from Preston Thorpe
This PR adds the `datetime` function, with all the support currently
that date/time have for modifiers, and `julianday` function, as well as
some additional modifiers for date/time/datetime.
There are a couple considerations here, I left a couple comments but
essentially there is going to have to be some more work done to track
the state of the expression during the application of modifiers, to
handle a bunch of edge-cases like re-applying the same timezone modifier
to itself, or converting an integer automatically assumed to be
julianday, into epoch, or `ceiling`/`floor` which will determine
relative addition of time in cases like
```
2024-01-31 +1 month = 2024-03-02
```
which was painful enough to get working to begin with.
I couldn't get the `julianday_converter` library to get the exact same
float precision as sqlite, so function is included that matches their
output, for some reason floating point math + `.floor()` would give the
correct result. They seem to 'round' to 8 decimal places, and I was able
to get this to work with the same output as sqlite, except in cases like
`2234.5`, in which case we return `2234.5000000` because of the `fmt`
precision:
```rust
pub fn exec_julianday(time_value: &OwnedValue) -> Result<String> {
    let dt = parse_naive_date_time(time_value);
    match dt {
        // if we did something heinous like: parse::<f64>().unwrap().to_string()
        // that would solve the precision issue, but dear lord...
        Some(dt) => Ok(format!("{:.1$}", to_julian_day_exact(&dt), 8)),
        None => Ok(String::new()),
    }
}
```
Suggestions would be appreciated on the float precision issue.

Reviewed-by: Sonny <14060682+sonhmai@users.noreply.github.com>

Closes #600
2025-01-05 20:13:13 +02:00
Pekka Enberg
4a5b6b43bd Merge 'Fix quote escape in literals' from Vrishabh
Previously we were not escaping the quotes properly in stirng literals
as shown below. The PR fixes that
limbo output without this PR
```
limbo> select '''a';
''a
limbo>  explain select '''a';
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     4     0                    0   Start at 4
1     String8            0     1     0     ''a            0   r[1]='''a'
2     ResultRow          1     1     0                    0   output=r[1]
3     Halt               0     0     0                    0
4     Transaction        0     0     0                    0
5     Goto               0     1     0                    0
```
sqlite3 output
```
sqlite> select '''a';
'a
sqlite> explain select '''a';
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     4     0                    0
1     String8        0     1     0     'a             0
2     ResultRow      1     1     0                    0
3     Halt           0     0     0                    0
4     Goto           0     1     0                    0
```
limbo output with this PR
```
limbo> select '''a';
'a
limbo> explain select '''a';
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     4     0                    0   Start at 4
1     String8            0     1     0     'a             0   r[1]=''a'
2     ResultRow          1     1     0                    0   output=r[1]
3     Halt               0     0     0                    0
4     Transaction        0     0     0                    0
5     Goto               0     1     0                    0
```

Closes #616
2025-01-05 20:11:48 +02:00
Pekka Enberg
92ef68d627 Merge 'refactor: simplify database header write logic' from Ziyak Jehangir
- Removed unecessary clones
- Got rid of uneeded scoping in read_complete callback
- Use more rusty syntax e.g. std::cell::RefCell::borrow_mut(&buffer) ->
buffer.borrow_mut()
- Changed write_page.unwrap() to write_page()? to match run_once and
read_page()
No functional change.

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

Closes #608
2025-01-05 20:11:37 +02:00
Samyak S Sarnayak
c09a0bcbf3 Nicer parse errors using miette
I noticed that the parse errors were a bit hard to read - only the nearest token and the line/col offsets were printed.

I made a first attempt at improving the errors using [miette](https://github.com/zkat/miette).
- Added derive for `miette::Diagnostic` to both the parser's error type and LimboError.
- Added miette dependency to both sqlite3_parser and core. The `fancy` feature is only enabled for CLI.

Some future improvements that can be made further:
- Add spans to AST nodes so that errors can better point to the correct token. See upstream issue: https://github.com/gwenn/lemon-rs/issues/33
- Construct more errors with offset information. I noticed that most parser errors are constructed with `None` as the offset.

Comparisons.
Before:
```
❯ cargo run --package limbo --bin limbo database.db --output-mode pretty
...
limbo> selet * from a;
[2025-01-05T11:22:55Z ERROR sqlite3Parser] near "Token([115, 101, 108, 101, 116])": syntax error
Parse error: near "selet": syntax error at (1, 6)
```

After:
```
❯ cargo run --package limbo --bin limbo database.db --output-mode pretty
...
limbo> selet * from a;
[2025-01-05T12:25:52Z ERROR sqlite3Parser] near "Token([115, 101, 108, 101, 116])": syntax error

  × near "selet": syntax error at (1, 6)
   ╭────
 1 │ selet * from a
   ·     ▲
   ·     ╰── syntax error
   ╰────

```
2025-01-05 17:56:59 +05:30
Jussi Saurio
f0b3bac435 add new more complex benchmark entry for preparing statement 2025-01-05 13:51:56 +02:00
Jussi Saurio
f434b24e63 Fix limbo/core to work with new boxed ast types 2025-01-05 13:51:34 +02:00
psvri
9340c8f0b1 Change sanitize_string comments to doc string 2025-01-05 17:16:18 +05:30
psvri
a11f4b2b10 Refactor escape string literal logic to a function 2025-01-05 14:21:11 +05:30
psvri
2d84956fda Fix quote escape in literals 2025-01-05 01:35:29 +05:30
Pekka Enberg
9f3e064bcf Merge 'Cleanup emitter some more' from Jussi Saurio
No functional changes, just move almost everything out of `emitter.rs`
into smaller modules with more distinct responsibilities. Also, from
`expr.rs`, move `translate_aggregation` into `aggregation.rs` and
`translate_aggregation_groupby` into `group_by.rs`

Closes #610
2025-01-04 17:48:35 +02:00
Pekka Enberg
5c52c8b1e9 Merge 'Fix integer overflow output to be same as sqlite3' from Vrishabh
In sqlite3, before arithmetic operation is done, it first checks if the
operation dosent overflow and then does the operation. In case it
overflows it would covert the arguments into floats and then does the
operation as [per code](https://github.com/sqlite/sqlite/blob/ded37f337b
7b2e916657a83732aaec40eb146282/src/vdbe.c#L1875)  . I have done the same
behaviour for limbo.

Closes #612
2025-01-04 17:46:48 +02:00
PThorpe92
ca428b3dda Julianday function and additional tests/comments 2025-01-04 10:42:34 -05:00
PThorpe92
7c4a780cc2 Add DateTime func and support more modifiers 2025-01-04 08:41:03 -05:00
Jussi Saurio
9a8156753e core/translate: break emitter.rs into smaller modules 2025-01-04 14:52:46 +02:00
psvri
18137c932e Fix integer overflow output to be same result as sqlite3 2025-01-04 18:14:09 +05:30
Jussi Saurio
1b61749c0f feat/core/translate: create automatic index in CREATE TABLE when necessary 2025-01-04 13:54:44 +02:00
Pekka Enberg
fc60e544af Merge 'Fix arithmetic operations for text values' from Vrishabh
We had not implemented arithmetic operations for text values. This PR
implements this and aligns the behavior with sqlite3 .

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

Closes #605
2025-01-04 13:40:03 +02:00
Jussi Saurio
e31317fbb5 emitter.rs: use way less arguments to functions 2025-01-04 12:59:30 +02:00
Jussi Saurio
d2b73e8492 emitter.rs: make t_ctx always be the second argument to any functions 2025-01-04 12:32:50 +02:00
Jussi Saurio
d1f74fa3cb Emitter cleanup part 2: add Resolver 2025-01-04 12:23:19 +02:00
Ziyak Jehangir
4f119f4b95 refactor: simplify database header write logic 2025-01-04 14:31:23 +05:30
Jussi Saurio
23f1858239 translatectx: consistent naming 2025-01-04 10:39:32 +02:00
Jussi Saurio
1a01487872 left join metadata: consistent naming 2025-01-04 10:39:32 +02:00
Jussi Saurio
2f129402e8 sorter data register: consistent naming 2025-01-04 10:39:32 +02:00
Jussi Saurio
0c572cda3c more consistent function naming 2025-01-04 10:39:32 +02:00
Jussi Saurio
9c1d952e3b consistent names for group by regs and labels 2025-01-04 10:39:32 +02:00
Jussi Saurio
28b1754cf4 group_by_emit: add comments to labels and registers 2025-01-04 10:39:32 +02:00
Jussi Saurio
9ccbb69618 remove fields from GroupByMetadata that can be function-local 2025-01-04 10:39:32 +02:00
Pekka Enberg
bd5f081ea8 Merge 'Add support for changes() and total_changes() functions' from Lemon-Peppermint
#525
- Adds the necessary `ScalarFunc` variants to support the `changes()` &
`total_changes()` SQLite function.
- Adds the necessary fields to the `Connection` struct to track changes.
- Modify the `InsertAwait` OpCode behaviour to affect the changes
counter.

Closes #589
2025-01-04 10:14:06 +02:00
Jussi Saurio
a934ead904 Merge 'Json extract' from Kacper Madej
Implements the `json_extract` function.
In the meantime, the json path has already been implemented by
@petersooley in https://github.com/tursodatabase/limbo/pull/555 which is
a requirement for `json_extract`.
However, this PR takes a different approach and parses the JSON path
using the JSON grammar, because there are a lot of quirks in how a JSON
`key` can look (see the JSON grammar in the Pest file).
The downside is that it allocates more memory than the current
implementation, but might be easier to maintain in the long run.
I included a lot of tests with some quirky behavior of the
`json_extract` (some of them still need some work). I also noticed that
these changed between sqlite versions (had `SQLite 3.43.2` locally and
`3.45` gave different results). Due to this, I'm not sure how much value
there is in trying to be fully compatible with SQLite. Perhaps the
approach taken by @petersooley solves 99% of use-cases?

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

Closes #524
2025-01-03 23:53:29 +02:00
Jussi Saurio
0fefffbbcb Merge 'fix: index seek wrong on SeekOp::LT\SeekOp::GT' from Kould
data does not match predicate when using index, e.g: `select id, age
from users where age > 90 limit 1;` will return data with age  90
the reason is that the current index seek directly uses record for
comparison, but the record of the index itself is longer than the record
of the key (because it contains the primary key), so Gt is invalid.
since only single-column indexes are currently supported:
https://github.com/tursodatabase/limbo/pull/350, only the first value of
the record is currently used for comparison.

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

Closes #593
2025-01-03 23:27:24 +02:00
psvri
2b879a4f40 Fix arithmetic operations for text values 2025-01-04 00:34:04 +05:30