Commit Graph

175 Commits

Author SHA1 Message Date
Pere Diaz Bou
c0e51c4ca6 wip wal 2024-11-05 15:29:53 +01:00
jussisaurio
daf5863932 manual fixes based on clippy suggestions 2024-10-13 12:19:04 +03:00
jussisaurio
f634e7f7a3 clippy fix 2024-10-13 12:08:54 +03:00
jussisaurio
b3c57d5691 core/translate: (refactor) use btreetablereference struct instead of tuple 2024-10-13 11:25:33 +03:00
Pekka Enberg
bf2e254a21 Merge 'core/translate/optimizer: eliminate unnecessary ORDER BY if result set is already ordered' from Jussi Saurio
Built on top of, and currently targets, #350, _not_ main
Closes #365
Examples:
```
limbo> explain select u.first_name, p.name from users u join products p on u.id = p.id order by u.id;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     15    0                    0   Start at 15
1     OpenReadAsync      0     2     0                    0   table=u, root=2
2     OpenReadAwait      0     0     0                    0
3     OpenReadAsync      1     3     0                    0   table=p, root=3
4     OpenReadAwait      0     0     0                    0
5     RewindAsync        0     0     0                    0
6     RewindAwait        0     14    0                    0   Rewind table u
7       RowId            0     1     0                    0   r[1]=u.rowid
8       SeekRowid        1     1     12                   0   if (r[1]!=p.rowid) goto 12
9       Column           0     1     2                    0   r[2]=u.first_name
10      Column           1     1     3                    0   r[3]=p.name
11      ResultRow        2     2     0                    0   output=r[2..3]
12    NextAsync          0     0     0                    0
13    NextAwait          0     7     0                    0
14    Halt               0     0     0                    0
15    Transaction        0     0     0                    0
16    Goto               0     1     0                    0
```
```
limbo> explain select * from users where age > 80 order by age limit 5;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     23    0                    0   Start at 23
1     OpenReadAsync      0     2     0                    0   table=users, root=2
2     OpenReadAwait      0     0     0                    0
3     OpenReadAsync      1     274   0                    0   table=age_idx, root=274
4     OpenReadAwait      0     0     0                    0
5     Integer            80    1     0                    0   r[1]=80
6     SeekGT             1     22    1                    0
7       DeferredSeek     1     0     0                    0
8       RowId            0     2     0                    0   r[2]=users.rowid
9       Column           0     1     3                    0   r[3]=users.first_name
10      Column           0     2     4                    0   r[4]=users.last_name
11      Column           0     3     5                    0   r[5]=users.email
12      Column           0     4     6                    0   r[6]=users.phone_number
13      Column           0     5     7                    0   r[7]=users.address
14      Column           0     6     8                    0   r[8]=users.city
15      Column           0     7     9                    0   r[9]=users.state
16      Column           0     8     10                   0   r[10]=users.zipcode
17      Column           0     9     11                   0   r[11]=users.age
18      ResultRow        2     10    0                    0   output=r[2..11]
19      DecrJumpZero     12    22    0                    0   if (--r[12]==0) goto 22
20    NextAsync          1     0     0                    0
21    NextAwait          1     7     0                    0
22    Halt               0     0     0                    0
23    Transaction        0     0     0                    0
24    Integer            5     12    0                    0   r[12]=5
25    Goto               0     1     0                    0
```

Closes #366
2024-10-13 10:12:28 +03:00
Pekka Enberg
fdf3b0d16b Merge '(core): Primary key index scans and single-column secondary index scans' from Jussi Saurio
This PR adds an index on `users.age` to `testing.db`, and support for
indexed lookups. Only single-column ascending indexes are currently
supported.
This PR also gets rid of `Operator::Seekrowid` in favor of
`Operator::Search` which handles all non-full-table-scan searches: 1.
integer primary key (rowid) point queries 2. integer primary key index
scans, and 3. secondary index scans.
examples:
```
limbo> select first_name, age from users where age > 90 limit 10;
Miranda|90
Sarah|90
Justin|90
Justin|90
John|90
Jeremy|90
Stephanie|90
Joshua|90
Jenny|90
Jennifer|90

limbo> explain query plan select first_name, age from users where age > 90 limit 10;
QUERY PLAN
`--TAKE 10
   `--PROJECT first_name, age
   |  `--SEARCH users USING INDEX age_idx

