We were not evaluating constant conditions (e.g '1 IS NULL')
when there were no tables referenced in the query, because
our WHERE term evaluation was based on "during which loop"
to evaluate them. However, when there are no tables, there are
no loops, so they were never evaluated.
We transform all JOIN conditions into WHERE clause terms in the query
planner. The JoinAwareConditionExpr name tries to make that point, but I
think it makes things more confusing. Let's call it WhereTerm (suggested
by Jussi).
- 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
SQLite holds on to it deeply, for example:
sqlite> create table a(a int);
sqlite> create table b(b integer);
sqlite> create table c(c glauber);
sqlite> pragma table_info=a;
0|a|INT|0||0
sqlite> pragma table_info=b;
0|b|INTEGER|0||0
sqlite> pragma table_info=c;
0|c|glauber|0||0
So we'll keep it as well so we can produce the same responses.
Closes#438
**Fixes:**
- Return the actual primary key instead of the rowid when the primary
key is not a rowid alias
sqlite:
```
limbo> create table foo (pk TEXT PRIMARY KEY, value);
sqlite> insert into foo values ('one', 'payload');
sqlite> insert into foo values ('two', 'payload');
sqlite> select * from foo;
one|payload
two|payload
```
limbo now:
```
limbo> create table foo (pk TEXT PRIMARY KEY, value);
limbo> insert into foo values ('one', 'payload');
limbo> insert into foo values ('two', 'payload');
limbo> select * from foo;
one|payload
two|payload
```
limbo before:
```
limbo> select * from foo;
1|payload
2|payload
```
Then, discovered two issues when running the whole TCL test suite
against a copy of `testing.db` that does not have rowid aliases in the
tables:
- Fix trying to convert a Scan into an IndexSearch when the associated
Expr refers to a different instance of the same table in a self-join
- Fix `scan_loop_body_labels` being pushed to in different parts of the
codegen for Scan/Search nodes resulting in incorrect label resolutions
**Additions:**
- Add a new db `testing/testing_norowidalias.db` that is a carbon copy
of `testing/testing.db` except the `id` columns of `users` and
`products` are not rowid aliases (i.e. they are `INT PRIMARY KEY`
instead of `INTEGER PRIMARY KEY`
- Run all TCL tests against both test databases with `do_execsql_test`
```
(testing/testing.db) Running test: coalesce-from-table
(testing/testing_norowidalias.db) Running test: coalesce-from-table
(testing/testing.db) Running test: coalesce-from-table-column
(testing/testing_norowidalias.db) Running test: coalesce-from-table-column
(testing/testing.db) Running test: coalesce-from-table-multiple-columns
(testing/testing_norowidalias.db) Running test: coalesce-from-table-multiple-columns
(testing/testing.db) Running test: glob-fn
(testing/testing_norowidalias.db) Running test: glob-fn
(testing/testing.db) Running test: where-glob
(testing/testing_norowidalias.db) Running test: where-glob
(testing/testing.db) Running test: where-glob-question-mark
(testing/testing_norowidalias.db) Running test: where-glob-question-mark
```
- Allow running tests against specific db file with
`do_execsql_test_on_specific_db $path`
- Wondering if I should add a new table with e.g. text primary key and
add some db-specific tests on that table...?
Closes#449
Mimics SQLite's EXPLAIN QUERY PLAN pretty printer.
Example run on a preexisting db:
```
$ cargo run /tmp/srn "explain query plan select * from t natural join t join t2 on t.id = 2*t2.id where t.id in (select * from t);"
QUERY PLAN
`--JOIN ON t.id = 2 * t2.id
|--JOIN
| |--SCAN t FILTER t.id IN (SELECT * FROM t)
| `--SCAN t
`--SCAN t2
```
Fixes https://github.com/penberg/limbo/issues/295