Files
turso/testing/analyze.test
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

64 lines
1.8 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 sqlite_stat1(tbl,idx,stat);
CREATE TABLE temp (a integer);
ANALYZE temp;
SELECT * FROM sqlite_stat1;
} {}
do_execsql_test_on_specific_db {:memory:} one-row-table {
CREATE TABLE sqlite_stat1(tbl,idx,stat);
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-deletes {
CREATE TABLE sqlite_stat1(tbl,idx,stat);
INSERT INTO sqlite_stat1 VALUES ('temp', NULL, 10);
CREATE TABLE temp (a integer);
INSERT INTO temp VALUES (1);
ANALYZE temp;
SELECT * FROM sqlite_stat1;
} {temp||1}
# 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-without-stat-table-fails {
CREATE TABLE temp (a integer);
ANALYZE temp;
} {.*ANALYZE.*not supported.*}
do_execsql_test_in_memory_error analyze-table-with-pk-fails {
CREATE TABLE sqlite_stat1(tbl,idx,stat);
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 sqlite_stat1(tbl,idx,stat);
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 sqlite_stat1(tbl,idx,stat);
CREATE TABLE temp (a integer, b integer);
CREATE INDEX temp_b ON temp (b);
ANALYZE temp_b;
} {.*ANALYZE.*not supported.*}