]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further improvements to localization of errors in input SQL.
authordrh <>
Sun, 6 Feb 2022 00:30:04 +0000 (00:30 +0000)
committerdrh <>
Sun, 6 Feb 2022 00:30:04 +0000 (00:30 +0000)
FossilOrigin-Name: fa34676042720161ca03f3926814152eb1d144ec12fd2b44e5429408ea4ad5b0

manifest
manifest.uuid
src/expr.c
src/printf.c
src/resolve.c
test/altertab2.test

index 20ba549bd0afb789a8784cffdbadb730f0789433..b6e55db69d0cf97ef53edc54f50d8e49fa668cfb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\ssqlite3_error_offset()\sto\sreport\sthe\sposition\sof\sunresolved\nidentifiers.
-D 2022-02-05T23:11:19.818
+C Further\simprovements\sto\slocalization\sof\serrors\sin\sinput\sSQL.
+D 2022-02-06T00:30:04.400
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -503,7 +503,7 @@ F src/date.c 41627dec396f3d33e2c317a065f9d59bb535982b2ea3a561c96e4d4cf1137b65
 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
 F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
 F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d
-F src/expr.c 31d23e6b57827b4cb8f0054f44e2ed86feb1dfcaa9b0c4d6c960b42536a17ca0
+F src/expr.c ddb6a18fcb231bd246c5570bc32b888ecfcccf4a145b141f63285b198205e84a
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c
 F src/func.c 5a0379450bd19ca5cb2d65327b0df6466a14fa0f06f9355329c3e0eec483519a
@@ -548,9 +548,9 @@ F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
 F src/pragma.c 7c024d690a3dc93f61830f11f900e4af2357f31d081b0c79099ca5e28919cba7
 F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
 F src/prepare.c a187dade741c1f09ae118fcbbf0302511807bfc0355880927d7152eb75b8260d
-F src/printf.c ceadf2ee3ad2f4bb22d4557611b514f51be3ac0ce2b6ebd1d17aed26ce023dc9
+F src/printf.c 88a96f8d7bedee6fa73f6be21a70c21089e772d88d32994b04d50e0bf0f38066
 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
-F src/resolve.c 868a88d47b11f4f6b8b413db72c9290c211972ee91316c1ece318846600ff725
+F src/resolve.c ea935b87d6fb36c78b70cdc7b28561dc8f33f2ef37048389549c7b5ef9b0ba5e
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
 F src/select.c 3baa9dd8cf240654773c7974e2bcce398ac9dd24419c36684156963defe43b35
 F src/shell.c.in 2f58e6aa6b3d2012db32f1c5fa4591e9d12fd582904632b4fc8f57a382b98fd3
@@ -668,7 +668,7 @@ F test/altermalloc2.test ca3ebc01670d9313953a2b7628d8cc00dc5ea9988f229b3cbbbe1cc
 F test/altermalloc3.test 4660ac6240a8c82ba3947b927612dcc7c05a8eec3fe3c9f38e047ca69a789a33
 F test/alterqf.test 3008318ba9e16b4ac0b5f83cf7683caa4b0a3154aafe3b4099838a250d4ba74a
 F test/altertab.test 7273b8506eab46342be016af78028df49f3bd99037412f997a8f1011b37a6912
-F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
+F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
 F test/altertab3.test 5929f522fd6fd708396ad9f317d4af9ff1a93e460df85bb1d54d4499eeb94960
 F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
 F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
@@ -1943,8 +1943,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 32a3a53b62ab09ac2212905e7f42fe6f1b09d891e015203e5caf4cb16262f18e
-R d206266e8d498e68ec7df6cacd558558
+P 5b8d2577907abda10de29884716bacc10bff0df1451228a0ac40342dbea6d589
+R 62d673014722dadc6f145e57ea78193f
 U drh
-Z 7fce1180d98a65f136fd63cea97bcf69
+Z 3fc4758d5d812a2bf659475da12b12d5
 # Remove this line to create a well-formed Fossil manifest.
index 37dc90b4d698375c9388a25f5c7c2f328b51a273..2dd503b2841ebea4eed0c40720f6c2cdfa9332c8 100644 (file)
@@ -1 +1 @@
-5b8d2577907abda10de29884716bacc10bff0df1451228a0ac40342dbea6d589
\ No newline at end of file
+fa34676042720161ca03f3926814152eb1d144ec12fd2b44e5429408ea4ad5b0
\ No newline at end of file
index af28fd6d29859fb25dd977d5357e4004f680f232..4c47f6fe6c84594b4cf1aea862f13b602b9ed277 100644 (file)
@@ -1070,6 +1070,7 @@ Expr *sqlite3ExprFunction(
     sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
     return 0;
   }
+  pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
   if( pList 
    && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
    && !pParse->nested
@@ -1113,7 +1114,7 @@ void sqlite3ExprFunctionUsable(
       **         SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
       **         that the schema is possibly tainted).
       */
-      sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
+      sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr);
     }
   }
 }
@@ -1169,6 +1170,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
       if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
         sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
             db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
