Subject: [PATCH] Do not allow a virtual table to be renamed into the name of one of its shadows. --- src/alter.c | 5 ++++- src/build.c | 29 +++++++++++++++++++++++------ src/sqliteInt.h | 5 +++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/alter.c b/src/alter.c index 1280e90..0fa24c0 100644 --- a/src/alter.c +++ b/src/alter.c @@ -117,7 +117,10 @@ void sqlite3AlterRenameTable( /* Check that a table or index named 'zName' does not already exist ** in database iDb. If so, this is an error. */ - if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + if( sqlite3FindTable(db, zName, zDb) + || sqlite3FindIndex(db, zName, zDb) + || sqlite3IsShadowTableOf(db, pTab, zName) + ){ sqlite3ErrorMsg(pParse, "there is already another table or index with this name: %s", zName); goto exit_rename_table; diff --git a/src/build.c b/src/build.c index e0fed8a..afe4171 100644 --- a/src/build.c +++ b/src/build.c @@ -1899,6 +1899,28 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ recomputeColumnsNotIndexed(pPk); } + +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Return true if pTab is a virtual table and zName is a shadow table name +** for that virtual table. +*/ +int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){ + int nName; /* Length of zName */ + Module *pMod; /* Module for the virtual table */ + + if( !IsVirtual(pTab) ) return 0; + nName = sqlite3Strlen30(pTab->zName); + if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0; + if( zName[nName]!='_' ) return 0; + pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); + if( pMod==0 ) return 0; + if( pMod->pModule->iVersion<3 ) return 0; + if( pMod->pModule->xShadowName==0 ) return 0; + return pMod->pModule->xShadowName(zName+nName+1); +} +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Return true if zName is a shadow table name in the current database @@ -1910,7 +1932,6 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ static int isShadowTableName(sqlite3 *db, char *zName){ char *zTail; /* Pointer to the last "_" in zName */ Table *pTab; /* Table that zName is a shadow of */ - Module *pMod; /* Module for the virtual table */ zTail = strrchr(zName, '_'); if( zTail==0 ) return 0; @@ -1919,11 +1940,7 @@ static int isShadowTableName(sqlite3 *db, char *zName){ *zTail = '_'; if( pTab==0 ) return 0; if( !IsVirtual(pTab) ) return 0; - pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]); - if( pMod==0 ) return 0; - if( pMod->pModule->iVersion<3 ) return 0; - if( pMod->pModule->xShadowName==0 ) return 0; - return pMod->pModule->xShadowName(zTail+1); + return sqlite3IsShadowTableOf(db, pTab, zName); } #else # define isShadowTableName(x,y) 0 diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b7d3571..76337f7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4407,6 +4407,11 @@ void sqlite3AutoLoadExtensions(sqlite3*); ); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); +#else +# define sqlite3IsShadowTableOf(A,B,C) 0 +#endif int sqlite3VtabEponymousTableInit(Parse*,Module*); void sqlite3VtabEponymousTableClear(sqlite3*,Module*); void sqlite3VtabMakeWritable(Parse*,Table*); -- 2.24.1