We don't need `push_predicates()` because that never REALLY was a predicate
pushdown optimization -- it just pushed WHERE clause condition expressions
into the correct SourceOperator nodes in the tree.
Now that we don't have a SourceOperator tree anymore and we keep the conditions
in the WHERE clause instead, we don't need to "push" anything anymore. Leaves
room for ACTUAL predicate pushdown optimizations later :)
We also don't need any weird bitmask stuff anymore, and perhaps we never did,
to determine where conditions should be evaluated.
Now that we do not have a tree of SourceOperators but rather
a Vec of TableReferences, we can just use loops instead of
recursion for handling the main query loop.
- use new TableReference and JoinAwareConditionExpr
- add utilities for determining at which loop depth a
WHERE condition should be evaluated, now that "operators"
do not carry condition expressions inside them anymore.
- Get rid of SourceOperator tree
- Make plan have a Vec of TableReference, and TableReference now
contains the information from the old SourceOperator.
- Remove `predicates` (conditions) from Table References -- put
everything in the WHERE clause like SQLite, and attach metadata
to the where clause expressions with JoinAwareConditionExpr struct.
- Refactor select_star() to be simpler now that we use a vec, not a tree
This PR adjust emitted instructions for expressions which include `IS` /
`IS NOT` operators (support for them in the conditions were added in the
#847)
Reviewed-by: Glauber Costa (@glommer)
Closes#857
This PR remove manual null-comparison optimization (introduced in #847)
which replace `Eq`/`Ne` instructions with explicit `IsNull`/`NotNull`.
There are few factors for this change:
1. Before, manual optimization were incorrect because it ignored
`jump_if_condition_is_true` flag which is important to properly build
logical condition evaluation
2. Manual optimization covered all scenarios in test cases and scenarios
when both sides are non trivial expressions were not covered by tests
3. Limbo already mark literals in the initial emitted bytecode as
constants and will evaluate and store them only once - so performance
difference from manual optimization seems very minor to me (but I am
wrong with high probability)
4. I think (but again, I am wrong with high probability) that such
replacement can be done in the generic optimizator layer instead of
manually encode them in the first emit phase
Fixes#850
Reviewed-by: Glauber Costa (@glommer)
Closes#856
The main difference between = and != is how null values are handled.
SQLite passes a flag "NULLEQ" to Eq and Ne to disambiguate that.
In the presence of that flag, NULL = NULL.
Some prep work is done to make sure we can pass a flag instead of a
boolean to Eq and Ne. I looked into the bitflags crate but got a bit
scared with the list of dependencies.
Warning:
The following query produces a different result for Limbo:
```
select * from demo where value is null or id == 2;
```
I strongly suspect the issue is with the OR implementation, though. The
bytecode generated is quite different.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#847
This seems to really be just an alias for IS:
"The IS NOT DISTINCT FROM operator is an alternative spelling for the IS
operator. Likewise, the IS DISTINCT FROM operator means the same thing
as IS NOT. Standard SQL does not support the compact IS and IS NOT
notation. Those compact forms are an SQLite extension. You have to use
the prolix and much less readable IS NOT DISTINCT FROM and IS DISTINCT
FROM operators on other SQL database engines."
Improvements:
- Use [rust-overlay](https://github.com/oxalica/rust-overlay), better
maintained than fenix and allows for:
- Use `rust-toolchain.toml` as the source of truth for the current rust
version, instead of tracking with stable. Preventing conflicting
versions with non-nix users.
- Add flake checks, could be useful for CI in the future, together with
crane and cachix.
- Add package, allow people to add limbo as a regular nix package. Now
we can `nix build .#`, `nix run .#` and `nix shell .#` (this one adds
`limbo` to the current `PATH`)
- Use [new `apple-sdk` pattern](https://discourse.nixos.org/t/the-
darwin-sdks-have-been-updated/55295), no need to declare each framework
now.
Closes#835
This PR continues work on the Go bindings.
- Register all symbols from the library at load time to prevent any
repeated `dlsym` calls.
- Add locks to prevent multiple concurrent FFI calls to functions that
act on the same state.
- Adds documentation/example in the go module `README`.
- Fixes memory access issue causing segfault due to passing pointer to
array of strings, that is difficult to work with in Go without the right
primitives. In place, simply return the amount of ResultColumns and Go
can provide the index to receive the column name, similar to
`rowsGetValue`
On next limbo release, I'll add the example to the main `README` next to
the other language examples. Until then, `go get
github.com/tursodatabase/limbo` will not work so the example will remain
in the bindings readme.
Closes#845
Instead of always having the caller specify all instructions, this
work introduces convenience functions into the program builder,
making the code a lot cleaner.
Draft for now, as this is done on top of #841
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#844