Commit Graph

128 Commits

Author SHA1 Message Date
Pekka Enberg
7f2525ac27 Merge 'Implement create virtual table using vtab modules, more work on virtual tables' from Preston Thorpe
This PR started out as one to improve the API of extensions but I ended
up building on top of this quite a bit and it just kept going. Sorry
this one is so large but there wasn't really a good stopping point, as
it kept leaving stuff in broken states.
**VCreate**: Support for `CREATE VIRTUAL TABLE t USING vtab_module`
**VUpdate**: Support for `INSERT` and `DELETE` methods on virtual
tables.
Sqlite uses `xUpdate` function with the `VUpdate` opcode to handle all
insert/update/delete functionality in virtual tables..
have to just document that:
```
if args[0] == NULL:  INSERT args[1] the values in args[2..]

if args[1] == NULL: DELETE args[0]

if args[0] != NULL && len(args) > 2: Update values=args[2..]  rowid=args[0]
```
I know I asked @jussisaurio on discord about this already, but it just
sucked so bad that I added some internal translation so we could expose
a [nice API](https://github.com/tursodatabase/limbo/pull/996/files#diff-
3e8f8a660b11786745b48b528222d11671e9f19fa00a032a4eefb5412e8200d1R54) and
handle the logic ourselves while keeping with sqlite's opcodes.
I'll change it back if I have to, I just thought it was genuinely awful
to have to rely on comments to explain all that to extension authors.
The included extension is not meant to be a legitimately useful one, it
is there for testing purposes. I did something similar in #960 using a
test extension, so I figure when they are both merged, I will go back
and combine them into one since you can do many kinds at once, and that
way it will reduce the amount of crates and therefore compile time.
1. Remaining opcodes.
2. `UPDATE` (when we support the syntax)
3. `xConnect` - expose API for a DB connection to a vtab so it can
perform arbitrary queries.

