From 32158724462f35e3c4e00e5dfc4b894348f09615 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 25 Apr 2018 10:30:46 +0000 Subject: [PATCH 01/10] Add an assert() to ensure that schema mutexes are held prior to accessing the DB_SchemaLoaded flag inside of sqlite3Init(). FossilOrigin-Name: d8b46290bb75c695dac523cf9a50d1b43e773802e3b95fd722feca16162ab7c5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/prepare.c | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index e5c1579ed5..cffde9d974 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\srecently\sadded\sNEVER()\smacro\sfrom\sa\sbranch\sthat\scan\sbe\staken\sin\nobscure\scircumstances. -D 2018-04-24T18:59:18.950 +C Add\san\sassert()\sto\sensure\sthat\sschema\smutexes\sare\sheld\sprior\sto\saccessing\nthe\sDB_SchemaLoaded\sflag\sinside\sof\ssqlite3Init(). +D 2018-04-25T10:30:46.214 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -487,7 +487,7 @@ F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 -F src/prepare.c b086fea6a1952db88beca31fdd621201ee5e4ce3f02905248cc3035a8174aa89 +F src/prepare.c 2243890992597ded6358121a25567efb4482369c3685692a2444ff3f46c5b434 F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 @@ -1725,7 +1725,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 ce35e39c5cc2b00dd6b4a9ffaa9d5eb7d9b862759e87d5f053729de7643eee9c -R b81c41d41f6d79a1f11e2959c7e48fbd -U dan -Z d6a8a882b554cae8ae80a8c6e35bf17b +P 2aa210030ae414782adab9291cc43a149a780f39bd3d306dc2892a8c20422a51 +R 445070ffd3b1be1286b1b020beb181c5 +U drh +Z c5a11b92ab72681e9cb438ff2daf1afb diff --git a/manifest.uuid b/manifest.uuid index 0dc75a413d..8de9ce360f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2aa210030ae414782adab9291cc43a149a780f39bd3d306dc2892a8c20422a51 \ No newline at end of file +d8b46290bb75c695dac523cf9a50d1b43e773802e3b95fd722feca16162ab7c5 \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index c1bd20f16b..d7cc5a9f19 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -374,6 +374,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ } /* All other schemas after the main schema. The "temp" schema must be last */ for(i=db->nDb-1; i>0; i--){ + assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) ); if( !DbHasProperty(db, i, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ) return rc; From b2c8559fad99cb0f16efc30938ed5fa1f3ae3690 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 25 Apr 2018 12:01:45 +0000 Subject: [PATCH 02/10] Avoid many unnecessary calls to sqlite3ReadSchema() and sqlite3Init() when the schema is known to be valid already. FossilOrigin-Name: 58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/attach.c | 3 ++- src/btmutex.c | 6 +++--- src/build.c | 16 ++++++++++------ src/prepare.c | 11 +++++++---- src/sqliteInt.h | 3 ++- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index cffde9d974..b3f7180c63 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\san\sassert()\sto\sensure\sthat\sschema\smutexes\sare\sheld\sprior\sto\saccessing\nthe\sDB_SchemaLoaded\sflag\sinside\sof\ssqlite3Init(). -D 2018-04-25T10:30:46.214 +C Avoid\smany\sunnecessary\scalls\sto\ssqlite3ReadSchema()\sand\ssqlite3Init()\swhen\nthe\sschema\sis\sknown\sto\sbe\svalid\salready. +D 2018-04-25T12:01:45.412 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -428,15 +428,15 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594 F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941 -F src/attach.c f2ed3224c0dc44f934c4edf232238bd29b7bd8b325532c0f541857bf0e12faaa +F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7 F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 -F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca +F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 9eb9531c65346bbfccf5325384b7db1849daf4db6601dcfe21ba5c5b20623b64 F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84 F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96 -F src/build.c 91d548027a54044851299e719d60d6a2b6eaf3e3274678098cb73a6ab8c0fa19 +F src/build.c c4227d058d52c24ffce2d33cd3a11234d8e8603901243cdb5165eddf64ee2177 F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 @@ -487,7 +487,7 @@ F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170 F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880 F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69 F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324 -F src/prepare.c 2243890992597ded6358121a25567efb4482369c3685692a2444ff3f46c5b434 +F src/prepare.c d16cb8a553c09bc0c46c33f8e0add77c8f755cfb4681ca5101aaff3a04df9625 F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 @@ -497,7 +497,7 @@ F src/shell.c.in fc3f9e47198c6baea6987b6ec86fb99e7c79cee8109ce9bdece790345d8c246 F src/sqlite.h.in aa9bd3ae4a077c7002059cb418271abe52214b0227b2a734bc44736b24cbcc40 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d -F src/sqliteInt.h db62bdf05257d9b3950e45224c98ce36acf4da411e2923464819a56678ed21d3 +F src/sqliteInt.h c1deb023eb117b4437a69d8c5a753deb36581f1933015cd262ad32b45c4d8431 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1725,7 +1725,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 2aa210030ae414782adab9291cc43a149a780f39bd3d306dc2892a8c20422a51 -R 445070ffd3b1be1286b1b020beb181c5 +P d8b46290bb75c695dac523cf9a50d1b43e773802e3b95fd722feca16162ab7c5 +R 214110ad6fdf7789b7b7a9c6d65bc1a8 U drh -Z c5a11b92ab72681e9cb438ff2daf1afb +Z 468a9bdbe012765b3a0a759e796a254f diff --git a/manifest.uuid b/manifest.uuid index 8de9ce360f..e7602bf1ed 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d8b46290bb75c695dac523cf9a50d1b43e773802e3b95fd722feca16162ab7c5 \ No newline at end of file +58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577 \ No newline at end of file diff --git a/src/attach.c b/src/attach.c index 7abdcd152e..ca0fd9fd1f 100644 --- a/src/attach.c +++ b/src/attach.c @@ -158,7 +158,7 @@ static void attachFunc( sqlite3_free( zPath ); db->nDb++; } - db->skipBtreeMutex = 0; + db->noSharedCache = 0; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf(db, "database is already attached"); @@ -230,6 +230,7 @@ static void attachFunc( if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); db->init.iDb = 0; + db->mDbFlags &= ~(DBFLAG_SchemaKnownOk); rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); assert( zErrDyn==0 || rc!=SQLITE_OK ); diff --git a/src/btmutex.c b/src/btmutex.c index ddffb67fa4..275a93ff21 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -195,10 +195,10 @@ static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){ skipOk = 0; } } - db->skipBtreeMutex = skipOk; + db->noSharedCache = skipOk; } void sqlite3BtreeEnterAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeEnterAll(db); + if( db->noSharedCache==0 ) btreeEnterAll(db); } static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ int i; @@ -210,7 +210,7 @@ static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){ } } void sqlite3BtreeLeaveAll(sqlite3 *db){ - if( db->skipBtreeMutex==0 ) btreeLeaveAll(db); + if( db->noSharedCache==0 ) btreeLeaveAll(db); } #ifndef NDEBUG diff --git a/src/build.c b/src/build.c index b032ff9f2c..9eb28572dc 100644 --- a/src/build.c +++ b/src/build.c @@ -343,24 +343,27 @@ Table *sqlite3LocateTable( const char *zDbase /* Name of the database. Might be NULL */ ){ Table *p; + sqlite3 *db = pParse->db; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ - if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 + && SQLITE_OK!=sqlite3ReadSchema(pParse) + ){ return 0; } - p = sqlite3FindTable(pParse->db, zName, zDbase); + p = sqlite3FindTable(db, zName, zDbase); if( p==0 ){ const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table"; #ifndef SQLITE_OMIT_VIRTUALTABLE - if( sqlite3FindDbName(pParse->db, zDbase)<1 ){ + if( sqlite3FindDbName(db, zDbase)<1 ){ /* If zName is the not the name of a table in the schema created using ** CREATE, then check to see if it is the name of an virtual table that ** can be an eponymous virtual table. */ - Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName); + Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName); if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){ - pMod = sqlite3PragmaVtabRegister(pParse->db, zName); + pMod = sqlite3PragmaVtabRegister(db, zName); } if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){ return pMod->pEpoTab; @@ -525,6 +528,7 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); DbSetProperty(db, iDb, DB_ResetWanted); DbSetProperty(db, 1, DB_ResetWanted); + db->mDbFlags &= ~DBFLAG_SchemaKnownOk; } if( db->nSchemaLock==0 ){ @@ -550,7 +554,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ sqlite3SchemaClear(pDb->pSchema); } } - db->mDbFlags &= ~DBFLAG_SchemaChange; + db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); sqlite3CollapseDatabaseArray(db); diff --git a/src/prepare.c b/src/prepare.c index d7cc5a9f19..c13f88d28b 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -145,6 +145,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ const char *zMasterName; int openedTransaction = 0; + assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 ); assert( iDb>=0 && iDbnDb ); assert( db->aDb[iDb].pSchema ); assert( sqlite3_mutex_held(db->mutex) ); @@ -396,10 +397,12 @@ int sqlite3ReadSchema(Parse *pParse){ assert( sqlite3_mutex_held(db->mutex) ); if( !db->init.busy ){ rc = sqlite3Init(db, &pParse->zErrMsg); - } - if( rc!=SQLITE_OK ){ - pParse->rc = rc; - pParse->nErr++; + if( rc!=SQLITE_OK ){ + pParse->rc = rc; + pParse->nErr++; + }else if( db->noSharedCache ){ + db->mDbFlags |= DBFLAG_SchemaKnownOk; + } } return rc; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 00ce823b1b..8ad15109a8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1362,7 +1362,7 @@ struct sqlite3 { u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ u8 mTrace; /* zero or more SQLITE_TRACE flags */ - u8 skipBtreeMutex; /* True if no shared-cache backends */ + u8 noSharedCache; /* True if no shared-cache backends */ u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */ int nextPagesize; /* Pagesize after VACUUM if >0 */ u32 magic; /* Magic number for detect library misuse */ @@ -1522,6 +1522,7 @@ struct sqlite3 { #define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */ #define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */ #define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */ +#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the From d11b8f671fe6203c4cd66a4d644eddb9e41ff681 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 25 Apr 2018 13:27:07 +0000 Subject: [PATCH 03/10] Add the new SQLITE_SHELL_INIT_PROC compile-time entry point to the CLI. This is needed to work around the tighter sqlite3_config() constraints now in the CLI. FossilOrigin-Name: 3bcdbccf530e2a5aab7b91f4b9e5535cced91f242c49ff69b05a75d643b8b4a3 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/shell.c.in | 12 ++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index b3f7180c63..9ca8d841ea 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\smany\sunnecessary\scalls\sto\ssqlite3ReadSchema()\sand\ssqlite3Init()\swhen\nthe\sschema\sis\sknown\sto\sbe\svalid\salready. -D 2018-04-25T12:01:45.412 +C Add\sthe\snew\sSQLITE_SHELL_INIT_PROC\scompile-time\sentry\spoint\sto\sthe\sCLI.\s\sThis\nis\sneeded\sto\swork\saround\sthe\stighter\ssqlite3_config()\sconstraints\snow\sin\sthe\nCLI. +D 2018-04-25T13:27:07.163 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -493,7 +493,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 3dbce4379836189acbc5719f40125f3d1e0dbaee024ec4550ab449744a8cb074 -F src/shell.c.in fc3f9e47198c6baea6987b6ec86fb99e7c79cee8109ce9bdece790345d8c246f +F src/shell.c.in 38aa5740e462bd3f4466ae1939d645349ea10fea65673e169cae1b018134b71a F src/sqlite.h.in aa9bd3ae4a077c7002059cb418271abe52214b0227b2a734bc44736b24cbcc40 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d @@ -1725,7 +1725,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 d8b46290bb75c695dac523cf9a50d1b43e773802e3b95fd722feca16162ab7c5 -R 214110ad6fdf7789b7b7a9c6d65bc1a8 +P 58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577 +R c07173975a3bfb0a4bc14f3247bfcc39 U drh -Z 468a9bdbe012765b3a0a759e796a254f +Z bcde754701772f8aaf655db1a8e0f6db diff --git a/manifest.uuid b/manifest.uuid index e7602bf1ed..6afd546d95 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577 \ No newline at end of file +3bcdbccf530e2a5aab7b91f4b9e5535cced91f242c49ff69b05a75d643b8b4a3 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index b56be13f77..a8d7f4ff72 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -8471,9 +8471,21 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ verify_uninitialized(); +#ifdef SQLITE_SHELL_INIT_PROC + { + /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name + ** of a C-function that will perform initialization actions on SQLite that + ** occur just before or after sqlite3_initialize(). Use this compile-time + ** option to embed this shell program in larger applications. */ + extern void SQLITE_SHELL_INIT_PROC(void); + SQLITE_SHELL_INIT_PROC(); + } +#else /* All the sqlite3_config() calls have now been made. So it is safe ** to call sqlite3_initialize() and process any command line -vfs option. */ sqlite3_initialize(); +#endif + if( zVfs ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs); if( pVfs ){ From 7eabc44dee611a7ffa90ab388892ac92d118061a Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 25 Apr 2018 17:10:30 +0000 Subject: [PATCH 04/10] Add the new DO and NOTHING keywords to the keyword lists maintained by various extensions and auxiliary programs. FossilOrigin-Name: 77a98a0781cd8450e2100111e70526db6a51d7e58e3c505ea87f685388099e82 --- ext/misc/completion.c | 5 +++-- ext/misc/dbdump.c | 5 +++-- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/shell.c.in | 5 +++-- tool/sqldiff.c | 5 +++-- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/ext/misc/completion.c b/ext/misc/completion.c index 780963515e..c65ec62212 100644 --- a/ext/misc/completion.c +++ b/ext/misc/completion.c @@ -183,12 +183,13 @@ static const char *completionKwrds[] = { "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "LEFT", "LIKE", "LIMIT", + "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", diff --git a/ext/misc/dbdump.c b/ext/misc/dbdump.c index b4d642286e..2b1bf8782e 100644 --- a/ext/misc/dbdump.c +++ b/ext/misc/dbdump.c @@ -148,12 +148,13 @@ static char quoteChar(const char *zName){ "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "LEFT", "LIKE", "LIMIT", + "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", diff --git a/manifest b/manifest index 9ca8d841ea..ef0d6df361 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\snew\sSQLITE_SHELL_INIT_PROC\scompile-time\sentry\spoint\sto\sthe\sCLI.\s\sThis\nis\sneeded\sto\swork\saround\sthe\stighter\ssqlite3_config()\sconstraints\snow\sin\sthe\nCLI. -D 2018-04-25T13:27:07.163 +C Add\sthe\snew\sDO\sand\sNOTHING\skeywords\sto\sthe\skeyword\slists\smaintained\nby\svarious\sextensions\sand\sauxiliary\sprograms. +D 2018-04-25T17:10:30.576 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -272,10 +272,10 @@ F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 -F ext/misc/completion.c 0d0bd16378415b982e7119baddef52a0d2cc25860c238a9d2832b0cc6a84a16d +F ext/misc/completion.c ba0f8ecc6ff016e52cbd3d44dd0c990f2845e3b29ddbde744d476bacd9b6bd00 F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 F ext/misc/csv.c d1e324fac3f87f818d684a3d752d1ef76dbcd4fc0db6746ac4034c19d0bcda21 -F ext/misc/dbdump.c 22018e00eb50e9ebf9067c92d4e7162dc5006a3efc4e0c19bc3829825a1043b0 +F ext/misc/dbdump.c 4469a3b6d967e4a6bf6a7b8124f1cf33c362096020e923ca27ee592854d90cf6 F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 @@ -493,7 +493,7 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 3dbce4379836189acbc5719f40125f3d1e0dbaee024ec4550ab449744a8cb074 -F src/shell.c.in 38aa5740e462bd3f4466ae1939d645349ea10fea65673e169cae1b018134b71a +F src/shell.c.in be819b84dc08e65bec15836cea6bf05303abe2ed7b46208bde76ef5ee0cdeb3d F src/sqlite.h.in aa9bd3ae4a077c7002059cb418271abe52214b0227b2a734bc44736b24cbcc40 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d @@ -1690,7 +1690,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c -F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb +F tool/sqldiff.c c86f7e70453626f8949e23c4116947e02779eaa14242e8fd6c2b899ac807b555 F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968 F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898 F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848 @@ -1725,7 +1725,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 58cf812fd81329e82b3fdd61b7ad2040c9b90d2d80f592b9231e0e1902c8d577 -R c07173975a3bfb0a4bc14f3247bfcc39 +P 3bcdbccf530e2a5aab7b91f4b9e5535cced91f242c49ff69b05a75d643b8b4a3 +R 9e60a6dd36d20684c5f81effe9563b16 U drh -Z bcde754701772f8aaf655db1a8e0f6db +Z 6dc12a942162208a495a5570be5abedc diff --git a/manifest.uuid b/manifest.uuid index 6afd546d95..a0fede738d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3bcdbccf530e2a5aab7b91f4b9e5535cced91f242c49ff69b05a75d643b8b4a3 \ No newline at end of file +77a98a0781cd8450e2100111e70526db6a51d7e58e3c505ea87f685388099e82 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index a8d7f4ff72..c5cb7ec161 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -781,12 +781,13 @@ static char quoteChar(const char *zName){ "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "LEFT", "LIKE", "LIMIT", + "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", diff --git a/tool/sqldiff.c b/tool/sqldiff.c index b31489bfd7..44f05e75f9 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -141,12 +141,13 @@ static char *safeId(const char *zId){ "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", + "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", + "LEFT", "LIKE", "LIMIT", + "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", From fc0ec3e5e839e92f8205804b1b1e836a51a8e5b5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 25 Apr 2018 19:02:48 +0000 Subject: [PATCH 05/10] Add new interfaces for accessing the list of SQL keywords: sqlite3_keyword_count(), sqlite3_keyword_name(), sqlite3_keyword_check(). FossilOrigin-Name: 7dd34e3776fed90a49344d54a1b68bb59f7957b5a8a1a367087b7cafb63111c1 --- ext/misc/completion.c | 39 +++++++------------------------ ext/misc/dbdump.c | 38 ++----------------------------- manifest | 24 ++++++++++---------- manifest.uuid | 2 +- src/main.c | 18 --------------- src/shell.c.in | 52 ++---------------------------------------- src/sqlite.h.in | 53 ++++++++++++++++++++++++++++++++++++++++++- tool/mkkeywordhash.c | 10 ++++++++ tool/sqldiff.c | 41 ++++----------------------------- 9 files changed, 92 insertions(+), 185 deletions(-) diff --git a/ext/misc/completion.c b/ext/misc/completion.c index c65ec62212..89c4f5d5db 100644 --- a/ext/misc/completion.c +++ b/ext/misc/completion.c @@ -62,6 +62,7 @@ struct completion_cursor { char *zPrefix; /* The prefix for the word we want to complete */ char *zLine; /* The whole that we want to complete */ const char *zCurrentRow; /* Current output row */ + int szRow; /* Length of the zCurrentRow string */ sqlite3_stmt *pStmt; /* Current statement */ sqlite3_int64 iRowid; /* The rowid */ int ePhase; /* Current phase */ @@ -174,33 +175,6 @@ static int completionClose(sqlite3_vtab_cursor *cur){ return SQLITE_OK; } -/* -** All SQL keywords understood by SQLite -*/ -static const char *completionKwrds[] = { - "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", - "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", - "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", - "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", - "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", - "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", - "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", - "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", - "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", - "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", - "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", - "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", - "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", - "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", - "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", - "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", - "WITH", "WITHOUT", -}; -#define completionKwCount \ - (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0])) - /* ** Advance a completion_cursor to its next row of output. ** @@ -223,11 +197,11 @@ static int completionNext(sqlite3_vtab_cursor *cur){ while( pCur->ePhase!=COMPLETION_EOF ){ switch( pCur->ePhase ){ case COMPLETION_KEYWORDS: { - if( pCur->j >= completionKwCount ){ + if( pCur->j >= sqlite3_keyword_count() ){ pCur->zCurrentRow = 0; pCur->ePhase = COMPLETION_DATABASES; }else{ - pCur->zCurrentRow = completionKwrds[pCur->j++]; + sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow); } iCol = -1; break; @@ -299,6 +273,7 @@ static int completionNext(sqlite3_vtab_cursor *cur){ if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){ /* Extract the next row of content */ pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol); + pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol); }else{ /* When all rows are finished, advance to the next phase */ sqlite3_finalize(pCur->pStmt); @@ -308,7 +283,9 @@ static int completionNext(sqlite3_vtab_cursor *cur){ } } if( pCur->nPrefix==0 ) break; - if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){ + if( pCur->nPrefix<=pCur->szRow + && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 + ){ break; } } @@ -328,7 +305,7 @@ static int completionColumn( completion_cursor *pCur = (completion_cursor*)cur; switch( i ){ case COMPLETION_COLUMN_CANDIDATE: { - sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT); + sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT); break; } case COMPLETION_COLUMN_PREFIX: { diff --git a/ext/misc/dbdump.c b/ext/misc/dbdump.c index 2b1bf8782e..2ca34a1128 100644 --- a/ext/misc/dbdump.c +++ b/ext/misc/dbdump.c @@ -141,46 +141,12 @@ static void appendText(DText *p, char const *zAppend, char quote){ ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ - /* All SQLite keywords, in alphabetical order */ - static const char *azKeywords[] = { - "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", - "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", - "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", - "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", - "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", - "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", - "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", - "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", - "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", - "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", - "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", - "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", - "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", - "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", - "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", - "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", - "WITH", "WITHOUT", - }; - int i, lwr, upr, mid, c; + int i; if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; for(i=0; zName[i]; i++){ if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; } - lwr = 0; - upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; - while( lwr<=upr ){ - mid = (lwr+upr)/2; - c = sqlite3_stricmp(azKeywords[mid], zName); - if( c==0 ) return '"'; - if( c<0 ){ - lwr = mid+1; - }else{ - upr = mid-1; - } - } - return 0; + return sqlite3_keyword_check(zName, i) ? '"' : 0; } diff --git a/manifest b/manifest index ef0d6df361..31c841268b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\snew\sDO\sand\sNOTHING\skeywords\sto\sthe\skeyword\slists\smaintained\nby\svarious\sextensions\sand\sauxiliary\sprograms. -D 2018-04-25T17:10:30.576 +C Add\snew\sinterfaces\sfor\saccessing\sthe\slist\sof\sSQL\skeywords:\nsqlite3_keyword_count(),\ssqlite3_keyword_name(),\ssqlite3_keyword_check(). +D 2018-04-25T19:02:48.148 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -272,10 +272,10 @@ F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256 F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 -F ext/misc/completion.c ba0f8ecc6ff016e52cbd3d44dd0c990f2845e3b29ddbde744d476bacd9b6bd00 +F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483 F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 F ext/misc/csv.c d1e324fac3f87f818d684a3d752d1ef76dbcd4fc0db6746ac4034c19d0bcda21 -F ext/misc/dbdump.c 4469a3b6d967e4a6bf6a7b8124f1cf33c362096020e923ca27ee592854d90cf6 +F ext/misc/dbdump.c 69ef1be5b210538f77dfcc6fcb55b4b5f5e98b1e0bcfd67d818711e10761db4d F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3 F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 @@ -456,7 +456,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302 -F src/main.c 10e3897f5d78cef6bcbd1eedc8ccc3fe9e9783d07e052d9d70e57364ded19274 +F src/main.c f579a7a1e6a602cf752ee910ef541481124bac9dfa7db720e698efdf5521bfd3 F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -493,8 +493,8 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c 3dbce4379836189acbc5719f40125f3d1e0dbaee024ec4550ab449744a8cb074 -F src/shell.c.in be819b84dc08e65bec15836cea6bf05303abe2ed7b46208bde76ef5ee0cdeb3d -F src/sqlite.h.in aa9bd3ae4a077c7002059cb418271abe52214b0227b2a734bc44736b24cbcc40 +F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3da +F src/sqlite.h.in 8e70752a57597c08f64f3d49fc1fc46926b862d2e23b038b0d23b9cc748d88ea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d F src/sqliteInt.h c1deb023eb117b4437a69d8c5a753deb36581f1933015cd262ad32b45c4d8431 @@ -1653,7 +1653,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3 -F tool/mkkeywordhash.c 98d7ce6f8ed32f23d6b30fbde6d9ed466d4ae38a9f8add20a36bebd3df56171c +F tool/mkkeywordhash.c 20f366ad3794e1db42e333a6f35fa41a024f2e3528579c9d58eb13eaa3ab4913 F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee @@ -1690,7 +1690,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c -F tool/sqldiff.c c86f7e70453626f8949e23c4116947e02779eaa14242e8fd6c2b899ac807b555 +F tool/sqldiff.c 579d7e4e42c30a963781654c87d2868823120b55d59e16ca77b0edbab0218713 F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968 F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898 F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848 @@ -1725,7 +1725,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 3bcdbccf530e2a5aab7b91f4b9e5535cced91f242c49ff69b05a75d643b8b4a3 -R 9e60a6dd36d20684c5f81effe9563b16 +P 77a98a0781cd8450e2100111e70526db6a51d7e58e3c505ea87f685388099e82 +R 10bd4b7452c152b5d411c22798c11389 U drh -Z 6dc12a942162208a495a5570be5abedc +Z 7768be7af0a3a3c7678dcf3e883a5c90 diff --git a/manifest.uuid b/manifest.uuid index a0fede738d..ebcd80ab08 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -77a98a0781cd8450e2100111e70526db6a51d7e58e3c505ea87f685388099e82 \ No newline at end of file +7dd34e3776fed90a49344d54a1b68bb59f7957b5a8a1a367087b7cafb63111c1 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 99e3e6f970..442067a14e 100644 --- a/src/main.c +++ b/src/main.c @@ -3861,24 +3861,6 @@ int sqlite3_test_control(int op, ...){ break; } -#ifdef SQLITE_N_KEYWORD - /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) - ** - ** If zWord is a keyword recognized by the parser, then return the - ** number of keywords. Or if zWord is not a keyword, return 0. - ** - ** This test feature is only available in the amalgamation since - ** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite - ** is built using separate source files. - */ - case SQLITE_TESTCTRL_ISKEYWORD: { - const char *zWord = va_arg(ap, const char*); - int n = sqlite3Strlen30(zWord); - rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0; - break; - } -#endif - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** ** If parameter onoff is non-zero, configure the wrappers so that all diff --git a/src/shell.c.in b/src/shell.c.in index c5cb7ec161..c0e5c7a75c 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -774,46 +774,12 @@ static void appendText(ShellText *p, char const *zAppend, char quote){ ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ - /* All SQLite keywords, in alphabetical order */ - static const char *azKeywords[] = { - "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", - "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", - "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", - "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", - "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", - "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", - "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", - "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", - "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", - "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", - "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", - "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", - "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", - "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", - "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", - "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", - "WITH", "WITHOUT", - }; - int i, lwr, upr, mid, c; + int i; if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; for(i=0; zName[i]; i++){ if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; } - lwr = 0; - upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; - while( lwr<=upr ){ - mid = (lwr+upr)/2; - c = sqlite3_stricmp(azKeywords[mid], zName); - if( c==0 ) return '"'; - if( c<0 ){ - lwr = mid+1; - }else{ - upr = mid-1; - } - } - return 0; + return sqlite3_keyword_check(zName, i) ? '"' : 0; } /* @@ -7497,9 +7463,6 @@ static int do_meta_command(char *zLine, ShellState *p){ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, -#ifdef SQLITE_N_KEYWORD - { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD, "IDENTIFIER" }, -#endif { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, @@ -7611,17 +7574,6 @@ static int do_meta_command(char *zLine, ShellState *p){ } break; - /* sqlite3_test_control(int, char *) */ -#ifdef SQLITE_N_KEYWORD - case SQLITE_TESTCTRL_ISKEYWORD: - if( nArg==3 ){ - const char *opt = azArg[2]; - rc2 = sqlite3_test_control(testctrl, opt); - isOk = 1; - } - break; -#endif - case SQLITE_TESTCTRL_IMPOSTER: if( nArg==5 ){ rc2 = sqlite3_test_control(testctrl, p->db, diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 02dc8944b9..4d84bf3eb6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7016,7 +7016,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 -#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ @@ -7030,6 +7030,57 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_PARSER_COVERAGE 26 #define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */ +/* +** CAPI3REF: SQL Keyword Checking +** +** These routines provide access to the set of SQL language keywords +** recognized by SQLite. Applications can uses these routines to determine +** whether or not a specific identifier needs to be escaped (for example, +** by enclosing in double-quotes) so as not to confuse the parser. +** +** The sqlite3_keyword_count() interface returns the number of distinct +** keywords understood by SQLite. +** +** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and +** makes *Z point to that keyword expressed as UTF8 and writes the number +** of bytes in the keyword into *L. The string that *Z points to is not +** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns +** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z +** or L are NULL or invalid pointers then calls to +** sqlite3_keyword_name(N,Z,L) result in undefined behavior. +** +** The sqlite3_keyword_check(Z,L) interface checks to see whether or not +** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero +** if it is and zero if not. +** +** The parser used by SQLite is forgiving. It is often possible to use +** a keyword as an identifier as long as such use does not result in a +** parsing ambiguity. For example, the statement +** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and +** creates a new table named "BEGIN" with three columns named +** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid +** using keywords as identifiers. Common techniques used to avoid keyword +** name collisions include: +**
    +**
  • Put all indentifier names inside double-quotes. This is the official +** SQL way to escape identifier names. +**
  • Put identifier names inside [...]. This is not standard SQL, +** but it is what SQL Server does and so lots of programmers use this +** technique. +**
  • Begin every identifier with the letter "Z" as no SQL keywords start +** with "Z". +**
  • Include a digit somewhere in every identifier name. +**
