aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-08-14 19:27:51 +0000
committerdrh <drh@noemail.net>2018-08-14 19:27:51 +0000
commit1595abcda65adeaf8bddaba36d133b414ff86cdf (patch)
tree0c12a356aed186e9633d5d38bc846222ec27b4a3 /src
parent5550b5eee7d51370ff326b1e741f6c0a3c737666 (diff)
downloadsqlite-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.c1
-rw-r--r--src/prepare.c21
-rw-r--r--src/sqliteInt.h8
-rw-r--r--src/vdbe.c7
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;