+        sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
         return;
       }
       x = (ynVar)i;
@@ -1196,6 +1198,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
   pExpr->iColumn = x;
   if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
     sqlite3ErrorMsg(pParse, "too many SQL variables");
+    sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
   }
 }
 
@@ -3637,11 +3640,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
     c = sqlite3DecOrHexToI64(z, &value);
     if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
 #ifdef SQLITE_OMIT_FLOATING_POINT
-      sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
+      sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr);
 #else
 #ifndef SQLITE_OMIT_HEX_INTEGER
       if( sqlite3_strnicmp(z,"0x",2)==0 ){
-        sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
+        sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T",
+                        negFlag?"-":"",pExpr);
       }else
 #endif
       {
@@ -4317,7 +4321,7 @@ expr_code_doover:
        || NEVER(pExpr->iAgg>=pInfo->nFunc)
       ){
         assert( !ExprHasProperty(pExpr, EP_IntValue) );
-        sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
+        sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr);
       }else{
         return pInfo->aFunc[pExpr->iAgg].iMem;
       }
@@ -4358,7 +4362,7 @@ expr_code_doover:
       }
 #endif
       if( pDef==0 || pDef->xFinalize!=0 ){
-        sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
+        sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
         break;
       }
       if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
index a8cfc193158ec45913ab7f2128878f71fe23e9ff..ef9f3f2b5b548bd27659b0d9b29f4d6d40c48eec 100644 (file)
@@ -849,13 +849,22 @@ void sqlite3_str_vappendf(
         goto adjust_width_for_utf8;
       }
       case etTOKEN: {
-        Token *pToken;
         if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
-        pToken = va_arg(ap, Token*);
-        assert( bArgList==0 );
-        if( pToken && pToken->n ){
-          sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
-          sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
+        if( flag_alternateform ){
+          /* %#T means an Expr pointer that uses Expr.u.zToken */
+          Expr *pExpr = va_arg(ap,Expr*);
+          if( pExpr && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
+            sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
+            sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
+          }
+        }else{
+          /* %T means a Token pointer */
+          Token *pToken = va_arg(ap, Token*);
+          assert( bArgList==0 );
+          if( pToken && pToken->n ){
+            sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
+            sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
+          }
         }
         length = width = 0;
         break;
index 8250ce9efd06883fa3a42e73657134136eb12aaf..480694f6f5756dba81212f64f2a0fd260a9a5ef8 100644 (file)
@@ -729,7 +729,8 @@ static void notValidImpl(
    Parse *pParse,       /* Leave error message here */
    NameContext *pNC,    /* The name context */
    const char *zMsg,    /* Type of error */
-   Expr *pExpr          /* Invalidate this expression on error */
+   Expr *pExpr,         /* Invalidate this expression on error */
+   Expr *pError         /* Associate error with this expression */
 ){
   const char *zIn = "partial index WHERE clauses";
   if( pNC->ncFlags & NC_IdxExpr )      zIn = "index expressions";
@@ -741,10 +742,11 @@ static void notValidImpl(
 #endif
   sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
   if( pExpr ) pExpr->op = TK_NULL;
+  sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
 }
-#define sqlite3ResolveNotValid(P,N,M,X,E) \
+#define sqlite3ResolveNotValid(P,N,M,X,E,R) \
   assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
-  if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E);
+  if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R);
 
 /*
 ** Expression p should encode a floating point value between 1.0 and 0.0.
@@ -879,7 +881,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         testcase( pNC->ncFlags & NC_IdxExpr );
         testcase( pNC->ncFlags & NC_GenCol );
         sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
-                               NC_IdxExpr|NC_GenCol, 0);
+                               NC_IdxExpr|NC_GenCol, 0, pExpr);
         pRight = pExpr->pRight;
         if( pRight->op==TK_ID ){
           zDb = 0;
@@ -910,7 +912,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       int no_such_func = 0;       /* True if no such function exists */
       int wrong_num_args = 0;     /* True if wrong number of arguments */
       int is_agg = 0;             /* True if is an aggregate function */
-      int nId;                    /* Number of characters in function name */
       const char *zId;            /* The function name. */
       FuncDef *pDef;              /* Information about the function */
       u8 enc = ENC(pParse->db);   /* The database encoding */
@@ -920,7 +921,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
 #endif
       assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
       zId = pExpr->u.zToken;
-      nId = sqlite3Strlen30(zId);
       pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
       if( pDef==0 ){
         pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -937,8 +937,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
             pExpr->iTable = exprProbability(pList->a[1].pExpr);
             if( pExpr->iTable<0 ){
               sqlite3ErrorMsg(pParse,
-                "second argument to likelihood() must be a "
-                "constant between 0.0 and 1.0");
+                "second argument to %#T() must be a "
+                "constant between 0.0 and 1.0", pExpr);
               pNC->nNcErr++;
             }
           }else{
@@ -959,8 +959,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
           if( auth!=SQLITE_OK ){
             if( auth==SQLITE_DENY ){
-              sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
-                                      pDef->zName);
+              sqlite3ErrorMsg(pParse, "not authorized to use function: %#T",
+                                      pExpr);
               pNC->nNcErr++;
             }
             pExpr->op = TK_NULL;
@@ -983,7 +983,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           ** in a CHECK constraint.  SQLServer, MySQL, and PostgreSQL all
           ** all this. */
           sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
-                                 NC_IdxExpr|NC_PartIdx|NC_GenCol, 0);
+                                 NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
         }else{
           assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
           pExpr->op2 = pNC->ncFlags & NC_SelfRef;
@@ -1015,7 +1015,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         );
         if( pDef && pDef->xValue==0 && pWin ){
           sqlite3ErrorMsg(pParse, 
-              "%.*s() may not be used as a window function", nId, zId
+              "%#T() may not be used as a window function", pExpr
           );
           pNC->nNcErr++;
         }else if( 
@@ -1029,13 +1029,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
           }else{
             zType = "aggregate";
           }