limbo> explain select first_name, age from users where age > 90 limit 10;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     15    0                    0   Start at 15
1     OpenReadAsync      0     2     0                    0   table=users, root=2
2     OpenReadAwait      0     0     0                    0
3     OpenReadAsync      1     274   0                    0   table=age_idx, root=274
4     OpenReadAwait      0     0     0                    0
5     Integer            90    1     0                    0   r[1]=90
6     SeekGT             1     14    1                    0
7       DeferredSeek     1     0     0                    0
8       Column           0     1     2                    0   r[2]=users.first_name
9       Column           0     9     3                    0   r[3]=users.age
10      ResultRow        2     2     0                    0   output=r[2..3]
11      DecrJumpZero     4     14    0                    0   if (--r[4]==0) goto 14
12    NextAsync          1     0     0                    0
13    NextAwait          1     7     0                    0
14    Halt               0     0     0                    0
15    Transaction        0     0     0                    0
16    Integer            10    4     0                    0   r[4]=10
17    Goto               0     1     0                    0
```
Sqlite version:
```
sqlite> explain select first_name, age from users where age > 90 limit 10;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     13    0                    0   Start at 13
1     Integer        10    1     0                    0   r[1]=10; LIMIT counter
2     OpenRead       0     2     0     10             0   root=2 iDb=0; users
3     OpenRead       1     274   0     k(2,,)         0   root=274 iDb=0; age_idx
4     Integer        90    2     0                    0   r[2]=90
5     SeekGT         1     12    2     1              0   key=r[2]
6       DeferredSeek   1     0     0                    0   Move 0 to 1.rowid if needed
7       Column         0     1     3                    0   r[3]= cursor 0 column 1
8       Column         1     0     4                    0   r[4]= cursor 1 column 0
9       ResultRow      3     2     0                    0   output=r[3..4]
10      DecrJumpZero   1     12    0                    0   if (--r[1])==0 goto 12
11    Next           1     6     0                    0
12    Halt           0     0     0                    0
13    Transaction    0     0     3     0              1   usesStmtJournal=0
14    Goto           0     1     0                    0
```
---
´Seek` instructions are also now supported for primary key rowid
searches:
```
limbo> select id, first_name from users where id > 9995;
9996|Donald
9997|Ruth
9998|Dorothy
9999|Gina
10000|Nicole

limbo> explain query plan select id, first_name from users where id > 9995;
QUERY PLAN
`--PROJECT id, first_name
   `--SEARCH users USING INTEGER PRIMARY KEY (rowid=?)

limbo> explain select id, first_name from users where id > 9995;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     11    0                    0   Start at 11
1     OpenReadAsync      0     2     0                    0   table=users, root=2
2     OpenReadAwait      0     0     0                    0
3     Integer            9995  1     0                    0   r[1]=9995
4     SeekGT             0     10    1                    0
5       RowId            0     2     0                    0   r[2]=users.rowid
6       Column           0     1     3                    0   r[3]=users.first_name
7       ResultRow        2     2     0                    0   output=r[2..3]
8     NextAsync          0     0     0                    0
9     NextAwait          0     5     0                    0
10    Halt               0     0     0                    0
11    Transaction        0     0     0                    0
12    Goto               0     1     0                    0
```
sqlite:
```
sqlite> explain select id, first_name from users where id > 9995;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     8     0                    0   Start at 8
1     OpenRead       0     2     0     2              0   root=2 iDb=0; users
2     SeekGT         0     7     1                    0   key=r[1]; pk
3       Rowid          0     2     0                    0   r[2]=users.rowid
4       Column         0     1     3                    0   r[3]= cursor 0 column 1
5       ResultRow      2     2     0                    0   output=r[2..3]
6     Next           0     3     0                    0
7     Halt           0     0     0                    0
8     Transaction    0     0     3     0              1   usesStmtJournal=0
9     Integer        9995  1     0                    0   r[1]=9995
10    Goto           0     1     0                    0
```
---
More complex example with a join that uses both a rowid lookup and a
secondary index scan:
```
limbo> explain query plan select u.first_name, p.name from users u join products p on u.id = p.id and u.age > 70;
QUERY PLAN
`--PROJECT u.first_name, p.name
   `--JOIN
   |  |--SEARCH u USING INDEX age_idx
   |  `--SEARCH p USING INTEGER PRIMARY KEY (rowid=?)

