diff options
author | drh <drh@noemail.net> | 2018-08-14 19:27:51 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2018-08-14 19:27:51 +0000 |
commit | 1595abcda65adeaf8bddaba36d133b414ff86cdf (patch) | |
tree | 0c12a356aed186e9633d5d38bc846222ec27b4a3 /src | |
parent | 5550b5eee7d51370ff326b1e741f6c0a3c737666 (diff) | |
download | sqlite-1595abcda65adeaf8bddaba36d133b414ff86cdf.tar.gz sqlite-1595abcda65adeaf8bddaba36d133b414ff86cdf.zip |
Improved error messages when an ALTER TABLE RENAME COLUMN fails due to a
duplicate column name.
FossilOrigin-Name: 37d11b8e8224a8b241ff57b9c4b9499db39dde4ddcb56ff8b03a3d08091a4c11
Diffstat (limited to 'src')
-rw-r--r-- | src/alter.c | 1 | ||||
-rw-r--r-- | src/prepare.c | 21 | ||||
-rw-r--r-- | src/sqliteInt.h | 8 | ||||
-rw-r--r-- | src/vdbe.c | 7 |
4 files changed, 26 insertions, 11 deletions
diff --git a/src/alter.c b/src/alter.c index f908933cd..09cbd75bc 100644 --- a/src/alter.c +++ b/src/alter.c @@ -1126,7 +1126,6 @@ static void renameColumnFunc( for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){ for(i=0; i<pFKey->nCol; i++){ - RenameToken *pTok = 0; if( bFKOnly==0 && pFKey->aCol[i].iFrom==sCtx.iCol ){ renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]); } diff --git a/src/prepare.c b/src/prepare.c index 14017d879..4d4b98d8a 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -25,15 +25,23 @@ static void corruptSchema( const char *zExtra /* Error information */ ){ sqlite3 *db = pData->db; - if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){ + if( db->mallocFailed ){ + pData->rc = SQLITE_NOMEM_BKPT; + }else if( pData->pzErrMsg[0]!=0 ){ + /* A error message has already been generated. Do not overwrite it */ + }else if( pData->mInitFlags & INITFLAG_AlterTable ){ + *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra); + pData->rc = SQLITE_ERROR; + }else if( db->flags & SQLITE_WriteSchema ){ + pData->rc = SQLITE_CORRUPT_BKPT; + }else{ char *z; if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); - sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; + pData->rc = SQLITE_CORRUPT_BKPT; } - pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT; } /* @@ -132,7 +140,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ -int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ +int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){ int rc; int i; #ifndef SQLITE_OMIT_DEPRECATED @@ -167,6 +175,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ initData.iDb = iDb; initData.rc = SQLITE_OK; initData.pzErrMsg = pzErrMsg; + initData.mInitFlags = mFlags; sqlite3InitCallback(&initData, 3, (char **)azArg, 0); if( initData.rc ){ rc = initData.rc; @@ -373,14 +382,14 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){ assert( db->nDb>0 ); /* Do the main schema first */ if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){ - rc = sqlite3InitOne(db, 0, pzErrMsg); + rc = sqlite3InitOne(db, 0, pzErrMsg, 0); if( rc ) return rc; } /* 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); + rc = sqlite3InitOne(db, i, pzErrMsg, 0); if( rc ) return rc; } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7b01bb27f..e7d86ba3b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3329,9 +3329,15 @@ typedef struct { char **pzErrMsg; /* Error message stored here */ int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ int rc; /* Result code stored here */ + u32 mInitFlags; /* Flags controlling error messages */ } InitData; /* +** Allowed values for mInitFlags +*/ +#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */ + +/* ** Structure containing global configuration data for the SQLite library. ** ** This structure also contains some state information. @@ -3801,7 +3807,7 @@ void sqlite3ExprListDelete(sqlite3*, ExprList*); u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); -int sqlite3InitOne(sqlite3*, int, char**); +int sqlite3InitOne(sqlite3*, int, char**, u32); void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); #ifndef SQLITE_OMIT_VIRTUALTABLE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName); diff --git a/src/vdbe.c b/src/vdbe.c index 62abaa301..c8ee9860f 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5722,7 +5722,8 @@ case OP_SqlExec: { /* Opcode: ParseSchema P1 * * P4 * ** ** Read and parse all entries from the SQLITE_MASTER table of database P1 -** that match the WHERE clause P4. +** that match the WHERE clause P4. If P4 is a NULL pointer, then the +** entire schema for P1 is reparsed. ** ** This opcode invokes the parser to create a new virtual machine, ** then runs the new virtual machine. It is thus a re-entrant opcode. @@ -5751,11 +5752,11 @@ case OP_ParseSchema: { if( pOp->p4.z==0 ){ sqlite3SchemaClear(db->aDb[iDb].pSchema); db->mDbFlags &= ~DBFLAG_SchemaKnownOk; - rc = sqlite3InitOne(db, iDb, &p->zErrMsg); + rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable); db->mDbFlags |= DBFLAG_SchemaChange; }else #endif - /* Used to be a conditional */ { + { zMaster = MASTER_NAME; initData.db = db; initData.iDb = pOp->p1; |