mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-17 08:34:19 +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.
54 lines
1.4 KiB
Tcl
Executable File
54 lines
1.4 KiB
Tcl
Executable File
#!/usr/bin/env tclsh
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
|
|
# Things that do work:
|
|
|
|
do_execsql_test_on_specific_db {:memory:} empty-table {
|
|
CREATE TABLE temp (a integer);
|
|
ANALYZE temp;
|
|
SELECT * FROM sqlite_stat1;
|
|
} {}
|
|
|
|
do_execsql_test_on_specific_db {:memory:} one-row-table {
|
|
CREATE TABLE temp (a integer);
|
|
INSERT INTO temp VALUES (1);
|
|
ANALYZE temp;
|
|
SELECT * FROM sqlite_stat1;
|
|
} {temp||1}
|
|
|
|
do_execsql_test_on_specific_db {:memory:} analyze-overwrites {
|
|
CREATE TABLE temp (a integer);
|
|
INSERT INTO temp VALUES (1);
|
|
ANALYZE temp;
|
|
INSERT INTO temp VALUES (2);
|
|
ANALYZE temp;
|
|
SELECT * FROM sqlite_stat1;
|
|
} {temp||2}
|
|
|
|
# Things that don't work:
|
|
|
|
do_execsql_test_in_memory_error analyze-all-databases-fails {
|
|
ANALYZE;
|
|
} {.*ANALYZE.*not supported.*}
|
|
|
|
do_execsql_test_in_memory_error analyze-one-database-fails {
|
|
ANALYZE main;
|
|
} {.*ANALYZE.*not supported.*}
|
|
|
|
do_execsql_test_in_memory_error analyze-table-with-pk-fails {
|
|
CREATE TABLE temp (a integer primary key);
|
|
ANALYZE temp;
|
|
} {.*ANALYZE.*not supported.*}
|
|
|
|
do_execsql_test_in_memory_error analyze-table-without-rowid-fails {
|
|
CREATE TABLE temp (a integer primary key) WITHOUT ROWID;
|
|
ANALYZE temp;
|
|
} {.*ANALYZE.*not supported.*}
|
|
|
|
do_execsql_test_in_memory_error analyze-index-fails {
|
|
CREATE TABLE temp (a integer, b integer);
|
|
CREATE INDEX temp_b ON temp (b);
|
|
ANALYZE temp_b;
|
|
} {.*ANALYZE.*not supported.*}
|