Closes #996
2025-02-25 15:31:12 +02:00
PThorpe92
9b742e1a76 Remove clone in vtab from_args 2025-02-17 22:37:17 -05:00
PThorpe92
8b5772fe1c Implement VUpdate (insert/delete for virtual tables 2025-02-17 20:44:44 -05:00
PThorpe92
9c8083231c Implement create virtual table and VUpdate opcode 2025-02-17 20:44:44 -05:00
Jussi Saurio
8e5499e5ed Fix not evaling constant conditions when no tables in query
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.
2025-02-17 13:10:27 +02:00
Jussi Saurio
a7300a4e0c select: fix bug with referring to a mixed-case alias 2025-02-14 16:40:58 +02:00
Pekka Enberg
ac54c35f92 Switch to workspace dependencies
...makes it easier to specify a version, which is needed for `cargo publish`.
2025-02-12 17:28:04 +02:00
Jussi Saurio
9e70e8fe02 Add basic CTE support 2025-02-08 14:50:05 +02:00
Jussi Saurio
338c27dad6 introduce Scope and Cte structs 2025-02-08 14:49:46 +02:00
PThorpe92
ae88d51e6f Remove TableReferenceType enum to clean up planner 2025-02-06 09:15:39 -05:00
PThorpe92
d4c06545e1 Refactor vtable impl and remove Rc Refcell from module 2025-02-06 09:15:39 -05:00
Jussi Saurio
f5f77c0bd1 Initial virtual table implementation 2025-02-06 07:51:50 -05:00
Jussi Saurio
795576b2ec dont eagerly allocate result column name strings 2025-02-05 17:53:23 +02:00
Jussi Saurio
1e5501650a Support column aliases in GROUP BY, ORDER BY and HAVING 2025-02-03 10:44:05 +02:00
Pekka Enberg
662d629666 Rename JoinAwareConditionExpr to WhereTerm
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).
2025-02-03 07:46:51 +02:00
Jussi Saurio
16a97d3b98 planner.rs: refactor from/join + where parsing logic
- 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.
2025-02-02 10:18:13 +02:00
ben594
54a6505b33 Handle negative limits and offsets 2025-01-26 16:40:30 -05:00
ben594
d03a0dbd39 Added parsing of offset clause 2025-01-26 16:40:30 -05:00
Jorge López
50852f36f8 syntactic changes: semantics, call is_empty instead of manually checking the size 2025-01-18 19:20:12 +01:00
Jorge López
3da813b260 syntactic changes: use if let .. else instead of checking for is_none() and calling unwrap() 2025-01-18 19:20:12 +01:00
Jorge López
218a2e6dda syntactic changes: remove unneeded mut, lifetimes,references that get instantaneously dereferenced and casts 2025-01-18 18:43:47 +01:00
Jorge López
86a4714711 syntactic changes: remove unneeded paths when the type is already imported 2025-01-18 18:29:12 +01:00
Levy A.
08c8c655e9 feat: initial implementation of Statement::bind 2025-01-15 16:51:04 -03:00
Kould
1bf651bd37 chore: rollback using rowid(sqlite3 unsupported) 2025-01-14 22:56:49 +08:00
Kould
5305a9d0fd feat: support keyword rowid 2025-01-14 22:41:40 +08:00
PThorpe92
3412a3d4c2 Rough design for extension api/draft extension 2025-01-14 07:20:48 -05:00
Jussi Saurio
1bcdf99eab core/optimizer: do expression rewriting on all expressions 2025-01-10 10:04:07 +02: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
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
Jussi Saurio
f434b24e63 Fix limbo/core to work with new boxed ast types 2025-01-05 13:51:34 +02:00
Jussi Saurio
80b9da95c0 replace termination_label_stack with much simpler LoopLabels 2025-01-01 07:56:39 +02:00
Jussi Saurio
2066475e03 feat: subqueries in FROM clause 2024-12-31 14:18:29 +02:00
Pekka Enberg
3046757d09 core/translate: Move prepare_delete_plan() to delete.rs
The planner.rs file is pretty big. Let's make it smaller by moving more
of delete handling to delete.rs.
2024-12-31 11:40:35 +02:00
Pekka Enberg
cb5d86ed8e core/translate: Move prepare_select_plan() to select.rs
The planner.rs file is pretty big. Let's make it smaller by moving more
of select handling to select.rs.
2024-12-31 11:38:13 +02:00
Pekka Enberg
f6149d3bd7 core/translate: Kill unused lifetimes 2024-12-31 11:33:17 +02:00
Lauri Virtanen
854005b977 Run cargo clippy --fix && cargo fmt 2024-12-29 19:22:28 +02:00
김선우
ad2d515ffd Merge branch 'main' into feature/delete-planning 2024-12-27 23:21:35 +09:00
Pekka Enberg
b2f96ddfbd core/translate: Remove unnecessary mut 2024-12-27 10:55:31 +02:00
Pekka Enberg
244326ee57 core: Remove unused imports 2024-12-27 10:55:31 +02:00
김선우
56165fb0d6 Merge branch 'main' into feature/delete-planning 2024-12-24 12:29:19 +09:00
김선우
906975e1ca Add limit support 2024-12-24 12:25:04 +09:00
PThorpe92
fbf42458b8 Use custom expr equality check in translation and planner 2024-12-22 21:46:31 -05:00
김선우
357ab551a5 nit 2024-12-23 07:42:12 +09:00
김선우
5cdcb8d78c Split Plan into Select and Delete 2024-12-23 05:45:23 +09:00
김선우
f8d4edc8d7 Use schema.get_table(...) instead of referencing directly 2024-12-23 04:54:40 +09:00
김선우
1d3ce52812 Refactor planner and optimizer to be DRY 2024-12-22 15:11:26 +09:00
김선우
57c7a56e35 Apply fmt, clippy 2024-12-22 14:27:21 +09:00
김선우
9a8b94ef93 First successful implementation of delete planning 2024-12-22 13:16:16 +09:00
Kacper Madej
9e01c22a5e Handle quoting identifiers properly 2024-12-18 19:45:06 +01:00
Pekka Enberg
61269e9c03 Merge 'Fix primary key handling' from Jussi Saurio
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
2024-12-16 18:49:19 +02:00