Commit Graph

212 Commits

Author SHA1 Message Date
jussisaurio
7d5fa12bb7 fix allocating wrong number of registers upfront for aggregation results 2024-11-26 17:31:51 +02:00
jussisaurio
56b15193d0 resolve aggregates from orderby as well 2024-11-26 17:31:51 +02:00
jussisaurio
885b6ecd76 Remove 'cursor_hint': it is never needed 2024-11-26 17:31:51 +02:00
jussisaurio
008be10cfd Add TODO about expression equality comparisons 2024-11-26 17:31:51 +02:00
jussisaurio
cfb7e79601 Function doc comments 2024-11-26 17:31:51 +02:00
jussisaurio
fc33c70481 remove many unnecessary fields from SortMetadata and GroupByMetadata 2024-11-26 17:31:51 +02:00
jussisaurio
ebce78bcd9 rename 2024-11-26 17:31:51 +02:00
jussisaurio
0510e150d3 fix comment 2024-11-26 17:31:51 +02:00
jussisaurio
1c37d8b24b extract function sorter_insert() 2024-11-26 17:31:51 +02:00
jussisaurio
4f3da982c0 extract function emit_result_row() 2024-11-26 17:31:51 +02:00
jussisaurio
52beeabd45 tweaks 2024-11-26 17:31:51 +02:00
jussisaurio
120601f732 fix metadata comments 2024-11-26 17:31:51 +02:00
jussisaurio
97ba4a788e remove sorts hashmap - only one sortmetadata struct is needed 2024-11-26 17:31:51 +02:00
jussisaurio
d2f84edd2e fix accidentally removing push_scan_direction() 2024-11-26 17:31:51 +02:00
jussisaurio
7ecc252507 fix rest of the failing tests 2024-11-26 17:31:51 +02:00
jussisaurio
9a557516b8 Fixes for expressions with aggregate arguments + limit 0 2024-11-26 17:31:51 +02:00
jussisaurio
cc902ed25d GROUP BY and ORDER BY mostly work 2024-11-26 17:31:51 +02:00
jussisaurio
3f9e60633f select refactor: order by and basic agg kinda work 2024-11-26 17:31:51 +02:00
jussisaurio
d0466e1cae introduce Column member of ast::Expr and bind idents to columns 2024-11-26 17:31:51 +02:00
jussisaurio
418ad40401 Merge 'Fix some Clippy warnings' from Lauri Virtanen
Reviewed-by: Pere Diaz Bou <limeng.1@bytedance.com>

Closes #417
2024-11-25 16:43:06 +02:00
Lauri Virtanen
cafbf5499f Support divide operator in expressions 2024-11-24 22:10:07 +02:00
Lauri Virtanen
afeb1cbe74 Clippy warning fixes 2024-11-24 20:24:47 +02:00
limeng.1
5e9e701417 resolve comments 2024-11-19 11:39:08 +08:00
limeng.1
1cb1d16c08 resolve comments 2024-11-19 11:39:08 +08:00
limeng.1
8cca659052 impl order by desc 2024-11-19 11:39:07 +08:00
jussisaurio
b86501f12e Merge 'implement CAST(col as type)' from Jussi Saurio
Closes #398

Reviewed-by: Pere Diaz Bou <pere-altea@hotmail.com>

Closes #404
2024-11-18 20:53:58 +02:00
Pere Diaz Bou
9c4ca28bd9 Merge 'CREATE TABLE support' from Pekka Enberg
Closes #383
2024-11-18 13:40:20 +01:00
Pekka Enberg
5efc218e6e Merge 'support subtract in translate_expr() (not in condition expressions yet)' from Jussi Saurio
closes #402

Closes #403
2024-11-18 09:28:23 +02:00
jussisaurio
62761d2b34 uppercase only once 2024-11-17 22:22:03 +02:00
jussisaurio
ddd0cc041c implement CAST(col as type) 2024-11-17 22:12:22 +02:00
jussisaurio
491bdd3bfc support subtract in translate_expr() (not in condition expressions yet) 2024-11-17 18:47:16 +02:00
jussisaurio
9a4864bc6a support parenthesized(single expr) in translate_expr() 2024-11-17 18:36:30 +02:00
jussisaurio
ccdcf302ca quick fix for #399 2024-11-17 17:06:09 +02:00
Pere Diaz Bou
d1dee484df properly format table and "if not exists" support 2024-11-16 17:02:53 +01:00
Pere Diaz Bou
090615b289 create btree table + parse schema 2024-11-16 16:24:28 +01:00
Pekka Enberg
fc5e42bb94 CREATE TABLE support 2024-11-16 13:07:10 +01:00
Pekka Enberg
cd5db55cf2 core: Make JSON support configurable
This adds a `json` feature flag, which allows users to disable JSON
support if needed.
2024-11-16 09:49:09 +02:00
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