From bfb9e35b30b129189fb009bbd7f0f2613c27cf29 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Mon, 24 Jan 2005 13:03:32 +0000 Subject: [PATCH] More test cases to do with invalidating precompiled statements. (CVS 2273) FossilOrigin-Name: b243681a0e328ee0bbf1140abfb60d65d2102ad5 --- manifest | 16 ++-- manifest.uuid | 2 +- src/trigger.c | 45 ++++----- test/schema.test | 244 +++++++++++++++++++++++++++++++++++------------ 4 files changed, 215 insertions(+), 92 deletions(-) diff --git a/manifest b/manifest index da66bf89e9..e24eb1f338 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sthe\scache\swith\sloading\sa\slarge\stable\sin\sselect2-2.0.\s(CVS\s2272) -D 2005-01-24T12:46:14 +C More\stest\scases\sto\sdo\swith\sinvalidating\sprecompiled\sstatements.\s(CVS\s2273) +D 2005-01-24T13:03:32 F Makefile.in ffd81f5e926d40b457071b4de8d7c1fa18f39b5a F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -70,7 +70,7 @@ F src/test3.c 683e1e3819152ffd35da2f201e507228921148d0 F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5 F src/tokenize.c 88bef43fe3e3c8865a7447f934296ac13238c4f6 -F src/trigger.c b3de66150300026f21522bb273bbc413a80f427d +F src/trigger.c 5da126eeedca7d25c892311f21f909ff1f3825ba F src/update.c 6e5c6eb660a5508c449c6d637571e24ef13f70a1 F src/utf.c 9bece2c7b94d9002ab1bb900a7658c6f826b0f74 F src/util.c a858b93ba06bbafab55ba41e4d58538eb51f4b6a @@ -174,7 +174,7 @@ F test/reindex.test 3552c6b944a3fab28cfd3049c04c65cb79419757 F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a F test/rowid.test 040a3bef06f970c45f5fcd14b2355f7f4d62f0cf F test/safety.test 907b64fee719554a3622853812af3886fddbbb4f -F test/schema.test ccaceafa6c0031489f7e927f0449bef360530387 +F test/schema.test 8725b41e19dec6c2d060b134417fe3da83c22d70 F test/select1.test ad700a2a1c325a23a7206ad4d189e33917de526f F test/select2.test 04103fbd55fca9558fd79d637fb7819d9d0b2f52 F test/select3.test 9de435aa84fc406708cd8dc1b1d60e7f27cea685 @@ -272,7 +272,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd -P d5233e0747789dea04d35a8350b408321d23a64d -R 64d7764e37b156dc0893bed779bcbc1f -U drh -Z b35e1974cc6fc16a36be9de3cc4530ba +P bd65b1805c116a9073a01164d77e2bfd4ab3b447 +R 5b52d70623d9cc9b1a479b06c91e23de +U danielk1977 +Z 0621873bf2da710b6c752ac8b3dbc2ce diff --git a/manifest.uuid b/manifest.uuid index fc7dc47a51..370148f519 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd65b1805c116a9073a01164d77e2bfd4ab3b447 \ No newline at end of file +b243681a0e328ee0bbf1140abfb60d65d2102ad5 \ No newline at end of file diff --git a/src/trigger.c b/src/trigger.c index 761abfce9f..ef4acefc02 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -189,20 +189,20 @@ void sqlite3FinishTrigger( TriggerStep *pStepList, /* The triggered program */ Token *pAll /* Token that describes the complete CREATE TRIGGER */ ){ - Trigger *nt = 0; /* The trigger whose construction is finishing up */ + Trigger *pTrig = 0; /* The trigger whose construction is finishing up */ sqlite3 *db = pParse->db; /* The database */ DbFixer sFix; if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup; - nt = pParse->pNewTrigger; + pTrig = pParse->pNewTrigger; pParse->pNewTrigger = 0; - nt->step_list = pStepList; + pTrig->step_list = pStepList; while( pStepList ){ - pStepList->pTrig = nt; + pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } - if( sqlite3FixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) - && sqlite3FixTriggerStep(&sFix, nt->step_list) ){ + if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken) + && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){ goto triggerfinish_cleanup; } @@ -228,35 +228,32 @@ void sqlite3FinishTrigger( /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; - sqlite3BeginWriteOperation(pParse, 0, nt->iDb); - sqlite3OpenMasterTable(v, nt->iDb); + sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb); + sqlite3OpenMasterTable(v, pTrig->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); - sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); - sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); + sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0); + sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0); sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); - if( nt->iDb!=0 ){ - sqlite3ChangeCookie(db, v, nt->iDb); - } + sqlite3ChangeCookie(db, v, pTrig->iDb); sqlite3VdbeAddOp(v, OP_Close, 0, 0); - sqlite3VdbeOp3(v, OP_ParseSchema, nt->iDb, 0, - sqlite3MPrintf("type='trigger' AND name='%q'", nt->name), P3_DYNAMIC); + sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0, + sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC); } if( db->init.busy ){ Table *pTab; - sqlite3HashInsert(&db->aDb[nt->iDb].trigHash, - nt->name, strlen(nt->name)+1, nt); - pTab = sqlite3LocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName); + sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash, + pTrig->name, strlen(pTrig->name)+1, pTrig); + pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName); assert( pTab!=0 ); - nt->pNext = pTab->pTrigger; - pTab->pTrigger = nt; - nt = 0; + pTrig->pNext = pTab->pTrigger; + pTab->pTrigger = pTrig; + pTrig = 0; } triggerfinish_cleanup: - sqlite3DeleteTrigger(nt); - sqlite3DeleteTrigger(pParse->pNewTrigger); - pParse->pNewTrigger = 0; + sqlite3DeleteTrigger(pTrig); + assert( !pParse->pNewTrigger ); sqlite3DeleteTriggerStep(pStepList); } diff --git a/test/schema.test b/test/schema.test index 67bf137e6b..04f7f13485 100644 --- a/test/schema.test +++ b/test/schema.test @@ -1,4 +1,4 @@ -# 2004 Jun 27 +# 2004 Jan 24 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -13,67 +13,126 @@ # This file tests the various conditions under which an SQLITE_SCHEMA # error should be returned. # -# $Id: schema.test,v 1.1 2005/01/24 10:26:00 danielk1977 Exp $ +# $Id: schema.test,v 1.2 2005/01/24 13:03:32 danielk1977 Exp $ + +#--------------------------------------------------------------------- +# When any of the following types of SQL statements or actions are +# executed, all pre-compiled statements are invalidated. An attempt +# to execute an invalidated statement always returns SQLITE_SCHEMA. +# +# CREATE/DROP TABLE...................................schema-1.* +# CREATE/DROP VIEW....................................schema-2.* +# CREATE/DROP TRIGGER.................................schema-3.* +# CREATE/DROP INDEX...................................schema-4.* +# DETACH..............................................schema-5.* +# Deleting a user-function............................schema-6.* +# Deleting a collation sequence.......................schema-7.* +# Setting or changing the authorization function......schema-8.* +# +# Note: Test cases schema-6.* are missing right now. +# set testdir [file dirname $argv0] source $testdir/tester.tcl -# schema-1.1: Test that if a table is dropped by one database connection, -# other database connections are aware of the schema change. -# schema-1.2: Test that if a view is dropped by one database connection, -# other database connections are aware of the schema change. -# do_test schema-1.1 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] execsql { CREATE TABLE abc(a, b, c); } - sqlite3 db2 test.db - execsql { - DROP TABLE abc; - } db2 - catchsql { - SELECT * FROM abc; - } -} {1 {no such table: abc}} -do_test schema-1.2 { - execsql { - CREATE TABLE abc(a, b, c); - CREATE VIEW abcview AS SELECT * FROM abc; - } - sqlite3 db2 test.db - execsql { - DROP VIEW abcview; - } db2 - db2 close - catchsql { - SELECT * FROM abcview; - } -} {1 {no such table: abcview}} - -# Tests 2.1 to 2.4 check that prepared statements are invalidated when -# a collation sequence is deleted (but not when one is added). -# -do_test schema-2.1 { - set sql {SELECT * FROM abc;} - set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] - add_test_collate $::DB 1 1 1 - sqlite3_step $::STMT -} {SQLITE_DONE} -do_test schema-2.2 { - sqlite3_reset $::STMT -} {SQLITE_OK} -do_test schema-2.3 { - add_test_collate $::DB 0 0 0 sqlite3_step $::STMT } {SQLITE_ERROR} -do_test schema-2.4 { +do_test schema-1.2 { + sqlite3_finalize $::STMT +} {SQLITE_SCHEMA} +do_test schema-1.3 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + DROP TABLE abc; + } + sqlite3_step $::STMT +} {SQLITE_ERROR} +do_test schema-1.4 { sqlite3_finalize $::STMT } {SQLITE_SCHEMA} -# Tests 3.1 to 3.4 check that prepared statements are invalidated when +ifcapable view { + do_test schema-2.1 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + CREATE VIEW v1 AS SELECT * FROM sqlite_master; + } + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-2.2 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} + do_test schema-2.3 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + DROP VIEW v1; + } + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-2.4 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} +} + +ifcapable trigger { + do_test schema-3.1 { + execsql { + CREATE TABLE abc(a, b, c); + } + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + CREATE TRIGGER abc_trig AFTER INSERT ON abc BEGIN + SELECT 1, 2, 3; + END; + } + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-3.2 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} + do_test schema-3.3 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + DROP TRIGGER abc_trig; + } + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-3.4 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} +} + +do_test schema-4.1 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + CREATE INDEX abc_index ON abc(a); + } + sqlite3_step $::STMT +} {SQLITE_ERROR} +do_test schema-4.2 { + sqlite3_finalize $::STMT +} {SQLITE_SCHEMA} +do_test schema-4.3 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + execsql { + DROP INDEX abc_index; + } + sqlite3_step $::STMT +} {SQLITE_ERROR} +do_test schema-4.4 { + sqlite3_finalize $::STMT +} {SQLITE_SCHEMA} + +#--------------------------------------------------------------------- +# Tests 5.1 to 5.4 check that prepared statements are invalidated when # a database is DETACHed (but not when one is ATTACHed). # -do_test schema-3.1 { +do_test schema-5.1 { set sql {SELECT * FROM abc;} set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] execsql { @@ -81,25 +140,96 @@ do_test schema-3.1 { } sqlite3_step $::STMT } {SQLITE_DONE} -do_test schema-3.2 { +do_test schema-5.2 { sqlite3_reset $::STMT } {SQLITE_OK} -do_test schema-3.3 { +do_test schema-5.3 { execsql { DETACH aux; } sqlite3_step $::STMT } {SQLITE_ERROR} -do_test schema-3.4 { +do_test schema-5.4 { sqlite3_finalize $::STMT } {SQLITE_SCHEMA} +#--------------------------------------------------------------------- +# Tests 7.* check that prepared statements are invalidated when +# a collation sequence is deleted (but not when one is added). +# +do_test schema-7.1 { + set sql {SELECT * FROM abc;} + set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] + add_test_collate $::DB 1 1 1 + sqlite3_step $::STMT +} {SQLITE_DONE} +do_test schema-7.2 { + sqlite3_reset $::STMT +} {SQLITE_OK} +do_test schema-7.3 { + add_test_collate $::DB 0 0 0 + sqlite3_step $::STMT +} {SQLITE_ERROR} +do_test schema-7.4 { + sqlite3_finalize $::STMT +} {SQLITE_SCHEMA} +#--------------------------------------------------------------------- +# Tests 8.1 and 8.2 check that prepared statements are invalidated when +# the authorization function is set. +# +ifcapable auth { + do_test schema-8.1 { + set ::STMT [sqlite3_prepare $::DB {SELECT * FROM sqlite_master} -1 TAIL] + db auth {} + sqlite3_step $::STMT + } {SQLITE_ERROR} + do_test schema-8.3 { + sqlite3_finalize $::STMT + } {SQLITE_SCHEMA} +} + +#--------------------------------------------------------------------- +# schema-9.1: Test that if a table is dropped by one database connection, +# other database connections are aware of the schema change. +# schema-9.2: Test that if a view is dropped by one database connection, +# other database connections are aware of the schema change. +# +do_test schema-9.1 { + sqlite3 db2 test.db + execsql { + DROP TABLE abc; + } db2 + db2 close + catchsql { + SELECT * FROM abc; + } +} {1 {no such table: abc}} +execsql { + CREATE TABLE abc(a, b, c); +} +ifcapable view { + do_test schema-9.2 { + execsql { + CREATE VIEW abcview AS SELECT * FROM abc; + } + sqlite3 db2 test.db + execsql { + DROP VIEW abcview; + } db2 + db2 close + catchsql { + SELECT * FROM abcview; + } + } {1 {no such table: abcview}} +} + +#--------------------------------------------------------------------- # Test that if a CREATE TABLE statement fails because there are other # btree cursors open on the same database file it does not corrupt # the sqlite_master table. # -do_test schema-4.1 { +do_test schema-10.1 { execsql { INSERT INTO abc VALUES(1, 2, 3); } @@ -107,27 +237,23 @@ do_test schema-4.1 { set ::STMT [sqlite3_prepare $::DB $sql -1 TAIL] sqlite3_step $::STMT } {SQLITE_ROW} -do_test schema-4.2 { +do_test schema-10.2 { catchsql { CREATE TABLE t2(a, b, c); } } {1 {database table is locked}} -do_test schema-4.3 { +do_test schema-10.3 { sqlite3_finalize $::STMT } {SQLITE_OK} -do_test schema-4.4 { +do_test schema-10.4 { sqlite3 db2 test.db execsql { SELECT * FROM abc } db2 } {1 2 3} -do_test schema-4.5 { +do_test schema-10.5 { db2 close } {} finish_test - - - -