In order [experimentally
compile](https://github.com/DougAnderson444/wit-limbo) `limbo_core` to a
[wasm component](https://component-model.bytecodealliance.org/), limbo
needed to have no reliance on `js`, `js-sys`, `wasm-bindgen`, et al.
(for those who aren't familiar, there are many `wasm` runtimes and not
all of them play nice with `wasm-bindgen`)
This PR simply cleans up the dependencies, and puts them behind optional
flags and whatnot in order to enable this. Both `log` and `tracing` were
being used, so I reduced this only to `tracing`.
End result is limbo can be used like this:
https://github.com/DougAnderson444/wit-limbo
We can open a discussion on the possibilities that running limbo as a
wasm component can offer, including potentially using composable
components to implement the sqlite runtime extensions, as well as giving
us a clean interface for PlatformIO operations -- define them once,
implement many ways on various platforms. I'm new to limbo, but it looks
like current extension are Rust based deps and features flags, whereas
sqlite is runtime, right? What if limbo was runtime extensible too?
The WIT interface is largely sync (though I believe wasmtime has an
async feature), but in my limited exposure to limbo so far a lot of the
wasm seems sync already anyway. Again, topic for further discussion.
Suffice to say, aligning these deps in this way paves the road for
further experiments and possibilities.
Related: https://github.com/neilg63/julian_day_converter/pull/2
Related: https://github.com/tursodatabase/limbo/issues/950
Closes: https://github.com/tursodatabase/limbo/issues/950Closes#983
Adds initial limited support for CTEs.
- No MATERIALIZED
- No RECURSIVE
- No named CTE columns
- Only SELECT statements supported inside CTE
Basically this kind of WITH clause can just be rewritten as a subquery,
so this PR adds some plumbing to rewrite them using the existing
subquery machinery.
It also introduces the concept of a `Scope` where a child query can
refer to its parent, useful for CTEs like:
```
do_execsql_test nested-subquery-cte {
with nested_sub as (
select concat(name, '!!!') as loud_hat
from products where name = 'hat'
),
sub as (
select upper(nested_sub.loud_hat) as loudest_hat from nested_sub
)
select sub.loudest_hat from sub;
} {HAT!!!}
```
I think we need to expand the use of `Scope` to all of our identifier
resolutions (currently we don't explicitly have logic for determining
what a given query can see), but I didn't want to bloat the PR too much.
Hence, this implementation is probably full of all sorts of bugs, but
I've added equivalent tests for ALL the existing subquery tests,
rewritten in CTE form.
Closes#920
I am on a bit of a mission to revisit a lot of the ref counting, this
was an easy first win.
It seems to be a linear path of function calls or hashmaps which can own
the completions directly, no cloning needed.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#912
Move result row to `ProgramState` to mimic what SQLite does where `Vdbe`
struct has a `pResultRow` member. This makes it easier to deal with result
lifetime, but more importantly, eventually lazily parse values at the edges of
the API.
- Remove eagerly allocated `name` from `ResultSetColumn`
- `ResultSetColumn` can calculate `name()` on demand:
- if it has an alias (`foo as bar`), use that
- if it is a column reference, use that
- otherwise return none, and callers can assign it a placeholder
name (like `column_1`)
- move the `plan.result_columns` and `plan.table_references` to
`Program` after preparing statement is done, so that column names can be
returned upon request
- make `name` in `Column` optional, not needed for pseudo tables and
sorters so avoids an extra string allocation
```sql
Prepare `SELECT 1`/Limbo/SELECT 1
time: [756.80 ns 758.27 ns 760.04 ns]
change: [-3.3257% -3.0252% -2.7035%] (p = 0.00 < 0.05)
Performance has improved.
Found 8 outliers among 100 measurements (8.00%)
2 (2.00%) low severe
3 (3.00%) low mild
1 (1.00%) high mild
2 (2.00%) high severe
Prepare `SELECT * FROM users LIMIT 1`/Limbo/SELECT * FROM users LIMIT 1
time: [1.4646 µs 1.4669 µs 1.4696 µs]
change: [-6.4769% -6.2021% -5.9137%] (p = 0.00 < 0.05)
Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
1 (1.00%) low severe
3 (3.00%) low mild
3 (3.00%) high severe
Prepare `SELECT first_name, count(1) FROM users GROUP BY first_name HAVING count(1) > 1 ORDER BY cou...`
time: [3.7256 µs 3.7311 µs 3.7376 µs]
change: [-4.5195% -4.2192% -3.9309%] (p = 0.00 < 0.05)
Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
1 (1.00%) low severe
2 (2.00%) low mild
2 (2.00%) high mild
```
Closes#898
We really need to make the WAL lock less expensive, but switching to
`parking_lot` is anyway something we should do.
Before:
```
Execute `SELECT 1`/Limbo
time: [56.230 ns 56.463 ns 56.688 ns]
```
After:
```
Execute `SELECT 1`/Limbo
time: [52.003 ns 52.132 ns 52.287 ns]
```
### What?
adding checkpoint result returning number of pages in wal and num pages
checkpointed.
Part of #696
### Context
SQLite returns in checkpoint result of calling `pragma wal_checkpoint;`
`0|3|3` while limbo returns `0|0|0`.
https://sqlite.org/pragma.html#pragma_wal_checkpoint
- 1st col: 1 (checkpoint SQLITE_BUSY) or 0 (not busy).
- 2nd col: # modified pages written to wal file
- 3rd col: # pages moved to db after checkpoint
This PR aims to add 2nd and 3rd column to the checkpoint result.
SQLite
```
sqlite3 test.db
sqlite> pragma journal_mode=wal;
wal
sqlite> pragma journal_mode;
wal
sqlite> create table t1 (id text);
sqlite> insert into t1(id) values (1),(2);
sqlite> select * from t1;
1
2
sqlite> pragma wal_checkpoint;
0|3|3
```
Limbo
```
./target/debug/limbo test.db
Limbo v0.0.13
Enter ".help" for usage hints.
limbo> pragma journal_mode;
wal
limbo> create table t1(id text);
limbo> insert into t1(id) values (1),(2);
limbo> select * from t1;
1
2
# current the 2nd and 3rd columns are hard coded in limbo to 0
limbo> pragma wal_checkpoint;
0|0|0
```
Closes#827
We spend a lot of time especially in `GROUP BY` queries providing
helpful comments for `EXPLAIN`, even when the query is not an `EXPLAIN`.
So let's not do that
Closes#784
```sql
Prepare `SELECT first_name, count(1) FROM users GROUP BY first_name HAVING count(1) > 1 ORDER BY cou...
time: [4.2724 µs 4.2783 µs 4.2848 µs]
change: [-6.1063% -5.7376% -5.3626%] (p = 0.00 < 0.05)
Performance has improved.
```
doesn't affect the other trivial prepare benchmarks
Closes#875
This simple patch makes sure we can operate with a reference to the
string instead of being forced to transform it to a string, and makes
sure that the Arc doesn't have to be cloned (which can be expensive in
multi-core systems).
This doesn't really make a large difference in benchmarks, given how
expensive Parse::new() is.