limbo> explain select u.first_name, p.name from users u join products p on u.id = p.id and u.age > 70;
addr  opcode             p1    p2    p3    p4             p5  comment
----  -----------------  ----  ----  ----  -------------  --  -------
0     Init               0     18    0                    0   Start at 18
1     OpenReadAsync      0     2     0                    0   table=u, root=2
2     OpenReadAwait      0     0     0                    0
3     OpenReadAsync      1     274   0                    0   table=age_idx, root=274
4     OpenReadAwait      0     0     0                    0
5     OpenReadAsync      2     3     0                    0   table=p, root=3
6     OpenReadAwait      0     0     0                    0
7     Integer            70    1     0                    0   r[1]=70
8     SeekGT             1     17    1                    0
9       DeferredSeek     1     0     0                    0
10      RowId            0     2     0                    0   r[2]=u.rowid
11      SeekRowid        2     2     15                   0   if (r[2]!=p.rowid) goto 15
12      Column           0     1     3                    0   r[3]=u.first_name
13      Column           2     1     4                    0   r[4]=p.name
14      ResultRow        3     2     0                    0   output=r[3..4]
15    NextAsync          1     0     0                    0
16    NextAwait          1     9     0                    0
17    Halt               0     0     0                    0
18    Transaction        0     0     0                    0
19    Goto               0     1     0                    0
```
sqlite:
```
sqlite> explain select u.first_name, p.name from users u join products p on u.id = p.id and u.age > 70;
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     14    0                    0   Start at 14
1     OpenRead       0     2     0     10             0   root=2 iDb=0; users
2     OpenRead       2     274   0     k(2,,)         0   root=274 iDb=0; age_idx
3     OpenRead       1     3     0     2              0   root=3 iDb=0; products
4     Integer        70    1     0                    0   r[1]=70
5     SeekGT         2     13    1     1              0   key=r[1]
6       DeferredSeek   2     0     0                    0   Move 0 to 2.rowid if needed
7       IdxRowid       2     2     0                    0   r[2]=rowid; users.rowid
8       SeekRowid      1     12    2                    0   intkey=r[2]
9       Column         0     1     3                    0   r[3]= cursor 0 column 1
10      Column         1     1     4                    0   r[4]= cursor 1 column 1
11      ResultRow      3     2     0                    0   output=r[3..4]
12    Next           2     6     0                    0
13    Halt           0     0     0                    0
14    Transaction    0     0     3     0              1   usesStmtJournal=0
15    Goto           0     1     0                    0
```

Closes #350
2024-10-13 10:11:23 +03:00
jussisaurio
04ecbff7fc Eliminate unnecessary ORDER BY if result set is already ordered 2024-10-10 23:43:39 +03:00
Lauri Virtanen
0ae1412193 Add instr(X,Y) scalar function
Relates to issue #144
2024-10-06 20:19:37 +03:00
jussisaurio
bb1c8b65e8 fmt 2024-10-06 00:22:12 +03:00
jussisaurio
dde10d2dd7 Better EXPLAIN QUERY PLAN for Operator::Search 2024-10-06 00:19:56 +03:00
jussisaurio
47534cb8df Get rid of Seekrowid operator in favor of a unified Search operator 2024-10-06 00:11:38 +03:00
jussisaurio
d3e797f59e rewind_labels was renamed to scan_loop_body_labels 2024-10-05 18:27:18 +03:00
jussisaurio
d22dbe9840 remove garbage comment 2024-10-05 18:25:04 +03:00
jussisaurio
3a11887122 fixerinos 2024-10-05 18:25:04 +03:00
jussisaurio
e118b70127 fmt 2024-10-05 18:25:04 +03:00
jussisaurio
3d56fbd91c stuff 2024-10-05 18:25:04 +03:00
jussisaurio
f02da18acd index scan wip foo doesnt work yet 2024-10-05 18:25:04 +03:00
jussisaurio
d3015ad854 Merge 'Fix NextAwait's next instruction; rename rewind_labels' from Arpit Saxena
Closes #351
NextAwait's next instruction was pointing to RewindAwait earlier which
is not current. The instruction now points to the instruction after
RewindAwait, which will be the loop body. Hence, rename rewind_labels to
scan_loop_body_labels to make it clearer

Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>

Closes #354
2024-10-05 18:23:37 +03:00
Lauri Virtanen
9e80a0c4a8 Add randomblob(N) scalar function
Relates to issue #144
2024-10-03 00:05:23 +03:00
Pekka Enberg
6fcd818160 Merge 'Add unhex(X) scalar function' from Lauri Virtanen
This commit adds `unhex(X)` scalar function. Function with `unhex(X,Y)`
two arguments is not implemented yet.
Relates to issue #144

Closes #353
2024-10-02 11:01:15 +03:00
Arpit Saxena
47c8fd1964 Fix NextAwait's next instruction; rename rewind_labels
Closes #351

NextAwait's next instruction was pointing to RewindAwait earlier which
is not current. The instruction now points to the instruction after
RewindAwait, which will be the loop body. Hence, rename rewind_labels to
scan_loop_body_labels to make it clearer
2024-10-02 11:58:42 +05:30
Lauri Virtanen
adc6f9b6cd Add unhex(X) scalar function
This commit adds `unhex(X)` scalar function. Function with `unhex(X,Y)`
two arguments is not implemented yet.

Relates to issue #144
2024-09-30 00:13:43 +03:00
Lauri Virtanen
f612ead8a3 Add zeroblob(N) scalar function
Relates to issue #144
2024-09-29 23:39:53 +03:00
Lauri Virtanen
0597c048fc Better support for BLOBs
- Limbo command line shell supports e.g. `SELECT x'616263';`
- `EXPLAIN SELECT x'616263';` lists the opcode

Missing:

- Command line shell not entirely compatible with SQLite when blobs have
  non-printable characters in the middle (e.g. `SELECT x'610062';`)
- Python bindings not supported (incoming soon)
2024-09-22 17:55:00 +03:00
baishen
5c00c576a5 Add support for hex scalar function 2024-09-22 08:50:08 -04:00
Lauri Virtanen
67573e12e5 Add typeof(X) scalar function 2024-09-21 15:56:29 +03:00
김선우
bbd1eea9ae Add support for parenthesized conditions 2024-09-21 16:03:49 +09:00
Pekka Enberg
b67640c437 Merge 'core: constraint check uniqueness' from Pere Diaz Bou
```bash
limbo> insert into products values (1, 'asdf', 432);
Runtime error: UNIQUE constraint failed: products.id (19)
```

Closes #336
2024-09-20 13:27:10 +03:00
Pere Diaz Bou
c8e5673f7a core: constraint check uniqueness 2024-09-20 11:45:55 +02:00
김선우
e9ba458514 Add support for sqlite_version 2024-09-18 17:57:51 +09:00
Pekka Enberg
a8b8c1d2c9 Merge 'Fix clippy ' from Kim Seon Woo
### Changes
- Remove clippy warning messages
- Add `#[allow(clippy...)]` in places where it might be better not to
fix
### TODO
recommended changes by `cargo fmt` on my local and github differs on
`sqlite3/src/lib.rs`. Should check for the reason
=> just upgrade the rust toolchain

