mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-24 11:34:21 +01:00
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.
Turso Testing
Testing Extensions
When adding tests for extensions, please follow these guidelines:
- Tests that verify the internal logic or behavior of a particular extension should go into
cli_tests/extensions.py. - Tests that verify how extensions interact with the database engine, such as virtual table handling, should be written
in TCL (see
vtab.testas an example).
To check which extensions are available in TCL, or to add a new one, refer to the tester.tcl file and look at the extension_map.