From: drh Date: Mon, 31 Mar 2003 02:12:46 +0000 (+0000) Subject: Add the sqliteErrorMsg() function and use it to generate error message X-Git-Tag: version-3.6.10~5177 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da93d238c2067a1951b8043c3c30355947fd6da9;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 2e38bb3ef8..029455550b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sATTACH\sand\sDETACH\sstatements\sare\snow\scoded\sbut\sare\sstill\smostly\suntested.\s(CVS\s890) -D 2003-03-31T00:30:48 +C Add\sthe\ssqliteErrorMsg()\sfunction\sand\suse\sit\sto\sgenerate\serror\smessage\ntext\sduring\sparsing\sand\scode\sgeneration.\s\sThis\ssimplifies\sthe\scode\nsomewhat\sand\smakes\sit\seasier\sto\shandle\snames\swith\sa\sdatabase\sprefix.\s(CVS\s891) +D 2003-03-31T02:12:47 F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -22,14 +22,14 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/auth.c f37bfc9451b8c1fa52f34adff474560018892729 F src/btree.c dba4d12945228dd7e94de7da0e1d8638b70d99f2 F src/btree.h 8209bfadf5845d4fdaa60f471bb360f894cd4095 -F src/build.c e56df7b1ccf923e75707953181c91380134253be -F src/delete.c 923497248e0ff9097a595c6333ec6d67fe6650b5 +F src/build.c 5ea24a62f447f3beabe6fb6218ec24f4dd6aff95 +F src/delete.c 58d698779a6b7f819718ecd45b310a9de8537088 F src/encode.c faf03741efe921755ec371cf4a6984536de00042 -F src/expr.c eae205a27ec45232f234f281f8827c3be58b303d +F src/expr.c b8daee83f837b24a22d889200bdd74973ca2d8db F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605 F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 -F src/insert.c 95e7ab3fb51909351273a6c6f8aa831201130ce7 +F src/insert.c dad4d914dc729a94e48de171802c23587a62c34f F src/main.c 6d9a38491fdc40c041df64a7399244c364481a09 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565 F src/os.c dfed46091f69cd2d1e601f8a214d41344f2b00b6 @@ -39,11 +39,11 @@ F src/pager.h 97d9a8cc5103750efd8037d71ebfb41849ef2f2f F src/parse.y 3be47fa18323aa2e3364fc42bf7a6ba5b3cc0a81 F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c afdc06d4606d14ab5793ef480206def6b02a2f19 +F src/select.c 7d69e569339e7ce9e672eb41d50a454110ea8a05 F src/shell.c c13ff46e905a59eb1c7dbea7c1850f8f115e6395 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in be3e56214fecc73d72195ca62d8a3d6663602ff4 -F src/sqliteInt.h b86c03c496bdc9ff543a12a1d88766fbcf28cd0c +F src/sqliteInt.h 1ce5af48f980d63ec6fbb41d3f8517b4eaf446ce F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c 4cb0ffa863123ae037db359849a231ff5cebfed4 F src/test1.c 7ad4e6308dde0bf5a0f0775ce20cb2ec37a328f8 @@ -51,9 +51,9 @@ F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700 F src/test3.c c12ea7f1c3fbbd58904e81e6cb10ad424e6fc728 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e F src/tokenize.c 675b4718d17c69fe7609dc8e85e426ef002be811 -F src/trigger.c b07dc1ff60f2b18a701a85b83577a967e193dee2 -F src/update.c ab8c48ce00747ccf8f449f7f51ae56e08b5428ba -F src/util.c 73b668d1ed468df650dc00685a5e4ffa6887feb4 +F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3 +F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a +F src/util.c 96178ddf8a01fe81f66620f555a53bcff54bd3d7 F src/vdbe.c 7171dbe873760f403b2501e96fd3d1bd852b3ce8 F src/vdbe.h ed43771f1dc2b994d5c484fdf2eab357c6ef0ee3 F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127 @@ -155,7 +155,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 0a358844e40020557c1aeea5779b194670350930 -R b07af9b76a439a5b405050fd15558aa2 +P c7c5e927a54f0fbc2ca625754787aff4d9c4eff1 +R 049a3c05f7f7ec86278cb228c093cf6f U drh -Z 8c6d8642908a4e47e8f8d0600ce4a4a6 +Z 310a08d8c23f76a9c9a4ece27530433b diff --git a/manifest.uuid b/manifest.uuid index b6b9aa9aec..b6ecefe2e8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c7c5e927a54f0fbc2ca625754787aff4d9c4eff1 \ No newline at end of file +1d3fc977211abdc7ba3fd51d661863e8ce5aef69 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 059c69be85..a14a72d2f1 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 @@ -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; inDb; 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 7fc2ddf911..fecb8cc12d 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 576ae2db81..caa6de11a8 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 @@ -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; ipList->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 f9f72f8c40..705bd8e9d2 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 48283550f3..e1704d2bfc 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; jnId; 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 bffef93a49..f4e6999dc9 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 7e48e4d575..ec95daae66 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->iDbnDb ); 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 fb06030612..58ff54b480 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 8231e98188..87e5f4431c 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 @@ -392,6 +392,134 @@ void sqliteSetNString(char **pz, ...){ va_end(ap); } +/* +** 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