-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
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
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
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
-c21bc5a2353e660f2acf5ed916921a4ee416910d0b3f2deb512a05c54138d1c0
\ No newline at end of file
+cf8eb465974e596a13df56f3efbc98e098e7b74de9af4fde9ad58312db9750e4
\ No newline at end of file
}
#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
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
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);
}else{
assert( !db->init.busy );
sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
** [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);