themixednuts
fa19ba4993
chore: add tests
2025-09-02 10:58:00 -05:00
TcMits
635402fc6f
string sometimes used as identifier quoting
2025-09-02 21:35:37 +07:00
Piotr Rzysko
569e41cb1e
Skip traversing children of aggregate functions
...
Aggregate functions cannot be nested, and this is validated during the
translation of aggregate function arguments. Therefore, traversing their
child expressions is unnecessary.
2025-09-02 08:22:37 +02:00
Piotr Rzysko
9b742a64c2
Handle functions with star argument wrapped in expressions
...
Handled in the same way as in `prepare_one_select_plan` for bare
function calls.
2025-09-02 08:22:36 +02:00
Piotr Rzysko
f3cbc382ce
Support external aggregate functions wrapped in expressions
...
Handled in the same way as in `prepare_one_select_plan` for bare
function calls. In `prepare_one_select_plan`, however, resolving
external scalar functions is performed unnecessarily twice.
2025-09-02 08:22:36 +02:00
Pekka Enberg
7189e98455
Merge 'Unify handling of grouped and ungrouped aggregations' from Piotr Rżysko
...
The initial commits fix issues and plug gaps between ungrouped and
grouped aggregations.
The final commit consolidates the code that emits `AggStep` to prevent
future disparities between the two.
Reviewed-by: Preston Thorpe <preston@turso.tech >
Closes #2867
2025-09-02 09:11:40 +03:00
Pekka Enberg
cfaba4ab10
Merge 'Implement libSQL's ALTER COLUMN extension' from Levy A.
...
Implement `ALTER COLUMN` as described here:
https://github.com/tursodatabase/libsql/blob/main/libsql-
sqlite3/doc/libsql_extensions.md#altering-columns
- [x] Add `ALTER COLUMN` to parser
- [x] Implement `Insn::AlterColumn`
- [x] Add tests
Closes #2814
2025-09-02 09:06:03 +03:00
themixednuts
b6e64587cb
fix: jsonb functions to check if binary is json string
...
chore: match sqlite error
chore: use existing slice variable
add better parsing logic, and validation
see sqlite source code @ sqlite/src/json.c -> static int jsonArgIsJsonb
chore: clippy
2025-09-01 19:52:57 -05:00
PThorpe92
f02e02af75
Fix TCL test
2025-09-01 11:39:43 -04:00
PThorpe92
bd9d6aa168
Add edge-case tests for boolean literals
2025-09-01 11:27:43 -04:00
PThorpe92
46f5565faf
Add more tests for boolean literals
2025-09-01 11:25:16 -04:00
PThorpe92
46182aa7ed
add test for inserting boolean literals
2025-09-01 11:25:10 -04:00
Piotr Rzysko
0a85883ee2
Support external aggregate functions in GROUP BY
2025-08-31 12:02:11 +02:00
Piotr Rzysko
7d179bd9fe
Fix handling of multiple arguments in aggregate functions
...
This bug occurred when arguments were read for the GROUP BY sorter — all
arguments were incorrectly resolved to the first column. Added tests
confirm that aggregates now work correctly both with and without the
sorter.
2025-08-31 12:02:11 +02:00
Piotr Rzysko
3ad4016080
Fix handling of zero-argument grouped aggregations
...
This commit consolidates the creation of the Aggregate struct, which was
previously handled differently in `prepare_one_select_plan` and
`resolve_aggregates`. That discrepancy caused inconsistent handling of
zero-argument aggregates.
The queries added in the new tests would previously trigger a panic.
2025-08-31 12:02:09 +02:00
Piotr Rzysko
978a78b79a
Handle COLLATE clause in grouped aggregations
...
Previously, it was only applied to ungrouped aggregations.
2025-08-31 06:51:26 +02:00
Levy A.
293865c2d6
feat+fix: add tests and restrict altering some constraints
2025-08-30 03:43:31 -03:00
Pekka Enberg
e1b5f2d948
Merge 'Implement UPSERT' from Preston Thorpe
...
This PR closes #2019
Implements https://sqlite.org/lang_upsert.html
Closes #2853
2025-08-30 08:54:35 +03:00
Pekka Enberg
13057c8013
testing: Improve insert.test for STRICT mode type case insensitivity
2025-08-30 08:52:05 +03:00
Pekka Enberg
b22f184a19
Merge 'Fix column case sensitivity on strict table' from
...
closes : #2822
```
turso> insert into strict_table values (1);
turso>
```
Closes #2823
2025-08-30 08:45:28 +03:00
Pekka Enberg
ca7f1002b4
Merge 'Change views to use DBSP circuits' from Glauber Costa
...
Instead of using static elements, use a dynamically generated DBSP-
circuit to keep views.
The DBSP circuit is generated from the logical plan, which only supports
enough for us to generate the DBSP circuit at the moment.
The state of the view is still kept inside the IncrementalView, instead
of materialized at the operator level. As a consequence, this still
depends on us always populating the view at startup. Fixing this is the
next step.
Closes #2815
2025-08-30 08:44:06 +03:00
themixednuts
f9b0c0aa27
chore: add update test to lowercase
...
Instead of making a new test that would be the same, just updated this one to show that sqlite and turso (with this pr) match and isnt case sensitive in strict tables.
2025-08-29 20:24:43 -05:00
PThorpe92
3ab2126c89
Comment out tests that require COLLLATE in unique index creation
2025-08-29 20:58:44 -04:00
PThorpe92
c659a0e4d4
Update upsert test to be more relevant to the exact behavior
2025-08-29 20:58:44 -04:00
PThorpe92
007675a081
Add some more tests for upsert
2025-08-29 20:58:44 -04:00
PThorpe92
1120d73931
Add a bunch of UPSERT tests
2025-08-29 20:58:43 -04:00
PThorpe92
6619b6e5a0
Add upsert test module to tcl tests
2025-08-29 20:58:43 -04:00
Piotr Rzysko
e33c2e0f0b
Fix sorter column deduplication
...
Previously, the added test case failed because the last result column
was missing - a nonexistent column in the sorter was referenced.
2025-08-28 09:49:55 +02:00
Glauber Costa
143c84c4e0
add tests for rollback of views.
2025-08-27 14:21:32 -05:00
bit-aloo
881b986302
improve the limi exprs test with foreach block
2025-08-26 19:56:25 +05:30
bit-aloo
05267454dc
remove redundant step during limit/offset evaluation and add test coverage most of the datatypes and some expression
2025-08-26 19:56:25 +05:30
bit-aloo
26d71603ac
add a test to test limit expressiveness
2025-08-26 19:56:12 +05:30
Jussi Saurio
3905f0af46
Add regression test for issue 2794
2025-08-26 09:21:58 +03:00
Glauber Costa
097510216e
implement the projector operator for DBSP
...
My goal with this patch is to be able to implement the ProjectOperator
for DBSP circuits using VDBE for expression evaluation.
*not* doing so is dangerous for the following reason: we will end up
with different, subtle, and incompatible behavior between SQLite
expressions if they are used in views versus outside of views.
In fact, even in our prototype had them: our projection tests, which
used to pass, were actually wrong =) (sqlite would return something
different if those functions were executed outside the view context)
For optimization reasons, we single out trivial expressions: they don't
have go through VDBE. Trivial expressions are expressions that only
involve Columns, Literals, and simple operators on elements of the same
type. Even type coercion takes this out of the realm of trivial.
Everything that is not trivial, is then translated with translate_expr -
in the same way SQLite will, and then compiled with VDBE.
We can, over time, make this process much better. There are essentially
infinite opportunities for optimization here. But for now, the main
warts are:
* VDBE execution needs a connection
* There is no good way in VDBE to pass parameters to a program.
* It is almost trivial to pollute the original connection. For example,
we need to issue HALT for the program to stop, but seeing that halt
will usually cause the program to try and halt the original program.
Subprograms, like the ones we use in triggers are a possible solution,
but they are much more expensive to execute, especially given that our
execution would essentially have to have a program with no other role
than to wrap the subprogram.
Therefore, what I am doing is:
* There is an in-memory database inside the projection operator (an
obvious optimization is to share it with *all* projection operators).
* We obtain a connection to that database when the operator is created
* We use that connection to execute our VDBE, which offers a clean, safe
and isolated way to execute the expression.
* We feed the values to the program manually by editing the registers
directly.
2025-08-25 17:48:17 +03:00
Alex Miller
370da9fa59
ANALYZE creates sqlite_stat1 if it doesn't exist
...
This change replaces a bail_parse_error!() when sqlite_stat1 doesn't
exist with the appropriate codegen to create the table, and handle both
cases of the table existing or not existing.
SQLite's codegen looks like:
sqlite> create table stat_test(a,b,c);
sqlite> explain analyze stat_test;
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- ------------- -- -------------
0 Init 0 40 0 0 Start at 40
1 ReadCookie 0 3 2 0
2 If 3 5 0 0
3 SetCookie 0 2 4 0
4 SetCookie 0 5 1 0
5 CreateBtree 0 2 1 0 r[2]=root iDb=0 flags=1
6 OpenWrite 0 1 0 5 0 root=1 iDb=0
7 NewRowid 0 1 0 0 r[1]=rowid
8 Blob 6 3 0 0 r[3]= (len=6)
9 Insert 0 3 1 8 intkey=r[1] data=r[3]
10 Close 0 0 0 0
11 Close 0 0 0 0
12 Null 0 4 5 0 r[4..5]=NULL
13 Noop 4 0 4 0
14 OpenWrite 3 1 0 5 0 root=1 iDb=0; sqlite_master
15 SeekRowid 3 17 1 0 intkey=r[1]
16 Rowid 3 5 0 0 r[5]= rowid of 3
17 IsNull 5 26 0 0 if r[5]==NULL goto 26
18 String8 0 6 0 table 0 r[6]='table'
19 String8 0 7 0 sqlite_stat1 0 r[7]='sqlite_stat1'
20 String8 0 8 0 sqlite_stat1 0 r[8]='sqlite_stat1'
21 Copy 2 9 0 0 r[9]=r[2]
22 String8 0 10 0 CREATE TABLE sqlite_stat1(tbl,idx,stat) 0 r[10]='CREATE TABLE sqlite_stat1(tbl,idx,stat)'
23 MakeRecord 6 5 4 BBBDB 0 r[4]=mkrec(r[6..10])
24 Delete 3 68 5 0
25 Insert 3 4 5 0 intkey=r[5] data=r[4]
26 SetCookie 0 1 2 0
27 ParseSchema 0 0 0 tbl_name='sqlite_stat1' AND type!='trigger' 0
28 OpenWrite 0 2 0 3 16 root=2 iDb=0; sqlite_stat1
29 OpenRead 5 2 0 3 0 root=2 iDb=0; stat_test
30 String8 0 18 0 stat_test 0 r[18]='stat_test'; stat_test
31 Count 5 20 0 0 r[20]=count()
32 IfNot 20 37 0 0
33 Null 0 19 0 0 r[19]=NULL
34 MakeRecord 18 3 16 BBB 0 r[16]=mkrec(r[18..20])
35 NewRowid 0 12 0 0 r[12]=rowid
36 Insert 0 16 12 8 intkey=r[12] data=r[16]
37 LoadAnalysis 0 0 0 0
38 Expire 0 0 0 0
39 Halt 0 0 0 0
40 Transaction 0 1 1 0 1 usesStmtJournal=1
41 Goto 0 1 0 0
And now Turso's looks like:
turso> create table stat_test(a,b,c);
turso> explain analyze stat_test;
addr opcode p1 p2 p3 p4 p5 comment
---- ----------------- ---- ---- ---- ------------- -- -------
0 Init 0 23 0 0 Start at 23
1 Null 0 1 0 0 r[1]=NULL
2 CreateBtree 0 2 1 0 r[2]=root iDb=0 flags=1
3 OpenWrite 0 1 0 0 root=1; iDb=0
4 NewRowid 0 3 0 0 r[3]=rowid
5 String8 0 4 0 table 0 r[4]='table'
6 String8 0 5 0 sqlite_stat1 0 r[5]='sqlite_stat1'
7 String8 0 6 0 sqlite_stat1 0 r[6]='sqlite_stat1'
8 Copy 2 7 0 0 r[7]=r[2]
9 String8 0 8 0 CREATE TABLE sqlite_stat1(tbl,idx,stat) 0 r[8]='CREATE TABLE sqlite_stat1(tbl,idx,stat)'
10 MakeRecord 4 5 9 0 r[9]=mkrec(r[4..8])
11 Insert 0 9 3 sqlite_stat1 0 intkey=r[3] data=r[9]
12 ParseSchema 0 0 0 tbl_name = 'sqlite_stat1' AND type != 'trigger' 0 tbl_name = 'sqlite_stat1' AND type != 'trigger'
13 OpenWrite 1 2 0 0 root=2; iDb=0
14 OpenRead 2 2 0 0 =stat_test, root=2, iDb=0
15 String8 0 12 0 stat_test 0 r[12]='stat_test'
16 Count 2 14 0 0
17 IfNot 14 22 0 0 if !r[14] goto 22
18 Null 0 13 0 0 r[13]=NULL
19 MakeRecord 12 3 11 0 r[11]=mkrec(r[12..14])
20 NewRowid 1 10 0 0 r[10]=rowid
21 Insert 1 11 10 sqlite_stat1 0 intkey=r[10] data=r[11]
22 Halt 0 0 0 0
23 Goto 0 1 0 0
The notable difference in size is following the same codegen difference
in CREATE TABLE, where sqlite's odd dance of adding a placeholder entry
which is immediately replaced is instead done in tursodb as just
inserting the correct row in the first place. Aside from lines 6-13 of
sqlite's vdbe being missing, there's still the lack of LoadAnalysis,
Expire, and Cookie management.
2025-08-24 13:35:39 -07:00
C4 Patino
51621f462a
core(datetime): added implementation of ceiling modifier to datetime
2025-08-23 22:59:08 -05:00
Alex Miller
4619890ffc
Add basic support for ANALYZE statement.
...
This permits only `ANALYZE <table_name>` to work, and all other forms
fail with a parse error (as documented in the tests).
On SQLite, ANALYZE generates:
sqlite> CREATE TABLE sqlite_stat1(tbl,idx,stat);
sqlite> CREATE TABLE iiftest(a int, b int, c int);
sqlite> EXPLAIN ANALYZE iiftest;
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- ------------- -- -------------
0 Init 0 21 0 0 Start at 21
1 Null 0 1 0 0 r[1]=NULL
2 OpenWrite 3 4 0 3 0 root=4 iDb=0; sqlite_stat1
3 Rewind 3 9 0 0
4 Column 3 0 2 0 r[2]= cursor 3 column 0
5 Ne 3 8 2 BINARY-8 81 if r[2]!=r[3] goto 8
6 Rowid 3 4 0 0 r[4]=sqlite_stat1.rowid
7 Delete 3 0 0 sqlite_stat1 2
8 Next 3 4 0 1
9 OpenWrite 0 4 0 3 0 root=4 iDb=0; sqlite_stat1
10 OpenRead 4 2 0 3 0 root=2 iDb=0; iiftest
11 String8 0 11 0 iiftest 0 r[11]='iiftest'; iiftest
12 Count 4 13 0 0 r[13]=count()
13 IfNot 13 18 0 0
14 Null 0 12 0 0 r[12]=NULL
15 MakeRecord 11 3 9 BBB 0 r[9]=mkrec(r[11..13])
16 NewRowid 0 5 0 0 r[5]=rowid
17 Insert 0 9 5 8 intkey=r[5] data=r[9]
18 LoadAnalysis 0 0 0 0
19 Expire 0 0 0 0
20 Halt 0 0 0 0
21 Transaction 0 1 9 0 1 usesStmtJournal=0
22 String8 0 3 0 iiftest 0 r[3]='iiftest'
23 Goto 0 1 0 0
Turso can now generate:
turso> create table sqlite_stat1(tbl,idx,stat);
turso> create table iiftest(a int, b int, c int);
turso> explain analyze iiftest;
addr opcode p1 p2 p3 p4 p5 comment
---- ----------------- ---- ---- ---- ------------- -- -------
0 Init 0 19 0 0 Start at 19
1 Null 0 1 0 0 r[1]=NULL
2 OpenWrite 0 2 0 0 root=2; iDb=0
3 Rewind 0 9 0 0 Rewind sqlite_stat1
4 Column 0 0 2 0 r[2]=sqlite_stat1.tbl
5 Ne 2 3 9 0 if r[2]!=r[3] goto 9
6 RowId 0 4 0 0 r[4]=sqlite_stat1.rowid
7 Delete 0 0 0 sqlite_stat1 0
8 Next 0 4 0 0
9 OpenWrite 1 2 0 0 root=2; iDb=0
10 OpenRead 2 3 0 0 =iiftest, root=3, iDb=0
11 String8 0 7 0 iiftest 0 r[7]='iiftest'
12 Count 2 9 0 0
13 IfNot 9 18 0 0 if !r[9] goto 18
14 Null 0 8 0 0 r[8]=NULL
15 MakeRecord 7 3 6 0 r[6]=mkrec(r[7..9])
16 NewRowid 1 5 0 0 r[5]=rowid
17 Insert 1 6 5 sqlite_stat1 0 intkey=r[5] data=r[6]
18 Halt 0 0 0 0
19 String8 0 3 0 iiftest 0 r[3]='iiftest'
20 Goto 0 1 0 0
Note the missing support for LoadAnalysis and Expire, but there's no
optimizer work done yet to leverage any gathered statistics yet anyway.
2025-08-22 23:18:53 -07:00
Pekka Enberg
a259d123de
testing/javascript: Add test case for blobs
2025-08-22 14:17:45 +03:00
Jussi Saurio
2caea349a9
Add regression test for #2686
2025-08-21 16:40:10 +03:00
Jussi Saurio
22be35e790
Add regression test
2025-08-21 16:31:12 +03:00
Pekka Enberg
7270e66530
unreliable-libc: Make fault injection seed configurable
2025-08-20 13:50:04 +03:00
Pekka Enberg
19456147ec
testing: Add unreliable libc
2025-08-20 13:43:47 +03:00
rajajisai
ff2d62aa9d
update test
2025-08-19 23:11:10 -04:00
rajajisai
73500eb00c
Include tests
2025-08-19 22:33:59 -04:00
Pekka Enberg
54b4fdaa7d
javascript: Implement transactions API
2025-08-19 16:35:44 +03:00
Pekka Enberg
387d384394
javascript: Implement Statement.columns()
2025-08-19 16:35:44 +03:00
Pekka Enberg
5002539b04
javascript: Implement safe integers
2025-08-19 16:35:44 +03:00
Pekka Enberg
6b59bcd51e
javascript: Fix Statement.get() for boundary values
2025-08-19 16:35:44 +03:00
Pekka Enberg
e99f189344
javascript: Implement Statement.pluck()
2025-08-19 16:35:44 +03:00
Pekka Enberg
692323ae9b
bindings/javascript: Rename @tursodatabase/database/sync to compat
...
We already have a `@tursodatabase/sync` package so let's make the name of the
better-sqlite3 compatibility API package stand out.
2025-08-19 13:20:34 +03:00