-          sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
+          sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr);
           pNC->nNcErr++;
           is_agg = 0;
         }
 #else
         if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
-          sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
+          sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr);
           pNC->nNcErr++;
           is_agg = 0;
         }
@@ -1045,18 +1045,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
                   && pParse->explain==0
 #endif
         ){
-          sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+          sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
           pNC->nNcErr++;
         }else if( wrong_num_args ){
-          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
-               nId, zId);
+          sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()",
+               pExpr);
           pNC->nNcErr++;
         }
 #ifndef SQLITE_OMIT_WINDOWFUNC
         else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
           sqlite3ErrorMsg(pParse, 
-              "FILTER may not be used with non-aggregate %.*s()", 
-              nId, zId
+              "FILTER may not be used with non-aggregate %#T()",
+              pExpr
           );
           pNC->nNcErr++;
         }
@@ -1141,7 +1141,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         testcase( pNC->ncFlags & NC_IdxExpr );
         testcase( pNC->ncFlags & NC_GenCol );
         if( pNC->ncFlags & NC_SelfRef ){
-          notValidImpl(pParse, pNC, "subqueries", pExpr);
+          notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
         }else{
           sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
         }
@@ -1159,7 +1159,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
       testcase( pNC->ncFlags & NC_IdxExpr );
       testcase( pNC->ncFlags & NC_GenCol );
       sqlite3ResolveNotValid(pParse, pNC, "parameters",
-               NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
+               NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr);
       break;
     }
     case TK_IS:
@@ -1211,6 +1211,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         testcase( pExpr->op==TK_ISNOT );
         testcase( pExpr->op==TK_BETWEEN );
         sqlite3ErrorMsg(pParse, "row value misused");
+        sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
       }
       break; 
     }
@@ -1324,11 +1325,13 @@ static void resolveOutOfRangeError(
   Parse *pParse,         /* The error context into which to write the error */
   const char *zType,     /* "ORDER" or "GROUP" */
   int i,                 /* The index (1-based) of the term out of range */
-  int mx                 /* Largest permissible value of i */
+  int mx,                /* Largest permissible value of i */
+  Expr *pError           /* Associate the error with the expression */
 ){
   sqlite3ErrorMsg(pParse, 
     "%r %s BY term out of range - should be "
     "between 1 and %d", i, zType, mx);
+  sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
 }
 
 /*
@@ -1384,7 +1387,7 @@ static int resolveCompoundOrderBy(
       if( NEVER(pE==0) ) continue;
       if( sqlite3ExprIsInteger(pE, &iCol) ){
         if( iCol<=0 || iCol>pEList->nExpr ){
-          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
           return 1;
         }
       }else{
@@ -1480,7 +1483,7 @@ int sqlite3ResolveOrderGroupBy(
   for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
     if( pItem->u.x.iOrderByCol ){
       if( pItem->u.x.iOrderByCol>pEList->nExpr ){
-        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0);
         return 1;
       }
       resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
@@ -1572,7 +1575,7 @@ static int resolveOrderGroupBy(
       ** number so that sqlite3ResolveOrderGroupBy() will convert the
       ** order-by term to a copy of the result-set expression */
       if( iCol<1 || iCol>0xffff ){
-        resolveOutOfRangeError(pParse, zType, i+1, nResult);
+        resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
         return 1;
       }
       pItem->u.x.iOrderByCol = (u16)iCol;
index 9c1ad5813408e6a39486abd2e33f7e8191ca1a06..def9e566867e63e323f37f932ca65f94c21ca730 100644 (file)
@@ -355,7 +355,7 @@ do_execsql_test 8.5 {
 reset_db
 do_catchsql_test 8.6 {
   CREATE TABLE t0(c0);
-  CREATE INDEX i0 ON t0(LIKELIHOOD(1,2) AND 0);
+  CREATE INDEX i0 ON t0(likelihood(1,2) AND 0);
   ALTER TABLE t0 RENAME TO t1;
   SELECT sql FROM sqlite_master WHERE name='i0';
 } {1 {error in index i0: second argument to likelihood() must be a constant between 0.0 and 1.0}}