Pekka Enberg
0b544717a1
Merge 'do not check rowid alias for null' from Nikita Sivukhin
...
Simple PR to check minor issue that `INTEGER PRIMARY KEY NOT NULL` (`NOT
NULL` is redundant here obviously) will prevent user to insert anything
to the table as rowid-alias column always set to null by `turso-db`
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com >
Closes #2063
2025-07-14 11:55:06 +03:00
Nikita Sivukhin
5409812610
properly implement generation of before/after records for new modes
2025-07-14 11:17:32 +04:00
Nikita Sivukhin
b258c10c9a
generate before/after row values in modification statements
2025-07-14 11:16:06 +04:00
Nikita Sivukhin
9129991b62
add id,before,after,full modes
2025-07-14 11:16:06 +04:00
Nils Koch
828d4f5016
fix clippy errors for rust 1.88.0 (auto fix)
2025-07-12 18:58:41 +03:00
Nikita Sivukhin
6d3bdf5b9e
do not check rowid alias for null
2025-07-12 14:07:26 +04:00
Nikita Sivukhin
62c1e38805
small fixes
2025-07-06 22:26:34 +04:00
Nikita Sivukhin
32fa2ac3ee
avoid capturing changes in cdc table
2025-07-06 22:24:35 +04:00
Nikita Sivukhin
a988bbaffe
allow to specify table in the capture_data_changes PRAGMA
2025-07-06 22:19:32 +04:00
Nikita Sivukhin
40769618c1
small refactoring
2025-07-06 21:16:58 +04:00
Nikita Sivukhin
04f2efeaa4
small renames
2025-07-06 21:16:57 +04:00
Nikita Sivukhin
a82529f55a
emit cdc changes for UPDATE / DELETE statements
2025-07-06 21:16:25 +04:00
Nikita Sivukhin
d72ba9877a
emit turso_cdc table changes in Insert query plan
2025-07-06 21:16:25 +04:00
Nikita Sivukhin
c9c5ef4e25
remote query_mode from ProgramBuilderOpts and from function arguments
...
- mode never changes and ProgramBuilder already created with proper mode set correctly
2025-07-02 13:24:12 +04:00
Pekka Enberg
725c3e4ddc
Rename limbo_sqlite3_parser crate to turso_sqlite3_parser
2025-06-29 12:34:46 +03:00
Pekka Enberg
2fc5c0ce5c
Switch to runtime flag for enabling indexes
...
Makes it easier to test the feature:
```
$ cargo run -- --experimental-indexes
Limbo v0.0.22
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database
limbo> CREATE TABLE t(x);
limbo> CREATE INDEX t_idx ON t(x);
limbo> DROP INDEX t_idx;
```
2025-06-26 10:07:28 +03:00
Pere Diaz Bou
e90996783b
clippy
2025-06-17 19:33:23 +02:00
Pere Diaz Bou
f91d2c5e99
fix disable in write cases
2025-06-17 19:33:23 +02:00
Pere Diaz Bou
b5f2f375b8
disable alter, delete, create index, insert and update for indexes
2025-06-17 19:33:23 +02:00
Pekka Enberg
db4945eada
Merge 'Fix update queries to set n_changes ' from Kim Seon Woo
...
- `Update` query doesn't update `n_changes`. Let's make it work
- Add `InsertFlags` to add meta information related to insert operations
- For update query, add `UPDATE` flag
- Currently, the update query executes `Insn::Delete` and `Insn::Insert`
internally, it increases `n_change` by 2. So, for the update query,
let's skip increasing `n_change` for the `Insn::Insert`
https://github.com/tursodatabase/limbo/issues/1681
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com >
Closes #1683
2025-06-16 16:30:20 +03:00
pedrocarlo
fef9add773
emit parse error instead of corrupt error for no such table
2025-06-14 18:45:23 -03:00
Jussi Saurio
30e4511d62
Merge 'NOT NULL constraint' from Anton Harniakou
...
Implements basic support for `NOT NULL` contraint check.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com >
Closes #1675
2025-06-13 14:25:24 +03:00
Levy A.
15e0cab8d8
refactor+fix: precompute default values from schema
2025-06-11 14:18:39 -03:00
김선우
a9c096bb01
Skip increasing n_changes for insn::Insert when it's UPDATE query
2025-06-07 17:23:23 +09:00
Anton Harniakou
fb86476525
Implement basic not null constraint checks
2025-06-05 19:02:31 +03:00
Jussi Saurio
77ce4780d9
Fix ProgramBuilder::cursor_ref not having unique keys
...
Currently we have this:
program.alloc_cursor_id(Option<String>, CursorType)`
where the String is the table's name or alias ('users' or 'u' in
the query).
This is problematic because this can happen:
`SELECT * FROM t WHERE EXISTS (SELECT * FROM t)`
There are two cursors, both with identifier 't'. This causes a bug
where the program will use the same cursor for both the main query
and the subquery, since they are keyed by 't'.
Instead introduce `CursorKey`, which is a combination of:
1. `TableInternalId`, and
2. index name (Option<String> -- in case of index cursors.
This should provide key uniqueness for cursors:
`SELECT * FROM t WHERE EXISTS (SELECT * FROM t)`
here the first 't' will have a different `TableInternalId` than the
second `t`, so there is no clash.
2025-05-29 00:59:24 +03:00
Jussi Saurio
d2a287f67f
Add Schema reference to Resolver - needed for adhoc subquery planning
2025-05-27 19:12:47 +03:00
pedrocarlo
ee93316c46
fix num_values detection + emitting correct column for temp_table + tests
2025-05-25 19:15:28 -03:00
pedrocarlo
e3fd1e589e
support using a INSERT SELECT that references the same table in both statements
2025-05-25 19:15:28 -03:00
pedrocarlo
90e3c8483d
tests with compound select
2025-05-25 19:15:28 -03:00
pedrocarlo
c8144340a0
adjust proper ordering for value insert
2025-05-25 19:12:30 -03:00
pedrocarlo
810211b3d1
passing incorrect number of values to virtual table insert
2025-05-25 19:12:30 -03:00
pedrocarlo
4bcfc8ca60
create separate function to populate multiple columns in a multi-row VALUES clause or in an INSERT INTO <table> SELECT. Virtual Table insert is broken, need to fix it still
2025-05-25 19:12:30 -03:00
pedrocarlo
bb7da39c72
remove assumption that translate_select is always called from a top-level context + adjust insert to use translate_select when needed
2025-05-25 19:12:30 -03:00
pedrocarlo
fd9e0db5cc
pass the owned ast to translate_insert + remove assumption of a list of values in populate_columns_insert
2025-05-25 19:02:17 -03:00
pedrocarlo
15ffdd3e51
modify translate_select to return number of result columns
2025-05-25 19:02:17 -03:00
Jussi Saurio
8bec75d804
Merge 'Initial Support for Nested Translation' from Pedro Muniz
...
This PR introduces some modifications to the Program Builder to allow us
to use nested parsing. By focusing the emission of Init and the last
Goto (prologue and epilogue), inside the ProgramBuilder, we can just not
emit them if we are parsing/translating in a nested context. For this
PR, I only migrated insert to use these functions as I need them to
support Insert statements that use `SELECT FROM` syntax. Nested parsing
overall enables code reuse for us and arguably is one of the only ways
to parse deeply nested queries without a lot of code duplication.
#1528
Closes #1543
2025-05-22 10:52:00 +03:00
pedrocarlo
53bf5d5ef5
adjust translate functions to take a program instead of Option<ProgramBuilder> + remove any Init emission in traslate functions + use epilogue in all places necessary
2025-05-21 16:41:10 -03:00
pedrocarlo
1c12535d9f
push prologue to top-level translate function
2025-05-21 15:50:43 -03:00
pedrocarlo
3090dd91fa
push translate_ctx creation outside of prologue
2025-05-21 13:06:25 -03:00
pedrocarlo
fc08f786fc
use prologue and epilogue in insert
2025-05-21 12:47:51 -03:00
pedrocarlo
517c7c81cd
refactor to include optional program builder argument
2025-05-21 12:47:51 -03:00
Piotr Rzysko
9c1dca72db
Introduce VTable
...
This allows storing table arguments parsed in the VTabModule::create
method.
2025-05-21 08:33:17 +02:00
pedrocarlo
5f2216cf8e
modify explain for MakeRecord to show index name
2025-05-14 13:30:39 -03:00
pedrocarlo
5bae32fe3f
modified OpenWrite to include index or table name in explain
2025-05-14 13:30:39 -03:00
Jussi Saurio
1b71f58bbf
Merge 'Redesign parameter binding in query translator' from Preston Thorpe
...
closes #1467
## Example:
Previously as explained in #1449 , our parameter binding wasn't working
properly because we would essentially
assign the first index of whatever was translated first
```console
limbo> create table t (id integer primary key, name text, age integer);
limbo> explain select * from t where name = ? and id > ? and age between ? and ?;
addr opcode p1 p2 p3 p4 p5 comment
---- ----------------- ---- ---- ---- ------------- -- -------
0 Init 0 20 0 0 Start at 20
1 OpenRead 0 2 0 0 table=t, root=2
2 Variable 1 4 0 0 r[4]=parameter(1) # always 1
3 IsNull 4 19 0 0 if (r[4]==NULL) goto 19
4 SeekGT 0 19 4 0 key=[4..4]
5 Column 0 1 5 0 r[5]=t.name
6 Variable 2 6 0 0 r[6]=parameter(2) # always 2
7 Ne 5 6 18 0 if r[5]!=r[6] goto 18
8 Variable 3 7 0 0 r[7]=parameter(3) # etc...
9 Column 0 2 8 0 r[8]=t.age
10 Gt 7 8 18 0 if r[7]>r[8] goto 18
11 Column 0 2 9 0 r[9]=t.age
12 Variable 4 10 0 0 r[10]=parameter(4)
13 Gt 9 10 18 0 if r[9]>r[10] goto 18
14 RowId 0 1 0 0 r[1]=t.rowid
15 Column 0 1 2 0 r[2]=t.name
16 Column 0 2 3 0 r[3]=t.age
17 ResultRow 1 3 0 0 output=r[1..3]
18 Next 0 5 0 0
19 Halt 0 0 0 0
20 Transaction 0 0 0 0 write=false
21 Goto 0 1 0 0
```
## Solution:
`rewrite_expr` currently is used to transform `true|false` to `1|0`, so
it has been adapted to transform anonymous `Expr::Variable`s to named
variables, inserting the appropriate index of the parameter by passing
in a counter.
```rust
ast::Expr::Variable(var) => {
if var.is_empty() {
// rewrite anonymous variables only, ensure that the `param_idx` starts at 1 and
// all the expressions are rewritten in the order they come in the statement
*expr = ast::Expr::Variable(format!("{}{param_idx}", PARAM_PREFIX));
*param_idx += 1;
}
Ok(())
}
```
# Corrected output: (notice the seek)
```console
limbo> explain select * from t where name = ? and id > ? and age between ? and ?;
addr opcode p1 p2 p3 p4 p5 comment
---- ----------------- ---- ---- ---- ------------- -- -------
0 Init 0 20 0 0 Start at 20
1 OpenRead 0 2 0 0 table=t, root=2
2 Variable 2 4 0 0 r[4]=parameter(2)
3 IsNull 4 19 0 0 if (r[4]==NULL) goto 19
4 SeekGT 0 19 4 0 key=[4..4]
5 Column 0 1 5 0 r[5]=t.name
6 Variable 1 6 0 0 r[6]=parameter(1)
7 Ne 5 6 18 0 if r[5]!=r[6] goto 18
8 Variable 3 7 0 0 r[7]=parameter(3)
9 Column 0 2 8 0 r[8]=t.age
10 Gt 7 8 18 0 if r[7]>r[8] goto 18
11 Column 0 2 9 0 r[9]=t.age
12 Variable 4 10 0 0 r[10]=parameter(4)
13 Gt 9 10 18 0 if r[9]>r[10] goto 18
14 RowId 0 1 0 0 r[1]=t.rowid
15 Column 0 1 2 0 r[2]=t.name
16 Column 0 2 3 0 r[3]=t.age
17 ResultRow 1 3 0 0 output=r[1..3]
18 Next 0 5 0 0
19 Halt 0 0 0 0
20 Transaction 0 0 0 0 write=false
21 Goto 0 1 0 0
```
## And a `Delete`:
```console
limbo> explain delete from t where name = ? and age > ? and id > ?;
addr opcode p1 p2 p3 p4 p5 comment
---- ----------------- ---- ---- ---- ------------- -- -------
0 Init 0 15 0 0 Start at 15
1 OpenWrite 0 2 0 0
2 Variable 3 1 0 0 r[1]=parameter(3)
3 IsNull 1 14 0 0 if (r[1]==NULL) goto 14
4 SeekGT 0 14 1 0 key=[1..1]
5 Column 0 1 2 0 r[2]=t.name
6 Variable 1 3 0 0 r[3]=parameter(1)
7 Ne 2 3 13 0 if r[2]!=r[3] goto 13
8 Column 0 2 4 0 r[4]=t.age
9 Variable 2 5 0 0 r[5]=parameter(2)
10 Le 4 5 13 0 if r[4]<=r[5] goto 13
11 RowId 0 6 0 0 r[6]=t.rowid
12 Delete 0 0 0 0
13 Next 0 5 0 0
14 Halt 0 0 0 0
15 Transaction 0 1 0 0 write=true
16 Goto 0 1 0 0
```
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com >
Closes #1475
2025-05-14 09:26:06 +03:00
PThorpe92
2f255524bd
Remove unused import and unnecessary mut annotations in insert.rs
2025-05-13 14:34:22 -04:00
PThorpe92
0593a99f0e
Remove insertCtx from parameters and replace fix with expr rewriting
2025-05-13 12:49:16 -04:00
Jussi Saurio
957fe1b446
Fix infinite loop when inserting multiple rows
2025-05-13 08:54:25 +03:00
PThorpe92
ab23f2a24f
Add comments and reorganize fix of ordering parameters for insert statements
2025-05-11 14:20:57 -04:00