+** +** Note that the number of keywords understood by SQLite can depend on +** compile-time options. For example, "VACUUM" is not a keyword if +** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also, +** new keywords may be added to future releases of SQLite. +*/ +int sqlite3_keyword_count(void); +int sqlite3_keyword_name(int,const char**,int*); +int sqlite3_keyword_check(const char*,int); + /* ** CAPI3REF: SQLite Runtime Status ** diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index 532bde1bb0..ec85131b64 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -617,6 +617,16 @@ int main(int argc, char **argv){ printf(" return id;\n"); printf("}\n"); printf("#define SQLITE_N_KEYWORD %d\n", nKeyword); + printf("int sqlite3_keyword_name(int i,const char **pzName,int *pnName){\n"); + printf(" if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;\n"); + printf(" *pzName = zKWText + aKWOffset[i];\n"); + printf(" *pnName = aKWLen[i];\n"); + printf(" return SQLITE_OK;\n"); + printf("}\n"); + printf("int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; }\n"); + printf("int sqlite3_keyword_check(const char *zName, int nName){\n"); + printf(" return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName);\n"); + printf("}\n"); return 0; } diff --git a/tool/sqldiff.c b/tool/sqldiff.c index 44f05e75f9..509470a156 100644 --- a/tool/sqldiff.c +++ b/tool/sqldiff.c @@ -134,29 +134,8 @@ static void strPrintf(Str *p, const char *zFormat, ...){ ** needed. */ static char *safeId(const char *zId){ - /* All SQLite keywords, in alphabetical order */ - static const char *azKeywords[] = { - "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", - "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", - "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", - "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", - "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", - "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DO", "DROP", "EACH", - "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", - "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", - "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", - "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", - "LEFT", "LIKE", "LIMIT", - "MATCH", "NATURAL", "NO", "NOT", "NOTHING", "NOTNULL", - "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", - "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP", - "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", - "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", - "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", - "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", - "WITH", "WITHOUT", - }; - int lwr, upr, mid, c, i, x; + int i, x; + char c; if( zId[0]==0 ) return sqlite3_mprintf("\"\""); for(i=x=0; (c = zId[i])!=0; i++){ if( !isalpha(c) && c!='_' ){ @@ -167,20 +146,10 @@ static char *safeId(const char *zId){ } } } - if( x ) return sqlite3_mprintf("%s", zId); - lwr = 0; - upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1; - while( lwr<=upr ){ - mid = (lwr+upr)/2; - c = sqlite3_stricmp(azKeywords[mid], zId); - if( c==0 ) return sqlite3_mprintf("\"%w\"", zId); - if( c<0 ){ - lwr = mid+1; - }else{ - upr = mid-1; - } + if( x || !sqlite3_keyword_check(zId,i) ){ + return sqlite3_mprintf("%s", zId); } - return sqlite3_mprintf("%s", zId); + return sqlite3_mprintf("\"%w\"", zId); } /* From 1e0807490633b2f1f3b059bbfd2970b6a88c0861 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Apr 2018 08:56:40 +0000 Subject: [PATCH 06/10] Update the "fuzz_malloc.test" script to print SQL statements in which OOM handling problems are found to stdout. FossilOrigin-Name: a956363cf6881be590120c7718976b54b12c4bd0d9228d8142b45e0fe1826f7e --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/fuzz_malloc.test | 5 +++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 31c841268b..911ec82612 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sinterfaces\sfor\saccessing\sthe\slist\sof\sSQL\skeywords:\nsqlite3_keyword_count(),\ssqlite3_keyword_name(),\ssqlite3_keyword_check(). -D 2018-04-25T19:02:48.148 +C Update\sthe\s"fuzz_malloc.test"\sscript\sto\sprint\sSQL\sstatements\sin\swhich\sOOM\nhandling\sproblems\sare\sfound\sto\sstdout. +D 2018-04-26T08:56:40.175 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -938,7 +938,7 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1 F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1 F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31 F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b -F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26 +F test/fuzz_malloc.test cf82eab3d93cd3e38b2d53c13c6739ff4cd5b1c31c2c45edd0bcee78e7060c2b F test/fuzzcheck.c 5eb86c6ac96833ee622f45bf47e8045999c1b4b10d05e4eb809894a4b39f2f84 F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664 F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973 @@ -1725,7 +1725,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 77a98a0781cd8450e2100111e70526db6a51d7e58e3c505ea87f685388099e82 -R 10bd4b7452c152b5d411c22798c11389 -U drh -Z 7768be7af0a3a3c7678dcf3e883a5c90 +P 7dd34e3776fed90a49344d54a1b68bb59f7957b5a8a1a367087b7cafb63111c1 +R 87ecaa91f6e5e22199ca34eced6f5939 +U dan +Z 215188660de40b918f194a41b8c6d741 diff --git a/manifest.uuid b/manifest.uuid index ebcd80ab08..ed66c889c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7dd34e3776fed90a49344d54a1b68bb59f7957b5a8a1a367087b7cafb63111c1 \ No newline at end of file +a956363cf6881be590120c7718976b54b12c4bd0d9228d8142b45e0fe1826f7e \ No newline at end of file diff --git a/test/fuzz_malloc.test b/test/fuzz_malloc.test index 1e31babd92..b01b9d7ae4 100644 --- a/test/fuzz_malloc.test +++ b/test/fuzz_malloc.test @@ -59,7 +59,12 @@ proc do_fuzzy_malloc_test {testname args} { # puts fuzyy-sql=\[$::sql\]; flush stdout foreach {rc res} [catchsql "$::sql"] {} if {$rc==0} { + set nErr1 [set_test_counter errors] do_malloc_test $testname-$ii -sqlbody $::sql -sqlprep $::prep + if {[set_test_counter errors]>$nErr1} { + puts "Previous fuzzy-sql=\[$::sql\]" + flush stdout + } } else { incr ii -1 } From 896494e8ad691ac9302786a4dfcb97020ee1dc32 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 26 Apr 2018 12:27:03 +0000 Subject: [PATCH 07/10] Improved VDBE comment on the OP_Param opcode. No substantial changes. FossilOrigin-Name: 368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/expr.c | 5 ++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 911ec82612..b7531d4c76 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\s"fuzz_malloc.test"\sscript\sto\sprint\sSQL\sstatements\sin\swhich\sOOM\nhandling\sproblems\sare\sfound\sto\sstdout. -D 2018-04-26T08:56:40.175 +C Improved\sVDBE\scomment\son\sthe\sOP_Param\sopcode.\s\sNo\ssubstantial\schanges. +D 2018-04-26T12:27:03.691 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -444,7 +444,7 @@ F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f -F src/expr.c 9a3b6eaa86c0e049d4da975972e62746383752ea4375a164c277ed49f70af277 +F src/expr.c 4a39bc2a9a3d825571519a1910ecfe3d4b6d596e775c9ed7cef7497ea06140ac F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51 @@ -1725,7 +1725,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 7dd34e3776fed90a49344d54a1b68bb59f7957b5a8a1a367087b7cafb63111c1 -R 87ecaa91f6e5e22199ca34eced6f5939 -U dan -Z 215188660de40b918f194a41b8c6d741 +P a956363cf6881be590120c7718976b54b12c4bd0d9228d8142b45e0fe1826f7e +R 67e4930e9711eb625aa31c5083fa85ba +U drh +Z bd6cee7c5fa35b400b9c5a8450cb9640 diff --git a/manifest.uuid b/manifest.uuid index ed66c889c8..6175b6c3c8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a956363cf6881be590120c7718976b54b12c4bd0d9228d8142b45e0fe1826f7e \ No newline at end of file +368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 6513c5ec7f..03fad6cc52 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4049,10 +4049,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( p1>=0 && p1<(pTab->nCol*2+2) ); sqlite3VdbeAddOp2(v, OP_Param, p1, target); - VdbeComment((v, "%s.%s -> $%d", + VdbeComment((v, "r[%d]=%s.%s", target, (pExpr->iTable ? "new" : "old"), - (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName), - target + (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName) )); #ifndef SQLITE_OMIT_FLOATING_POINT From de7ca50dac6a05b75ec4375116f1bcde8f19ded3 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 26 Apr 2018 15:04:18 +0000 Subject: [PATCH 08/10] Clarification of the behavior of a BEFORE UPDATE trigger when the trigger changes the values of some of the columns used to compute new columns in the UPDATE. FossilOrigin-Name: 7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/update.c | 9 ++++++--- test/trigger1.test | 23 +++++++++++++++++++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b7531d4c76..954f369eef 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sVDBE\scomment\son\sthe\sOP_Param\sopcode.\s\sNo\ssubstantial\schanges. -D 2018-04-26T12:27:03.691 +C Clarification\sof\sthe\sbehavior\sof\sa\sBEFORE\sUPDATE\strigger\swhen\sthe\strigger\nchanges\sthe\svalues\sof\ssome\sof\sthe\scolumns\sused\sto\scompute\snew\scolumns\sin\nthe\sUPDATE. +D 2018-04-26T15:04:18.138 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -557,7 +557,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97 F src/treeview.c 6cea286ca9af8b126dae9714799265353387244eba0d451c3cc2cd60946cc4c7 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 -F src/update.c 0d53281948be1c7f7242151fe9adcdcb02eb9faeb1ee4c98cffd67c12adc3599 +F src/update.c 2946cf3c6995f9d5cdccedcc08339d18b8eae72c15f06c011ef3230550c0583b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1477,7 +1477,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677 -F test/trigger1.test ea9624cc1dae05645469df6119fa815f9e6f1e8c +F test/trigger1.test d7bdbff72c65293dddc8a443c3fd90b957869ac274c5e25ea6acc326f5e3c233 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 @@ -1725,7 +1725,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 a956363cf6881be590120c7718976b54b12c4bd0d9228d8142b45e0fe1826f7e -R 67e4930e9711eb625aa31c5083fa85ba +P 368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 +R d67c07078741cec11cd337cb536cdcc8 U drh -Z bd6cee7c5fa35b400b9c5a8450cb9640 +Z aca21fa0a22205b706503004c2920563 diff --git a/manifest.uuid b/manifest.uuid index 6175b6c3c8..1c442962fc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 \ No newline at end of file +7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 \ No newline at end of file diff --git a/src/update.c b/src/update.c index 80f3b43e86..dcab4eeb0b 100644 --- a/src/update.c +++ b/src/update.c @@ -639,10 +639,13 @@ void sqlite3Update( VdbeCoverage(v); } - /* If it did not delete it, the row-trigger may still have modified + /* If it did not delete it, the BEFORE trigger may still have modified ** some of the columns of the row being updated. Load the values for - ** all columns not modified by the update statement into their - ** registers in case this has happened. + ** all columns not modified by the update statement into their registers + ** in case this has happened. Only unmodified columns are reloaded. + ** The values computed for modified columns use the values before the + ** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26) + ** for an example. */ for(i=0; inCol; i++){ if( aXRef[i]<0 && i!=pTab->iPKey ){ diff --git a/test/trigger1.test b/test/trigger1.test index a190efd464..e785343b35 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -728,4 +728,27 @@ do_execsql_test trigger1-17.0 { PRAGMA integrity_check; } {ok} +# 2018-04-26 +# When a BEFORE UPDATE trigger changes a column value in a row being +# updated, and that column value is used by the UPDATE to change other +# column, the value used to compute the update is from before the trigger. +# In the example that follows, the value of "b" in "c=b" is 2 (the value +# prior to running the BEFORE UPDATE trigger) not 1000. +# +do_execsql_test trigger1-18.0 { + CREATE TABLE t18(a PRIMARY KEY,b,c); + INSERT INTO t18(a,b,c) VALUES(1,2,3); + CREATE TRIGGER t18r1 BEFORE UPDATE ON t18 BEGIN + UPDATE t18 SET b=1000 WHERE a=old.a; + END; + UPDATE t18 SET c=b WHERE a=1; + SELECT * FROM t18; +} {1 1000 2} ;# Not: 1 1000 1000 +do_execsql_test trigger1-18.1 { + DELETE FROM t18; + INSERT INTO t18(a,b,c) VALUES(1,2,3); + UPDATE t18 SET c=b, b=b+1 WHERE a=1; + SELECT * FROM t18; +} {1 3 2} ;# Not: 1 1001 1000 + finish_test From 909066bba06bdedf84f2b24dee32479341058489 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 26 Apr 2018 15:50:10 +0000 Subject: [PATCH 09/10] Ensure that new.* values of an UPDATE do not get clobbered after the BEFORE triggers run when unmodified columns of the row being updated are reloaded. Fix for ticket [d85fffd6ffe856092ed8da] FossilOrigin-Name: 0a514e62ad1ebe5c12da8daed429ae2f9d9910471d3c5cef3b6870bdadfefca1 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/update.c | 9 ++++++++- src/vdbe.h | 1 + src/vdbeaux.c | 6 ++++++ test/trigger1.test | 11 +++++++++++ 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 954f369eef..11e53dfe69 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarification\sof\sthe\sbehavior\sof\sa\sBEFORE\sUPDATE\strigger\swhen\sthe\strigger\nchanges\sthe\svalues\sof\ssome\sof\sthe\scolumns\sused\sto\scompute\snew\scolumns\sin\nthe\sUPDATE. -D 2018-04-26T15:04:18.138 +C Ensure\sthat\snew.*\svalues\sof\san\sUPDATE\sdo\snot\sget\sclobbered\safter\sthe\nBEFORE\striggers\srun\swhen\sunmodified\scolumns\sof\sthe\srow\sbeing\supdated\sare\nreloaded.\s\sFix\sfor\sticket\s[d85fffd6ffe856092ed8da] +D 2018-04-26T15:50:10.476 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -557,16 +557,16 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97 F src/treeview.c 6cea286ca9af8b126dae9714799265353387244eba0d451c3cc2cd60946cc4c7 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 -F src/update.c 2946cf3c6995f9d5cdccedcc08339d18b8eae72c15f06c011ef3230550c0583b +F src/update.c 75ac1102d791d999ca918d7b3dced4b3023fb0ed1167a4b11591c5bc3cfbb439 F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5 F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 -F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd +F src/vdbe.h fff31fb658cf1aac5a2fb4d06f8d16589aef38a906e78a1565a78b8c5df7fc0a F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 -F src/vdbeaux.c 944bae5207bbce456c466d01dcf2aac3ad49c957325d35c0ba7de882d3e5c25c +F src/vdbeaux.c b82ca213e6b5461ef773beb76a2cfb720b301372dd4797007eb13ef6cf6f18c4 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191 F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f @@ -1477,7 +1477,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677 -F test/trigger1.test d7bdbff72c65293dddc8a443c3fd90b957869ac274c5e25ea6acc326f5e3c233 +F test/trigger1.test 254eb5245c472af5fd5a6d8c321f7af97b8532db2eff7a24c31ac67155a12c27 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 @@ -1725,7 +1725,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 368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 -R d67c07078741cec11cd337cb536cdcc8 +P 7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 +R fca770ecccc439d6123031b9ede2b90c U drh -Z aca21fa0a22205b706503004c2920563 +Z 0f59500027b236c3f3feca2847bff4bf diff --git a/manifest.uuid b/manifest.uuid index 1c442962fc..83dbc5ed7f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 \ No newline at end of file +0a514e62ad1ebe5c12da8daed429ae2f9d9910471d3c5cef3b6870bdadfefca1 \ No newline at end of file diff --git a/src/update.c b/src/update.c index dcab4eeb0b..d098df820d 100644 --- a/src/update.c +++ b/src/update.c @@ -602,6 +602,12 @@ void sqlite3Update( j = aXRef[i]; if( j>=0 ){ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i); + if( tmask&TRIGGER_BEFORE ){ + /* Must preserve copied values even in case the original is + ** reloaded in the After-BEFORE-trigger-reload-loop below. + ** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28 */ + sqlite3VdbeSwapOpcode(v, -1, OP_SCopy, OP_Copy); + } }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){ /* This branch loads the value of a column that will not be changed ** into a register. This is done if there are no BEFORE triggers, or @@ -639,7 +645,8 @@ void sqlite3Update( VdbeCoverage(v); } - /* If it did not delete it, the BEFORE trigger may still have modified + /* After-BEFORE-trigger-reload-loop: + ** If it did not delete it, the BEFORE trigger may still have modified ** some of the columns of the row being updated. Load the values for ** all columns not modified by the update statement into their registers ** in case this has happened. Only unmodified columns are reloaded. diff --git a/src/vdbe.h b/src/vdbe.h index 60525a9e9e..6dcf2e4dd2 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -200,6 +200,7 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int); VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8); +void sqlite3VdbeSwapOpcode(Vdbe*, u32 addr, u8, u8); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index be092b98b7..aff08ea3e6 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -843,6 +843,12 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; } +/* Change the opcode to iNew if it was previously iOld */ +void sqlite3VdbeSwapOpcode(Vdbe *p, u32 addr, u8 iOld, u8 iNew){ + VdbeOp *pOp = sqlite3VdbeGetOp(p,addr); + if( pOp->opcode==iOld ) pOp->opcode = iNew; +} + /* ** Change the P2 operand of instruction addr so that it points to ** the address of the next instruction to be coded. diff --git a/test/trigger1.test b/test/trigger1.test index e785343b35..f3a0e62977 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -751,4 +751,15 @@ do_execsql_test trigger1-18.1 { SELECT * FROM t18; } {1 3 2} ;# Not: 1 1001 1000 +# 2018-04-26 ticket [https://www.sqlite.org/src/tktview/d85fffd6ffe856092e] +# VDBE Program uses an expired value. +# +do_execsql_test trigger1-19.0 { + CREATE TABLE t19(a INT PRIMARY KEY, b, c)WITHOUT ROWID; + INSERT INTO t19(a,b,c) VALUES(1,2,3); + CREATE TRIGGER t19r3 BEFORE UPDATE ON t19 BEGIN SELECT new.b; END; + UPDATE t19 SET c=b WHERE a=1; + SELECT * FROM t19; +} {1 2 2} + finish_test From f226f03d4fde3d2e374254e359b648c999124e5a Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Apr 2018 16:13:47 +0000 Subject: [PATCH 10/10] When processing an "ORDER BY ... LIMIT" that does not use an index, check whether or not a record may appear in the final result set before adding it to the sorter. FossilOrigin-Name: 71bf91c218334381b1b4bdba6a093e623b62e17f3e8550e154a11f0cb0b404f3 --- manifest | 17 +++++++++------ manifest.uuid | 2 +- src/select.c | 59 ++++++++++++++++++++++++++------------------------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index 954f369eef..21484880f4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarification\sof\sthe\sbehavior\sof\sa\sBEFORE\sUPDATE\strigger\swhen\sthe\strigger\nchanges\sthe\svalues\sof\ssome\sof\sthe\scolumns\sused\sto\scompute\snew\scolumns\sin\nthe\sUPDATE. -D 2018-04-26T15:04:18.138 +C When\sprocessing\san\s"ORDER\sBY\s...\sLIMIT"\sthat\sdoes\snot\suse\san\sindex,\scheck\nwhether\sor\snot\sa\srecord\smay\sappear\sin\sthe\sfinal\sresult\sset\sbefore\sadding\sit\sto\nthe\ssorter. +D 2018-04-26T16:13:47.273 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439 @@ -492,7 +492,7 @@ F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 3dbce4379836189acbc5719f40125f3d1e0dbaee024ec4550ab449744a8cb074 +F src/select.c daf07d8defce3311f9e69f1280a874d78bc1d16c305f6aa689640f7afa02842f F src/shell.c.in d63f06c870ec1761ea98bd1cae651ff0ea6beadf8be892105dabd913f94cb3da F src/sqlite.h.in 8e70752a57597c08f64f3d49fc1fc46926b862d2e23b038b0d23b9cc748d88ea F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1725,7 +1725,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 368c14da868a843767344f6cc17c499fddd83244c0510337ed9a918e64ee2413 -R d67c07078741cec11cd337cb536cdcc8 -U drh -Z aca21fa0a22205b706503004c2920563 +P 7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 +R 6079da62ec760c692d1ac980ae12bf44 +T *branch * sorter-limit-opt +T *sym-sorter-limit-opt * +T -sym-trunk * +U dan +Z 8f9d35d6b39a3409ee54166c5149a9b9 diff --git a/manifest.uuid b/manifest.uuid index 1c442962fc..2cb0bbfb3c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7bb23c2a3d37f0d5e5515b917860818906819d54a0066e1ba8e9792a82f7d279 \ No newline at end of file +71bf91c218334381b1b4bdba6a093e623b62e17f3e8550e154a11f0cb0b404f3 \ No newline at end of file diff --git a/src/select.c b/src/select.c index 79fc211147..ac313d0288 100644 --- a/src/select.c +++ b/src/select.c @@ -579,7 +579,6 @@ static void pushOntoSorter( if( nPrefixReg==0 && nData>0 ){ sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); if( nOBSat>0 ){ int regPrevKey; /* The first nOBSat columns of the previous row */ int addrFirst; /* Address of the OP_IfNot opcode */ @@ -588,6 +587,7 @@ static void pushOntoSorter( int nKey; /* Number of sorting key columns, including OP_Sequence */ KeyInfo *pKI; /* Original KeyInfo on the sorter table */ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord); regPrevKey = pParse->nMem+1; pParse->nMem += pSort->nOBSat; nKey = nExpr - pSort->nOBSat + bSeq; @@ -621,6 +621,35 @@ static void pushOntoSorter( sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); sqlite3VdbeJumpHere(v, addrJmp); } + if( iLimit ){ + /* At this point the values for the new sorter entry are stored + ** in an array of registers. They need to be composed into a record + ** and inserted into the sorter if either (a) there are currently + ** less than LIMIT+OFFSET items or (b) the new record is smaller than + ** the largest record currently in the sorter. If (b) is true and there + ** are already LIMIT+OFFSET items in the sorter, delete the largest + ** entry before inserting the new one. This way there are never more + ** than LIMIT+OFFSET items in the sorter. + ** + ** If the new record does not need to be inserted into the sorter, + ** jump to the next iteration of the loop. Or, if the + ** pSort->bOrderedInnerLoop flag is set to indicate that the inner + ** loop delivers items in sorted order, jump to the next iteration + ** of the outer loop. + */ + int iCsr = pSort->iECursor; + int iJmp = sqlite3VdbeCurrentAddr(v)+5+(nOBSat<=0)+pSort->bOrderedInnerLoop; + assert( pSort->bOrderedInnerLoop==0 || pSort->bOrderedInnerLoop==1 ); + sqlite3VdbeAddOp2(v, OP_IfNotZero, iLimit, sqlite3VdbeCurrentAddr(v)+4); + VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Last, iCsr, 0); + sqlite3VdbeAddOp4Int(v, OP_IdxLE, iCsr, iJmp, regBase+nOBSat, nExpr-nOBSat); + VdbeCoverage(v); + sqlite3VdbeAddOp1(v, OP_Delete, iCsr); + } + if( nOBSat<=0 ){ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat,regRecord); + } if( pSort->sortFlags & SORTFLAG_UseSorter ){ op = OP_SorterInsert; }else{ @@ -628,34 +657,6 @@ static void pushOntoSorter( } sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord, regBase+nOBSat, nBase-nOBSat); - if( iLimit ){ - int addr; - int r1 = 0; - /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit - ** register is initialized with value of LIMIT+OFFSET.) After the sorter - ** fills up, delete the least entry in the sorter after each insert. - ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */ - addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v); - sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); - if( pSort->bOrderedInnerLoop ){ - r1 = ++pParse->nMem; - sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1); - VdbeComment((v, "seq")); - } - sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); - if( pSort->bOrderedInnerLoop ){ - /* If the inner loop is driven by an index such that values from - ** the same iteration of the inner loop are in sorted order, then - ** immediately jump to the next iteration of an inner loop if the - ** entry from the current iteration does not fit into the top - ** LIMIT+OFFSET entries of the sorter. */ - int iBrk = sqlite3VdbeCurrentAddr(v) + 2; - sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1); - sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); - VdbeCoverage(v); - } - sqlite3VdbeJumpHere(v, addr); - } } /*