Closes #329
2024-09-18 09:46:07 +03:00
rjhallsted
f6b7a3fba4 Remove duplication of glob and like translation 2024-09-16 16:31:37 -07:00
rjhallsted
b87b874ed0 WIP commit on glob support 2024-09-16 15:51:32 -07:00
김선우
b68efa32d9 Merge branch 'main' into feature/fix-clippy 2024-09-16 21:58:07 +09:00
Pekka Enberg
9bbfdab5fa Revert "Merge 'Add support for sqlite_version() scalar function' from Kim Seon Woo"
This reverts commit e365c12ce0, reversing
changes made to 21bd1a961e. The pull request broke some tests:

```
thread 'main' panicked at core/vdbe/mod.rs:1713:72:
index out of bounds: the len is 3 but the index is 3
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    while executing
"exec {*}$command"
    (procedure "evaluate_sql" line 3)
    invoked from within
"evaluate_sql $sqlite_exec $sql"
    (procedure "run_test" line 2)
    invoked from within
"run_test $::sqlite_exec $combined_sql $combined_expected_output"
    (procedure "do_execsql_test" line 5)
    invoked from within
"do_execsql_test sqlite_version {
  SELECT sqlite_version();
} {3.46.1}"
    (file "./testing/scalar-functions.test" line 434)
    invoked from within
"source $testdir/scalar-functions.test"
    (file "./testing/all.test" line 16)
make: *** [Makefile:59: test-compat] Error 1
```
2024-09-16 14:28:18 +03:00
Pekka Enberg
e365c12ce0 Merge 'Add support for sqlite_version() scalar function' from Kim Seon Woo
### sqlite
<img width="792" alt="image" src="https://github.com/user-
attachments/assets/1a9238db-d948-4583-a808-f9adfec7c534">
### limbo
<img width="809" alt="image" src="https://github.com/user-
attachments/assets/ea3e5f7e-bb3e-450d-be34-59ca00128beb">
### Changes
- Add support for `sqlite_version()` function
- Update function's explain message depending on the number of arguments

