Modify the sqlite3_stmt_readonly() interface so that it returns false for
CREATE TABLE IF NOT EXISTS statements even if the table already exists and the statement is really a read-only no-op. Likewise for DROP TABLE, CREATE INDEX, and DROP INDEX. Update the documentation for sqlite3_stmt_readonly() to reflect this new behavior. FossilOrigin-Name: cf8eb465974e596a13df56f3efbc98e098e7b74de9af4fde9ad58312db9750e4
This commit is contained in:
parent
756748ea86
commit
31da7be9f2
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C The\scontent\scolumns\sof\sthe\sindex-btree\sthat\simplements\sa\sWITHOUT\sROWID\ntable\sare\snot\sordered\sand\sso\sthe\squery\splanner\sshould\snot\sassume\sthey\nare\sordered.\s\sFix\sfor\sthe\sissue\sidentified\sby\n[forum:/forumpost/6c8960f545|forum\spost\s6c8960f545].
|
||||
D 2021-05-13T13:43:40.565
|
||||
C Modify\sthe\ssqlite3_stmt_readonly()\sinterface\sso\sthat\sit\sreturns\sfalse\sfor\nCREATE\sTABLE\sIF\sNOT\sEXISTS\sstatements\seven\sif\sthe\stable\salready\sexists\sand\nthe\sstatement\sis\sreally\sa\sread-only\sno-op.\s\sLikewise\sfor\sDROP\sTABLE,\s\nCREATE\sINDEX,\sand\sDROP\sINDEX.\s\sUpdate\sthe\sdocumentation\sfor\nsqlite3_stmt_readonly()\sto\sreflect\sthis\snew\sbehavior.
|
||||
D 2021-05-13T18:24:22.567
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -487,7 +487,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 5372d8bca3374145477e129be5ed6e907731e1d117c0dc1b524b536f1cc0e577
|
||||
F src/btree.h 096cc53baa58be22b02c896d1cf933c38cfc6d65f9253c1367ece8cc88a24de5
|
||||
F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0
|
||||
F src/build.c bf4f76eb77ff0193ef826f9dbd0285e8b55fe8ecb24d1f6b14bf72b68df6a422
|
||||
F src/build.c a7866beda66a7c8971e013674c7f659d19977d9ad51e11032479b1f754d1ef21
|
||||
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 2a322b9a3d75771fb4d99e0702851f4f68dda982507a0f798eefb0712969a410
|
||||
@ -545,7 +545,7 @@ F src/resolve.c c38bbb89d7ba7a8673ec4f59b63e0980eb859c39ff2acc5df8b3d0f2dcd33115
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 57dbb27e0d0cb2438487c797365a4c17294d0df3c25c970ca87f123105f33ed0
|
||||
F src/shell.c.in 1b32ba2918ede13b68df47c7b92b72ba0d06e68d384e78bb9d7456527271d400
|
||||
F src/sqlite.h.in c0969405cc053220ebf81d487c5851007928e45e487237dd23435d13c25daab0
|
||||
F src/sqlite.h.in 5c950066775ca9efdaa49077c05d38d0bef6418f3bd07d2dce0210f1d2f3c326
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
||||
F src/sqliteInt.h 2b1cbc7f78346ac83ea962e5daf6a201e223cf1902e0cfde54f37cf3d82fcc24
|
||||
@ -1913,7 +1913,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P b2b0e23ba885f22c88b03492e42c3cd1cbd59289e452263951bb757a871699f0
|
||||
R 764f06f91ab95ce9134e7e810a3df5f2
|
||||
P c21bc5a2353e660f2acf5ed916921a4ee416910d0b3f2deb512a05c54138d1c0
|
||||
R 2e9914ba2c75f0fbf85c89829a93e146
|
||||
U drh
|
||||
Z 2bf41f499ef008f771df581659494cf8
|
||||
Z 708e967733b505d5e67438dc1caa81fb
|
||||
|
@ -1 +1 @@
|
||||
c21bc5a2353e660f2acf5ed916921a4ee416910d0b3f2deb512a05c54138d1c0
|
||||
cf8eb465974e596a13df56f3efbc98e098e7b74de9af4fde9ad58312db9750e4
|
24
src/build.c
24
src/build.c
@ -1048,6 +1048,22 @@ i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Insert a single OP_JournalMode query opcode in order to force the
|
||||
** prepared statement to return false for sqlite3_stmt_readonly(). This
|
||||
** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
|
||||
** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
|
||||
** will return false for sqlite3_stmt_readonly() even if that statement
|
||||
** is a read-only no-op.
|
||||
*/
|
||||
static void sqlite3ForceNotReadOnly(Parse *pParse){
|
||||
int iReg = ++pParse->nMem;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
if( v ){
|
||||
sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Begin constructing a new table representation in memory. This is
|
||||
** the first of several action routines that get called in response
|
||||
@ -1147,6 +1163,7 @@ void sqlite3StartTable(
|
||||
}else{
|
||||
assert( !db->init.busy || CORRUPT_DB );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
goto begin_table_error;
|
||||
}
|
||||
@ -3197,7 +3214,10 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
||||
if( noErr ) db->suppressErr--;
|
||||
|
||||
if( pTab==0 ){
|
||||
if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
if( noErr ){
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
goto exit_drop_table;
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
@ -3767,6 +3787,7 @@ void sqlite3CreateIndex(
|
||||
}else{
|
||||
assert( !db->init.busy );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
goto exit_create_index;
|
||||
}
|
||||
@ -4285,6 +4306,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
|
||||
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
|
||||
}else{
|
||||
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
|
||||
sqlite3ForceNotReadOnly(pParse);
|
||||
}
|
||||
pParse->checkSchema = 1;
|
||||
goto exit_drop_index;
|
||||
|
@ -4198,6 +4198,15 @@ const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
||||
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
|
||||
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
|
||||
** sqlite3_stmt_readonly() returns false for those commands.
|
||||
**
|
||||
** ^This routine returns false if there is any possibility that the
|
||||
** statement might change the database file. ^A false return does
|
||||
** not guarantee that the statement will change the database file.
|
||||
** ^For example, an UPDATE statement might have a WHERE clause that
|
||||
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
|
||||
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
|
||||
** read-only no-op if the table already exists, but
|
||||
** sqlite3_stmt_readonly() still returns false for such a statement.
|
||||
*/
|
||||
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user