diff options
author | drh <drh@noemail.net> | 2003-03-31 02:12:46 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2003-03-31 02:12:46 +0000 |
commit | da93d238c2067a1951b8043c3c30355947fd6da9 (patch) | |
tree | 29057f4a84763deb95565d3e8bd2622614c85c15 /src | |
parent | 1c2d84148a6bb2f8d231debd65bc09e948abf029 (diff) | |
download | sqlite-da93d238c2067a1951b8043c3c30355947fd6da9.tar.gz sqlite-da93d238c2067a1951b8043c3c30355947fd6da9.zip |
Add the sqliteErrorMsg() function and use it to generate error message
text during parsing and code generation. This simplifies the code
somewhat and makes it easier to handle names with a database prefix. (CVS 891)
FossilOrigin-Name: 1d3fc977211abdc7ba3fd51d661863e8ce5aef69
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 38 | ||||
-rw-r--r-- | src/delete.c | 16 | ||||
-rw-r--r-- | src/expr.c | 31 | ||||
-rw-r--r-- | src/insert.c | 33 | ||||
-rw-r--r-- | src/select.c | 85 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/trigger.c | 31 | ||||
-rw-r--r-- | src/update.c | 6 | ||||
-rw-r--r-- | src/util.c | 130 |
9 files changed, 213 insertions, 160 deletions
diff --git a/src/build.c b/src/build.c index 059c69be8..a14a72d2f 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.137 2003/03/31 00:30:48 drh Exp $ +** $Id: build.c,v 1.138 2003/03/31 02:12:47 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -1750,20 +1750,17 @@ void sqliteDropIndex(Parse *pParse, SrcList *pName){ assert( pName->nSrc==1 ); pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ - sqliteSetString(&pParse->zErrMsg, "no such index: ", pName->a[0].zName, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such index: %S", pName, 0); goto exit_drop_index; } if( pIndex->autoIndex ){ - sqliteSetString(&pParse->zErrMsg, "index associated with UNIQUE " + sqliteErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); - pParse->nErr++; goto exit_drop_index; } if( pIndex->iDb>1 ){ - sqliteSetString(&pParse->zErrMsg, "cannot alter schema of attached " + sqliteErrorMsg(pParse, "cannot alter schema of attached " "databases", 0); - pParse->nErr++; goto exit_drop_index; } #ifndef SQLITE_OMIT_AUTHORIZATION @@ -2108,9 +2105,7 @@ void sqliteBeginTransaction(Parse *pParse, int onError){ if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0) ) return; if( db->flags & SQLITE_InTrans ){ - pParse->nErr++; - sqliteSetString(&pParse->zErrMsg, "cannot start a transaction " - "within a transaction", 0); + sqliteErrorMsg(pParse, "cannot start a transaction within a transaction"); return; } sqliteBeginWriteOperation(pParse, 0, 0); @@ -2128,9 +2123,7 @@ void sqliteCommitTransaction(Parse *pParse){ if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ - pParse->nErr++; - sqliteSetString(&pParse->zErrMsg, - "cannot commit - no transaction is active", 0); + sqliteErrorMsg(pParse, "cannot commit - no transaction is active"); return; } db->flags &= ~SQLITE_InTrans; @@ -2149,9 +2142,7 @@ void sqliteRollbackTransaction(Parse *pParse){ if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ - pParse->nErr++; - sqliteSetString(&pParse->zErrMsg, - "cannot rollback - no transaction is active", 0); + sqliteErrorMsg(pParse, "cannot rollback - no transaction is active"); return; } v = sqliteGetVdbe(pParse); @@ -2701,10 +2692,7 @@ void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ sqliteDequote(zName); for(i=0; i<db->nDb; i++){ if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ - sqliteSetString(&pParse->zErrMsg, "database \"", zName, - "\" already in use", 0); - sqliteFree(zName); - pParse->nErr++; + sqliteErrorMsg(pParse, "database %z is already in use", zName); return; } } @@ -2715,8 +2703,7 @@ void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ sqliteDequote(zFile); rc = sqliteBtreeOpen(zFile, 0, MAX_PAGES, &aNew->pBt); if( rc ){ - sqliteSetString(&pParse->zErrMsg, "unable to open database: ", zFile, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "unable to open database: %s", zFile); } sqliteFree(zFile); db->flags &= ~SQLITE_Initialized; @@ -2746,14 +2733,11 @@ void sqliteDetach(Parse *pParse, Token *pDbname){ if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break; } if( i>=db->nDb ){ - sqliteSetNString(&pParse->zErrMsg, "no such database: ", -1, - pDbname->z, pDbname->n, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such database: %T", pDbname); return; } if( i<2 ){ - sqliteSetString(&pParse->zErrMsg, "cannot detached \"main\" or \"temp\"",0); - pParse->nErr++; + sqliteErrorMsg(pParse, "cannot detached database %T", pDbname); return; } sqliteBtreeClose(db->aDb[i].pBt); diff --git a/src/delete.c b/src/delete.c index 7fc2ddf91..fecb8cc12 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.49 2003/03/27 13:50:00 drh Exp $ +** $Id: delete.c,v 1.50 2003/03/31 02:12:47 drh Exp $ */ #include "sqliteInt.h" @@ -29,12 +29,7 @@ Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){ const char *zDb = pSrc->a[i].zDatabase; pTab = sqliteFindTable(pParse->db, zTab, zDb); if( pTab==0 ){ - if( zDb==0 || zDb[0]==0 ){ - sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0); - }else{ - sqliteSetString(&pParse->zErrMsg, "no such table: ", zDb, ".", zTab, 0); - } - pParse->nErr++; + sqliteErrorMsg(pParse, "no such table: %S", pSrc, 0); break; } pSrc->a[i].pTab = pTab; @@ -49,10 +44,9 @@ Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){ */ int sqliteIsReadOnly(Parse *pParse, Table *pTab){ if( pTab->readOnly || pTab->pSelect ){ - sqliteSetString(&pParse->zErrMsg, - pTab->pSelect ? "view " : "table ", pTab->zName, - " may not be modified", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "%s %s may not be modified", + pTab->pSelect ? "view" : "table", + pTab->zName); return 1; } return 0; diff --git a/src/expr.c b/src/expr.c index 576ae2db8..caa6de11a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.90 2003/03/27 12:51:25 drh Exp $ +** $Id: expr.c,v 1.91 2003/03/31 02:12:47 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -477,14 +477,10 @@ int sqliteExprResolveIds( } sqliteFree(z); if( cnt==0 && pExpr->token.z[0]!='"' ){ - sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1, - pExpr->token.z, pExpr->token.n, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such column: %T", &pExpr->token); return 1; }else if( cnt>1 ){ - sqliteSetNString(&pParse->zErrMsg, "ambiguous column name: ", -1, - pExpr->token.z, pExpr->token.n, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "ambiguous column name: %T", &pExpr->token); return 1; } if( pExpr->op==TK_COLUMN ){ @@ -600,16 +596,12 @@ int sqliteExprResolveIds( sqliteFree(zLeft); sqliteFree(zRight); if( cnt==0 ){ - sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1, - pLeft->token.z, pLeft->token.n, ".", 1, - pRight->token.z, pRight->token.n, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such column: %T.%T", + &pLeft->token, &pRight->token); return 1; }else if( cnt>1 ){ - sqliteSetNString(&pParse->zErrMsg, "ambiguous column name: ", -1, - pLeft->token.z, pLeft->token.n, ".", 1, - pRight->token.z, pRight->token.n, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "ambiguous column name: %T.%T", + &pLeft->token, &pRight->token); return 1; } sqliteExprDelete(pExpr->pLeft); @@ -647,9 +639,8 @@ int sqliteExprResolveIds( for(i=0; i<pExpr->pList->nExpr; i++){ Expr *pE2 = pExpr->pList->a[i].pExpr; if( !sqliteExprIsConstant(pE2) ){ - sqliteSetString(&pParse->zErrMsg, - "right-hand side of IN operator must be constant", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "right-hand side of IN operator must be constant"); return 1; } if( sqliteExprCheck(pParse, pE2, 0, 0) ){ @@ -1219,8 +1210,8 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){ } case TK_RAISE: { if( !pParse->trigStack ){ - sqliteSetNString(&pParse->zErrMsg, - "RAISE() may only be used within a trigger-program", -1, 0); + sqliteErrorMsg(pParse, + "RAISE() may only be used within a trigger-program"); pParse->nErr++; return; } diff --git a/src/insert.c b/src/insert.c index f9f72f8c4..705bd8e9d 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.76 2003/03/27 13:50:00 drh Exp $ +** $Id: insert.c,v 1.77 2003/03/31 02:12:47 drh Exp $ */ #include "sqliteInt.h" @@ -137,11 +137,9 @@ void sqliteInsert( TK_BEFORE, TK_ROW, 0) || sqliteTriggersExist(pParse, pTab->pTrigger, TK_INSERT, TK_AFTER, TK_ROW, 0); if( pTab->readOnly || (pTab->pSelect && !row_triggers_exist) ){ - sqliteSetString(&pParse->zErrMsg, - pTab->pSelect ? "view " : "table ", - zTab, - " may not be modified", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "%s %s may not be modified", + pTab->pSelect ? "view" : "table", + zTab); goto insert_cleanup; } @@ -245,24 +243,13 @@ void sqliteInsert( ** of columns to be inserted into the table. */ if( pColumn==0 && nColumn!=pTab->nCol ){ - char zNum1[30]; - char zNum2[30]; - sprintf(zNum1,"%d", nColumn); - sprintf(zNum2,"%d", pTab->nCol); - sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, - " has ", zNum2, " columns but ", - zNum1, " values were supplied", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "table %S has %d columns but %d values were supplied", + pTabList, 0, pTab->nCol, nColumn); goto insert_cleanup; } if( pColumn!=0 && nColumn!=pColumn->nId ){ - char zNum1[30]; - char zNum2[30]; - sprintf(zNum1,"%d", nColumn); - sprintf(zNum2,"%d", pColumn->nId); - sqliteSetString(&pParse->zErrMsg, zNum1, " values for ", - zNum2, " columns", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); goto insert_cleanup; } @@ -292,8 +279,8 @@ void sqliteInsert( } } if( j>=pTab->nCol ){ - sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, - " has no column named ", pColumn->a[i].zName, 0); + sqliteErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); pParse->nErr++; goto insert_cleanup; } diff --git a/src/select.c b/src/select.c index 48283550f..e1704d2bf 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.128 2003/03/27 12:51:25 drh Exp $ +** $Id: select.c,v 1.129 2003/03/31 02:12:47 drh Exp $ */ #include "sqliteInt.h" @@ -120,9 +120,8 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ pParse->nErr++; jointype = JT_INNER; }else if( jointype & JT_RIGHT ){ - sqliteSetString(&pParse->zErrMsg, - "RIGHT and FULL OUTER JOINs are not currently supported", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "RIGHT and FULL OUTER JOINs are not currently supported"); jointype = JT_INNER; } return jointype; @@ -218,9 +217,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ if( pTerm->jointype & JT_NATURAL ){ Table *pTab; if( pTerm->pOn || pTerm->pUsing ){ - sqliteSetString(&pParse->zErrMsg, "a NATURAL join may not have " + sqliteErrorMsg(pParse, "a NATURAL join may not have " "an ON or USING clause", 0); - pParse->nErr++; return 1; } pTab = pTerm->pTab; @@ -234,9 +232,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ /* Disallow both ON and USING clauses in the same join */ if( pTerm->pOn && pTerm->pUsing ){ - sqliteSetString(&pParse->zErrMsg, "cannot have both ON and USING " - "clauses in the same join", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); return 1; } @@ -268,9 +265,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ for(j=0; j<pList->nId; j++){ if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 || columnIndex(pOther->pTab, pList->a[j].zName)<0 ){ - sqliteSetString(&pParse->zErrMsg, "cannot join using column ", - pList->a[j].zName, " - column not present in both tables", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "cannot join using column %s - column " + "not present in both tables", pList->a[j].zName); return 1; } addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere); @@ -915,9 +911,7 @@ static int fillInColumnList(Parse *pParse, Select *p){ sqliteFindTable(pParse->db, pTabList->a[i].zName, pTabList->a[i].zDatabase); if( pTab==0 ){ - sqliteSetString(&pParse->zErrMsg, "no such table: ", - pTabList->a[i].zName, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such table: %S", pTabList, i); return 1; } if( pTab->pSelect ){ @@ -1033,10 +1027,9 @@ static int fillInColumnList(Parse *pParse, Select *p){ } if( !tableSeen ){ if( pName ){ - sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1, - pName->z, pName->n, 0); + sqliteErrorMsg(pParse, "no such table: %T", pName); }else{ - sqliteSetString(&pParse->zErrMsg, "no tables specified", 0); + sqliteErrorMsg(pParse, "no tables specified"); } rc = 1; } @@ -1130,11 +1123,9 @@ static int matchOrderbyToColumn( if( pOrderBy->a[i].done ) continue; if( sqliteExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ - char zBuf[200]; - sprintf(zBuf,"ORDER BY position %d should be between 1 and %d", - iCol, pEList->nExpr); - sqliteSetString(&pParse->zErrMsg, zBuf, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "ORDER BY position %d should be between 1 and %d", + iCol, pEList->nExpr); nErr++; break; } @@ -1164,11 +1155,8 @@ static int matchOrderbyToColumn( pOrderBy->a[i].done = 1; } if( iCol<0 && mustComplete ){ - char zBuf[30]; - sprintf(zBuf,"%d",i+1); - sqliteSetString(&pParse->zErrMsg, "ORDER BY term number ", zBuf, - " does not match any result column", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "ORDER BY term number %d does not match any result column", i+1); nErr++; break; } @@ -1278,9 +1266,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ if( p==0 || p->pPrior==0 ) return 1; pPrior = p->pPrior; if( pPrior->pOrderBy ){ - sqliteSetString(&pParse->zErrMsg,"ORDER BY clause should come after ", - selectOpName(p->op), " not before", 0); - pParse->nErr++; + sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before", + selectOpName(p->op)); return 1; } @@ -1451,9 +1438,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){ } assert( p->pEList && pPrior->pEList ); if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ - sqliteSetString(&pParse->zErrMsg, "SELECTs to the left and right of ", - selectOpName(p->op), " do not have the same number of result columns", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); return 1; } @@ -1978,9 +1964,8 @@ int sqliteSelect( ** only a single column may be output. */ if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ - sqliteSetString(&pParse->zErrMsg, "only a single result allowed for " - "a SELECT that is part of an expression", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "only a single result allowed for " + "a SELECT that is part of an expression"); goto select_end; } @@ -2020,9 +2005,7 @@ int sqliteSelect( } if( pHaving ){ if( pGroupBy==0 ){ - sqliteSetString(&pParse->zErrMsg, "a GROUP BY clause is required " - "before HAVING", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); goto select_end; } if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pHaving) ){ @@ -2048,16 +2031,13 @@ int sqliteSelect( } if( sqliteExprIsConstant(pE) ){ if( sqliteExprIsInteger(pE, &iCol)==0 ){ - sqliteSetString(&pParse->zErrMsg, - "ORDER BY terms must not be non-integer constants", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "ORDER BY terms must not be non-integer constants"); goto select_end; }else if( iCol<=0 || iCol>pEList->nExpr ){ - char zBuf[2000]; - sprintf(zBuf,"ORDER BY column number %d out of range - should be " + sqliteErrorMsg(pParse, + "ORDER BY column number %d out of range - should be " "between 1 and %d", iCol, pEList->nExpr); - sqliteSetString(&pParse->zErrMsg, zBuf, 0); - pParse->nErr++; goto select_end; } } @@ -2079,16 +2059,13 @@ int sqliteSelect( } if( sqliteExprIsConstant(pE) ){ if( sqliteExprIsInteger(pE, &iCol)==0 ){ - sqliteSetString(&pParse->zErrMsg, - "GROUP BY terms must not be non-integer constants", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, + "GROUP BY terms must not be non-integer constants"); goto select_end; }else if( iCol<=0 || iCol>pEList->nExpr ){ - char zBuf[2000]; - sprintf(zBuf,"GROUP BY column number %d out of range - should be " + sqliteErrorMsg(pParse, + "GROUP BY column number %d out of range - should be " "between 1 and %d", iCol, pEList->nExpr); - sqliteSetString(&pParse->zErrMsg, zBuf, 0); - pParse->nErr++; goto select_end; } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bffef93a4..f4e6999dc 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.167 2003/03/31 00:30:49 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.168 2003/03/31 02:12:48 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -961,6 +961,7 @@ void sqliteRealToSortable(double r, char *); char *sqliteMPrintf(const char *,...); void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); +void sqliteErrorMsg(Parse*, const char*, ...); void sqliteDequote(char*); int sqliteKeywordCode(const char*, int); int sqliteRunParser(Parse*, const char*, char **); diff --git a/src/trigger.c b/src/trigger.c index 7e48e4d57..ec95daae6 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -66,33 +66,29 @@ void sqliteCreateTrigger( goto trigger_cleanup; } if( tab->iDb>=2 ){ - sqliteSetString(&pParse->zErrMsg, "triggers may not be added to " - "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "triggers may not be added to auxiliary " + "database %s", db->aDb[tab->iDb].zName); goto trigger_cleanup; } zName = sqliteStrNDup(pName->z, pName->n); if( sqliteHashFind(&(db->aDb[tab->iDb].trigHash), zName,pName->n+1) ){ - sqliteSetNString(&pParse->zErrMsg, "trigger ", -1, - pName->z, pName->n, " already exists", -1, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "trigger %T already exists", pName); goto trigger_cleanup; } if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){ - sqliteSetString(&pParse->zErrMsg,"cannot create trigger on system table",0); + sqliteErrorMsg(pParse, "cannot create trigger on system table"); pParse->nErr++; goto trigger_cleanup; } if( tab->pSelect && tr_tm != TK_INSTEAD ){ - sqliteSetString(&pParse->zErrMsg, "cannot create ", - (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", " trigger on view: ", - pTableName->a[0].zName, 0); + sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S", + (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0); goto trigger_cleanup; } if( !tab->pSelect && tr_tm == TK_INSTEAD ){ - sqliteSetString(&pParse->zErrMsg, "cannot create INSTEAD OF", - " trigger on table: ", pTableName->a[0].zName, 0); + sqliteErrorMsg(pParse, "cannot create INSTEAD OF" + " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION @@ -362,14 +358,13 @@ void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){ if( pTrigger ) break; } if( !pTrigger ){ - sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0); + sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0); goto drop_trigger_cleanup; } assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb ); if( pTrigger->iDb>=2 ){ - sqliteSetString(&pParse->zErrMsg, "triggers may not be removed from " - "auxiliary database \"", db->aDb[pTrigger->iDb].zName, "\"", 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "triggers may not be removed from " + "auxiliary database %s", db->aDb[pTrigger->iDb].zName); goto drop_trigger_cleanup; } pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName); @@ -764,9 +759,7 @@ void sqliteViewTriggers( } } if( jj>=pTab->nCol ){ - sqliteSetString(&pParse->zErrMsg, "no such column: ", - pChanges->a[ii].zName, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[ii].zName); goto trigger_cleanup; } } diff --git a/src/update.c b/src/update.c index fb0603061..58ff54b48 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.57 2003/03/27 13:50:00 drh Exp $ +** $Id: update.c,v 1.58 2003/03/31 02:12:48 drh Exp $ */ #include "sqliteInt.h" @@ -140,9 +140,7 @@ void sqliteUpdate( } } if( j>=pTab->nCol ){ - sqliteSetString(&pParse->zErrMsg, "no such column: ", - pChanges->a[i].zName, 0); - pParse->nErr++; + sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName); goto update_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION diff --git a/src/util.c b/src/util.c index 8231e9818..87e5f4431 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.58 2003/02/16 22:21:32 drh Exp $ +** $Id: util.c,v 1.59 2003/03/31 02:12:48 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -393,6 +393,134 @@ void sqliteSetNString(char **pz, ...){ } /* +** Add an error message to pParse->zErrMsg and increment pParse->nErr. +** The following formatting characters are allowed: +** +** %s Insert a string +** %z A string that should be freed after use +** %d Insert an integer +** %T Insert a token +** %S Insert the first element of a SrcList +*/ +void sqliteErrorMsg(Parse *pParse, const char *zFormat, ...){ + va_list ap; + int nByte; + int i, j; + char *z; + static char zNull[] = "NULL"; + + pParse->nErr++; + nByte = 1 + strlen(zFormat); + va_start(ap, zFormat); + for(i=0; zFormat[i]; i++){ + if( zFormat[i]!='%' && zFormat[i+1] ) continue; + i++; + switch( zFormat[i] ){ + case 'd': { + (void)va_arg(ap, int); + nByte += 20; + break; + } + case 'z': + case 's': { + char *z2 = va_arg(ap, char*); + if( z2==0 ) z2 = zNull; + nByte += strlen(z2); + break; + } + case 'T': { + Token *p = va_arg(ap, Token*); + nByte += p->n; + break; + } + case 'S': { + SrcList *p = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + assert( p->nSrc>k && k>=0 ); + nByte += strlen(p->a[k].zName); + if( p->a[k].zDatabase && p->a[k].zDatabase[0] ){ + nByte += strlen(p->a[k].zDatabase)+1; + } + break; + } + default: { + nByte++; + break; + } + } + } + va_end(ap); + z = sqliteMalloc( nByte ); + if( z==0 ) return; + sqliteFree(pParse->zErrMsg); + pParse->zErrMsg = z; + va_start(ap, zFormat); + for(i=j=0; zFormat[i]; i++){ + if( zFormat[i]!='%' ) continue; + if( i>j ){ + memcpy(z, &zFormat[j], i-j); + z += i-j; + } + j = i+2; + i++; + switch( zFormat[i] ){ + case 'd': { + int x = va_arg(ap, int); + sprintf(z, "%d", x); + z += strlen(z); + break; + } + case 'z': + case 's': { + int len; + char *z2 = va_arg(ap, char*); + if( z2==0 ) z2 = zNull; + len = strlen(z2); + memcpy(z, z2, len); + z += len; + if( zFormat[i]=='z' && z2!=zNull ){ + sqliteFree(z2); + } + break; + } + case 'T': { + Token *p = va_arg(ap, Token*); + memcpy(z, p->z, p->n); + z += p->n; + break; + } + case 'S': { + int len; + SrcList *p = va_arg(ap, SrcList*); + int k = va_arg(ap, int); + assert( p->nSrc>k && k>=0 ); + if( p->a[k].zDatabase && p->a[k].zDatabase[0] ){ + len = strlen(p->a[k].zDatabase); + memcpy(z, p->a[k].zDatabase, len); + z += len; + *(z++) = '.'; + } + len = strlen(p->a[k].zName); + memcpy(z, p->a[k].zName, len); + z += len; + break; + } + default: { + *(z++) = zFormat[i]; + break; + } + } + } + va_end(ap); + if( i>j ){ + memcpy(z, &zFormat[j], i-j); + z += i-j; + } + assert( (z - pParse->zErrMsg) < nByte ); + *z = 0; +} + +/* ** Convert an SQL-style quoted string into a normal string by removing ** the quote characters. The conversion is done in-place. If the ** input does not begin with a quote character, then this routine |