Closes #331
2024-09-16 14:18:19 +03:00
Pekka Enberg
21bd1a961e Merge 'Fix three issues with LIKE operator (#319)' from Jussi Saurio
Closes #319
1. Allow using a column as the pattern
2. Construct LIKE regexes with `^` and `$` so that eg the string
`'foobar'` does not match the pattern `'fooba'` unless the pattern
specifically has a wildcard
3. Support function expressions as the LIKE pattern

Closes #327
2024-09-16 14:17:48 +03:00
Pekka Enberg
95987f9824 Merge 'Support grouping by a function expression' from Jussi Saurio
Closes #326
2024-09-16 14:17:03 +03:00
김선우
6b40acabbc Add support for sqlite_version() scalar function 2024-09-16 18:38:42 +09:00
JeanArhancet
d03a734f21 feat: add sign function 2024-09-15 14:57:01 +02:00
김선우
28884181be Fix clippy 2024-09-15 16:23:27 +09:00
jussisaurio
3f0162c76c Support grouping by a function expression 2024-09-15 09:58:46 +03:00
jussisaurio
6b8cd02f71 Fix function expressions in like pattern not working 2024-09-15 09:57:54 +03:00
jussisaurio
234c56ca81 Fix two issues with LIKE operator (#319) 2024-09-15 09:57:54 +03:00
jussisaurio
b6e88ca883 cargo clippy --fix --allow-dirty && cargo fmt 2024-09-15 09:35:39 +03:00
김선우
fc07ca9d73 Add support for concat_ws 2024-09-14 23:47:45 +09:00
jussisaurio
a108dea825 GROUP BY 2024-09-14 16:14:45 +03:00
jussisaurio
0839211a49 Pass FuncCtx to Insn::Function to keep track of arg count 2024-09-14 12:38:14 +03:00
rjhallsted
dc3d3a492a Fix register positions of binary expression arguments to fix where-like-fn case 2024-09-12 12:03:27 -07:00
rjhallsted
960560dffc Use the same comment for Expr::Like case 2024-09-10 14:26:21 -07:00