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
╰────
```
The name "row result" is confusing because it really *is* a result from
a step() call. The only difference is how a row is represented as we
return from VDBE or from a statement.
Therefore, rename RowResult to StepResult.
This adds an interrupt() method to Statement that allows apps to
interrupt a running statement. Please note that this is different from
`sqlite3_interrupt()` which interrupts all ongoing operations in a
database. Although we want to support that too, per statement interrupt
is much more useful to apps.
This PR mainly adds custom logic to check equality in ast expressions.
Not sure if this belongs in the `vendored` parser or not, let me know
and I'll bring it out. Also replaces `Vec` arguments with slice refs
where possible, as well as some clippy warnings in the same `emitter`
file.
I'll write some more tests tomorrow to make sure this is as thorough as
possible.
EDIT: failed test same issue referenced in #484. Marking as draft until
more tests + cases added
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#488
- Limbo command line shell supports e.g. `SELECT x'616263';`
- `EXPLAIN SELECT x'616263';` lists the opcode
Missing:
- Command line shell not entirely compatible with SQLite when blobs have
non-printable characters in the middle (e.g. `SELECT x'610062';`)
- Python bindings not supported (incoming soon)
Improve quality of life while implementing core features.
```
Welcome to Limbo SQL shell!
> .opcodes
Abortable
---------
Verify that an Abort can happen. Assert if an Abort at this point might cause database corruption. This opcode only appears in debugging builds. An Abort is safe if either there have been no writes, or if there is an active statement journal.
Add
---------
Add the value in register P1 to the value in register P2 and store the result in register P3. If either input is NULL, the result is NULL.
AddImm
---------
Add the constant P2 to the value in register P1. The result is always an integer. To force any register to be an integer, just add 0.
Affinity
---------
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.
AggFinal
---------
P1 is the memory location that is the accumulator for an aggregate or window function. Execute the finalizer function for an aggregate and store the result in P1. P2 is the number of arguments that the step function takes and P4 is a pointer to the FuncDef for this function. The P2 argument is not used by this opcode. It is only there to disambiguate functions that can take varying numbers of arguments. The P4 argument is only needed for the case where the step function was not previously called.
```
It can also search for specific opcode:
```
> .opcodes yield
Yield
---------
Swap the program counter with the value in register P1. This has the effect of yielding to a coroutine. If the coroutine that is launched by this instruction ends with Yield or Return then continue to the next instruction. But if the coroutine launched by this instruction ends with EndCoroutine, then jump to P2 rather than continuing with the next instruction. See also: InitCoroutine
```