Change SQLITE_TESTCTRL_INITMODE to SQLITE_TESTCTRL_IMPOSTER. Revise the order
of parameters. Give it the ability to reset the schema parse table so that imposter tables can be erased. FossilOrigin-Name: 42d5601739c90434e5adfda8fa99ef7b903877db
This commit is contained in:
parent
0699f29a14
commit
1ffede8c86
27
manifest
27
manifest
@ -1,5 +1,5 @@
|
||||
C Added\sSQLITE_TESTCTRL_INITMODE\sfor\simproved\stestability.
|
||||
D 2015-01-30T15:52:26.210
|
||||
C Change\sSQLITE_TESTCTRL_INITMODE\sto\sSQLITE_TESTCTRL_IMPOSTER.\s\sRevise\sthe\sorder\nof\sparameters.\s\sGive\sit\sthe\sability\sto\sreset\sthe\sschema\sparse\stable\sso\sthat\nimposter\stables\scan\sbe\serased.
|
||||
D 2015-01-30T20:59:27.457
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5407a688f4d77a05c18a8142be8ae5a2829dd610
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -173,10 +173,10 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
|
||||
F src/btree.c 4c098bb6e8678e4596983862abf78f7a0fcb807e
|
||||
F src/btree.c 2a1245df0356a229bcd0fd87a8536b5067f16e82
|
||||
F src/btree.h 94277c1d30c0b75705974bcc8b0c05e79c03d474
|
||||
F src/btreeInt.h a3d0ae1d511365e1a2b76ad10960dbe55c286f34
|
||||
F src/build.c f5cfd7b32216f695b995bbc7c1a395f6d451d11f
|
||||
F src/build.c eefaa4f1d86bc3c08023a61fdd1e695b47796975
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
|
||||
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
|
||||
@ -195,7 +195,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
F src/loadext.c 86bd4e2fccd520b748cba52492ab60c4a770f660
|
||||
F src/main.c 81ddebf2feb9cbd8c8ea160cdd979503f645d505
|
||||
F src/main.c ce38ddcedf33e5530b0e6c592809bb8822a6e8d0
|
||||
F src/malloc.c 740db54387204c9a2eb67c6d98e68b08e9ef4eab
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
|
||||
@ -230,16 +230,16 @@ F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c f6c46d3434439ab2084618d603e6d6dbeb0d6ada
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 1f2087523007c42900ffcbdeaef06a23ad9329fc
|
||||
F src/shell.c ed7cf7c29fb1a23d47179affc89cb447868fc976
|
||||
F src/sqlite.h.in 6910064681444efb5c467472499b56bb6bcee0f4
|
||||
F src/shell.c 22b4406b0b59efd14b3b351a5809dda517df6d30
|
||||
F src/sqlite.h.in 54678c21401909f72b221344dd560d285a1ba5eb
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h eaf210295b551d4e40e622aec1b2261c0b28f844
|
||||
F src/sqliteInt.h c4e05f7489cd300f856e2283d5e61302ce826471
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 81712116e826b0089bb221b018929536b2b5406f
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c b8014393a96a9781bb635c8b1f52fc9b77a2bfcf
|
||||
F src/test1.c 5dcdade99e77b7b9f7760106c80a83cf50f10e1e
|
||||
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
F src/test4.c d168f83cc78d02e8d35567bb5630e40dcd85ac1e
|
||||
@ -630,6 +630,7 @@ F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
|
||||
F test/hexlit.test f9ecde8145bfc2341573473256c74ae37a200497
|
||||
F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 w test/initmode.test
|
||||
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
@ -655,7 +656,6 @@ F test/index7.test 917cf1e1c7439bb155abbeabec511b28945e157b
|
||||
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/initmode.test 38bbaefeb47e034a162856e664a0da3b95e6999b
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
@ -1238,8 +1238,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 1797158db2a818134c5cba1578f69ed85948b980 3a6e2afe408d2b0c8166d00def2048568169d87a
|
||||
R 4fa14bf275b60ddd661b9bd3fb0ea0dd
|
||||
T +closed 3a6e2afe408d2b0c8166d00def2048568169d87a
|
||||
P 98e029134dc1300d3ecb48b41b5107ec69ba85db
|
||||
R ae5f14ccaf584de0786e4614152020d2
|
||||
U drh
|
||||
Z b68a5e615b7688be627f33067b9af11c
|
||||
Z c23d2e36f9e88e779a131b19c0ee1b9b
|
||||
|
@ -1 +1 @@
|
||||
98e029134dc1300d3ecb48b41b5107ec69ba85db
|
||||
42d5601739c90434e5adfda8fa99ef7b903877db
|
@ -175,6 +175,12 @@ static int hasSharedCacheTableLock(
|
||||
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
|
||||
Index *pIdx = (Index *)sqliteHashData(p);
|
||||
if( pIdx->tnum==(int)iRoot ){
|
||||
if( iTab ){
|
||||
/* Two or more indexes share the same root page. There must
|
||||
** be imposter tables. So just return true. The assert is not
|
||||
** useful in that case. */
|
||||
return 1;
|
||||
}
|
||||
iTab = pIdx->pTable->tnum;
|
||||
}
|
||||
}
|
||||
|
11
src/build.c
11
src/build.c
@ -1731,11 +1731,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
assert( pPk!=0 );
|
||||
nPk = pPk->nKeyCol;
|
||||
|
||||
/* Make sure every column of the PRIMARY KEY is NOT NULL */
|
||||
for(i=0; i<nPk; i++){
|
||||
pTab->aCol[pPk->aiColumn[i]].notNull = 1;
|
||||
/* Make sure every column of the PRIMARY KEY is NOT NULL. (Except,
|
||||
** do not enforce this for imposter tables.) */
|
||||
if( !db->init.imposterTable ){
|
||||
for(i=0; i<nPk; i++){
|
||||
pTab->aCol[pPk->aiColumn[i]].notNull = 1;
|
||||
}
|
||||
pPk->uniqNotNull = 1;
|
||||
}
|
||||
pPk->uniqNotNull = 1;
|
||||
|
||||
/* The root page of the PRIMARY KEY is the table root page */
|
||||
pPk->tnum = pTab->tnum;
|
||||
|
25
src/main.c
25
src/main.c
@ -3599,15 +3599,30 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_INITMODE, db, busy, iDb, newTnum);
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
|
||||
**
|
||||
** Set the db->init.busy, db->init.iDb, and db->init.tnum fields.
|
||||
** This test control is used to create imposter tables. "db" is a pointer
|
||||
** to the database connection. dbName is the database name (ex: "main" or
|
||||
** "temp") which will receive the imposter. "onOff" turns imposter mode on
|
||||
** or off. "tnum" is the root page of the b-tree to which the imposter
|
||||
** table should connect.
|
||||
**
|
||||
** Enable imposter mode only when the schema has already been parsed. Then
|
||||
** run a single CREATE TABLE statement to construct the imposter table in the
|
||||
** parsed schema. Then turn imposter mode back off again.
|
||||
**
|
||||
** If onOff==0 and tnum>0 then reset the schema for all databases, causing
|
||||
** the schema to be reparsed the next time it is needed. This has the
|
||||
** effect of erasing all imposter tables.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_INITMODE: {
|
||||
case SQLITE_TESTCTRL_IMPOSTER: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
db->init.busy = va_arg(ap,int);
|
||||
db->init.iDb = va_arg(ap,int);
|
||||
db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
|
||||
db->init.busy = db->init.imposterTable = va_arg(ap,int);
|
||||
db->init.newTnum = va_arg(ap,int);
|
||||
if( db->init.busy==0 && db->init.newTnum>0 ){
|
||||
sqlite3ResetAllSchemasOfConnection(db);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3536,7 +3536,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
|
||||
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
|
||||
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
|
||||
{ "initmode", SQLITE_TESTCTRL_INITMODE },
|
||||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
|
||||
};
|
||||
int testctrl = -1;
|
||||
int rc = 0;
|
||||
@ -3629,14 +3629,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SQLITE_TESTCTRL_INITMODE:
|
||||
case SQLITE_TESTCTRL_IMPOSTER:
|
||||
if( nArg==5 ){
|
||||
rc = sqlite3_test_control(testctrl, p->db,
|
||||
integerValue(azArg[2]),
|
||||
azArg[2],
|
||||
integerValue(azArg[3]),
|
||||
integerValue(azArg[4]));
|
||||
}else{
|
||||
fprintf(stderr,"Usage: .testctrl initmode fBusy iDb newTnum\n");
|
||||
fprintf(stderr,"Usage: .testctrl initmode dbName onoff tnum\n");
|
||||
rc = 1;
|
||||
}
|
||||
break;
|
||||
|
@ -6260,7 +6260,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_BYTEORDER 22
|
||||
#define SQLITE_TESTCTRL_ISINIT 23
|
||||
#define SQLITE_TESTCTRL_SORTER_MMAP 24
|
||||
#define SQLITE_TESTCTRL_INITMODE 25
|
||||
#define SQLITE_TESTCTRL_IMPOSTER 25
|
||||
#define SQLITE_TESTCTRL_LAST 25
|
||||
|
||||
/*
|
||||
|
@ -1087,6 +1087,7 @@ struct sqlite3 {
|
||||
u8 iDb; /* Which db file is being initialized */
|
||||
u8 busy; /* TRUE if currently initializing */
|
||||
u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
|
||||
u8 imposterTable; /* Building an imposter table */
|
||||
} init;
|
||||
int nVdbeActive; /* Number of VDBEs currently running */
|
||||
int nVdbeRead; /* Number of active VDBEs that read or write */
|
||||
|
17
src/test1.c
17
src/test1.c
@ -5915,7 +5915,7 @@ static int test_test_control(
|
||||
} aVerb[] = {
|
||||
{ "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
||||
{ "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
||||
{ "SQLITE_TESTCTRL_INITMODE", SQLITE_TESTCTRL_INITMODE },
|
||||
{ "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
|
||||
};
|
||||
int iVerb;
|
||||
int iFlag;
|
||||
@ -5957,18 +5957,19 @@ static int test_test_control(
|
||||
break;
|
||||
}
|
||||
|
||||
case SQLITE_TESTCTRL_INITMODE: {
|
||||
int fBusy, iDb, newTnum;
|
||||
case SQLITE_TESTCTRL_IMPOSTER: {
|
||||
int onOff, tnum;
|
||||
const char *zDbName;
|
||||
sqlite3 *db;
|
||||
if( objc!=6 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "DB fBusy iDb newTnum");
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[3], &fBusy) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[4], &iDb) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[5], &newTnum) ) return TCL_ERROR;
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_INITMODE, db, fBusy, iDb, newTnum);
|
||||
zDbName = Tcl_GetString(objv[3]);
|
||||
if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
|
||||
if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -12,17 +12,17 @@
|
||||
# This file implements tests for SQLite library.
|
||||
#
|
||||
# The focus of this file is adding extra entries in the symbol table
|
||||
# using sqlite3_test_control(SQLITE_TESTCTRL_INITMODE) and verifying that
|
||||
# using sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER) and verifying that
|
||||
# SQLite handles those as expected.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix initmode
|
||||
set testprefix imposter
|
||||
|
||||
# Create a bunch of data to sort against
|
||||
#
|
||||
do_test initmode-1.0 {
|
||||
do_test imposter-1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d NOT NULL);
|
||||
CREATE INDEX t1b ON t1(b);
|
||||
@ -31,15 +31,21 @@ do_test initmode-1.0 {
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,1000+i,2000+i,3000+i FROM c;
|
||||
}
|
||||
set t1_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1'}]
|
||||
set t1a_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1a'}]
|
||||
set t1b_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1b'}]
|
||||
set t1c_root [db one {SELECT rootpage FROM sqlite_master WHERE name='t1c'}]
|
||||
|
||||
# Create a shadow table that uses the same b-tree as t1 but which does
|
||||
# Create an imposter table that uses the same b-tree as t1 but which does
|
||||
# not have the indexes
|
||||
#
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 1 0 $t1_root
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $t1_root
|
||||
db eval {CREATE TABLE xt1(a,b,c,d)}
|
||||
sqlite3_test_control SQLITE_TESTCTRL_INITMODE db 0 0 0
|
||||
|
||||
# And create an imposter table for the t1c index.
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 1 $t1c_root
|
||||
db eval {CREATE TABLE xt1c(c,rowid,PRIMARY KEY(c,rowid))WITHOUT ROWID;}
|
||||
|
||||
# Go out of imposter mode for now.
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 0
|
||||
|
||||
# Create triggers to record changes to xt1.
|
||||
#
|
||||
@ -64,10 +70,10 @@ do_test initmode-1.0 {
|
||||
# column corresponds to t1.rowid and t1.a, but the xt1.a column is always
|
||||
# NULL
|
||||
#
|
||||
do_execsql_test initmode-1.1 {
|
||||
do_execsql_test imposter-1.1 {
|
||||
SELECT rowid FROM xt1 WHERE a IS NOT NULL;
|
||||
} {}
|
||||
do_execsql_test initmode-1.2 {
|
||||
do_execsql_test imposter-1.2 {
|
||||
SELECT a,b,c,d FROM t1 EXCEPT SELECT rowid,b,c,d FROM xt1;
|
||||
SELECT rowid,b,c,d FROM xt1 EXCEPT SELECT a,b,c,d FROM t1;
|
||||
} {}
|
||||
@ -78,7 +84,7 @@ do_execsql_test initmode-1.2 {
|
||||
# the NOT NULL constraint on t1.d, resulting in a logically inconsistent
|
||||
# database.
|
||||
#
|
||||
do_execsql_test initmode-1.3 {
|
||||
do_execsql_test imposter-1.3 {
|
||||
DELETE FROM xt1 WHERE rowid=5;
|
||||
INSERT INTO xt1(rowid,a,b,c,d) VALUES(99,'hello',1099,2022,NULL);
|
||||
SELECT * FROM chnglog ORDER BY rowid;
|
||||
@ -87,14 +93,49 @@ do_execsql_test initmode-1.3 {
|
||||
{INSERT t1: rowid=99, a='hello', b=1099, c=2022, d=NULL} \
|
||||
]
|
||||
|
||||
do_execsql_test initmode-1.4a {
|
||||
do_execsql_test imposter-1.4a {
|
||||
PRAGMA integrity_check;
|
||||
} {/NULL value in t1.d/}
|
||||
do_execsql_test initmode-1.4b {
|
||||
do_execsql_test imposter-1.4b {
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1b/}
|
||||
do_execsql_test initmode-1.4c {
|
||||
do_execsql_test imposter-1.4c {
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1c/}
|
||||
|
||||
# Cleanup the corruption.
|
||||
# Then demonstrate that the xt1c imposter table can insert non-unique
|
||||
# and NULL values into the UNIQUE index.
|
||||
#
|
||||
do_execsql_test imposter-2.0 {
|
||||
DELETE FROM t1;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,i,i,i FROM c;
|
||||
UPDATE xt1c SET c=NULL WHERE rowid=5;
|
||||
PRAGMA integrity_check;
|
||||
} {/row # missing from index t1c/}
|
||||
|
||||
do_execsql_test imposter-2.1 {
|
||||
DELETE FROM t1;
|
||||
WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10)
|
||||
INSERT INTO t1(a,b,c,d) SELECT i,i,i,i FROM c;
|
||||
UPDATE xt1c SET c=99 WHERE rowid IN (5,7,9);
|
||||
SELECT c FROM t1 ORDER BY c;
|
||||
} {1 2 3 4 6 8 10 99 99 99}
|
||||
do_execsql_test imposter-2.2 {
|
||||
UPDATE xt1 SET c=99 WHERE rowid IN (5,7,9);
|
||||
PRAGMA integrity_check;
|
||||
} {/non-unique entry in index t1c/}
|
||||
|
||||
# Erase the imposter tables
|
||||
#
|
||||
do_test imposter-3.1 {
|
||||
sqlite3_test_control SQLITE_TESTCTRL_IMPOSTER db main 0 1
|
||||
db eval {
|
||||
DELETE FROM t1 WHERE rowid IN (5,7,9);
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {ok}
|
||||
|
||||
|
||||
finish_test
|
Loading…
Reference in New Issue
Block a user