SQLite4
Check-in [79197d57b4]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change sqlite4_prepare() to return the number of bytes read from the input SQL script via an output variable (instead of returning a pointer to the next SQL statement within the buffer).
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 79197d57b4a6bffd58bd881148edf2968b084f2b
User & Date: dan 2013-05-10 19:19:07
Context
2013-05-18
19:42
Use the default sqlite4_mm object for malloc() and free(). check-in: e3280f4585 user: dan tags: trunk
2013-05-10
19:19
Change sqlite4_prepare() to return the number of bytes read from the input SQL script via an output variable (instead of returning a pointer to the next SQL statement within the buffer). check-in: 79197d57b4 user: dan tags: trunk
18:42
Change the sqlite4_exec() function to pass protected sqlite4_value objects to the callback instead of an array of nul-terminated strings. check-in: bbf3a54dcf user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/legacy.c.

    31     31     sqlite4 *db,                /* The database on which the SQL executes */
    32     32     const char *zSql,           /* The SQL to be executed */
    33     33     int (*xCall)(void*,int,sqlite4_value**,const char**),  /* Callback function */
    34     34     void *pArg,                 /* First argument to xCall() */
    35     35     char **pzErrMsg             /* Write error messages here */
    36     36   ){
    37     37     int rc = SQLITE4_OK;        /* Return code */
    38         -  const char *zLeftover;      /* Tail of unprocessed SQL */
    39     38     int nRetry = 0;             /* Number of retry attempts */
    40     39     int bAbort = 0;             /* Set to true if callback returns non-zero */
    41     40   
    42     41     if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT;
    43     42     if( zSql==0 ) zSql = "";
    44     43   
    45     44     sqlite4_mutex_enter(db->mutex);
................................................................................
    46     45     sqlite4Error(db, SQLITE4_OK, 0);
    47     46   
    48     47     /* Loop until we run out of SQL to execute, or the callback function
    49     48     ** returns non-zero, or an error occurs.  */
    50     49     while( zSql[0] && bAbort==0
    51     50        && (rc==SQLITE4_OK || (rc==SQLITE4_SCHEMA && (++nRetry)<2))
    52     51     ){
           52  +    int nUsed;                    /* Length of first SQL statement in zSql */
    53     53       int nCol;                     /* Number of returned columns */
    54     54       sqlite4_stmt *pStmt = 0;      /* The current SQL statement */
    55     55       const char **azCol = 0;       /* Names of result columns */
    56     56       sqlite4_value **apVal = 0;    /* Row of value objects */
    57     57   
    58     58       pStmt = 0;
    59         -    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover);
           59  +    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed);
    60     60       assert( rc==SQLITE4_OK || pStmt==0 );
    61     61       if( rc!=SQLITE4_OK ){
    62     62         continue;
    63     63       }
    64     64       if( !pStmt ){
    65     65         /* this happens for a comment or white-space */
    66         -      zSql = zLeftover;
           66  +      zSql += nUsed;
    67     67         continue;
    68     68       }
    69     69   
    70     70       nCol = sqlite4_column_count(pStmt);
    71     71       do {
    72     72   
    73     73         /* Step the statement. Then invoke the callback function if required */
................................................................................
   101    101         }
   102    102   
   103    103         if( bAbort || rc!=SQLITE4_ROW ){
   104    104           rc = sqlite4VdbeFinalize((Vdbe *)pStmt);
   105    105           pStmt = 0;
   106    106           if( rc!=SQLITE4_SCHEMA ){
   107    107             nRetry = 0;
   108         -          zSql = zLeftover;
          108  +          zSql += nUsed;
   109    109             while( sqlite4Isspace(zSql[0]) ) zSql++;
   110    110           }
   111    111           assert( rc!=SQLITE4_ROW );
   112    112         }
   113    113       }while( rc==SQLITE4_ROW );
   114    114   
   115    115       sqlite4DbFree(db, azCol);

Changes to src/prepare.c.

   467    467   */
   468    468   static int sqlite4Prepare(
   469    469     sqlite4 *db,              /* Database handle. */
   470    470     const char *zSql,         /* UTF-8 encoded SQL statement. */
   471    471     int nBytes,               /* Length of zSql in bytes. */
   472    472     Vdbe *pReprepare,         /* VM being reprepared */
   473    473     sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   474         -  const char **pzTail       /* OUT: End of parsed string */
          474  +  int *pnUsed               /* OUT: Bytes read from zSql */
   475    475   ){
   476    476     Parse *pParse;            /* Parsing context */
   477    477     char *zErrMsg = 0;        /* Error message */
   478    478     int rc = SQLITE4_OK;       /* Result code */
   479    479     int i;                    /* Loop counter */
   480    480   
   481    481     /* Allocate the parsing context */
................................................................................
   522    522     if( pParse->rc==SQLITE4_DONE ) pParse->rc = SQLITE4_OK;
   523    523     if( pParse->checkSchema ){
   524    524       schemaIsValid(pParse);
   525    525     }
   526    526     if( db->mallocFailed ){
   527    527       pParse->rc = SQLITE4_NOMEM;
   528    528     }
   529         -  if( pzTail ){
   530         -    *pzTail = pParse->zTail;
          529  +  if( pnUsed ){
          530  +    *pnUsed = (pParse->zTail-zSql);
   531    531     }
   532    532     rc = pParse->rc;
   533    533   
   534    534   #ifndef SQLITE4_OMIT_EXPLAIN
   535    535     if( rc==SQLITE4_OK && pParse->pVdbe && pParse->explain ){
   536    536       static const char * const azColName[] = {
   537    537          "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
................................................................................
   587    587   }
   588    588   static int sqlite4LockAndPrepare(
   589    589     sqlite4 *db,              /* Database handle. */
   590    590     const char *zSql,         /* UTF-8 encoded SQL statement. */
   591    591     int nBytes,               /* Length of zSql in bytes. */
   592    592     Vdbe *pOld,               /* VM being reprepared */
   593    593     sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   594         -  const char **pzTail       /* OUT: End of parsed string */
          594  +  int *pnUsed               /* OUT: Bytes read from zSql */
   595    595   ){
   596    596     int rc;
   597    597     assert( ppStmt!=0 );
   598    598     *ppStmt = 0;
   599    599     if( !sqlite4SafetyCheckOk(db) ){
   600    600       return SQLITE4_MISUSE_BKPT;
   601    601     }
   602    602     sqlite4_mutex_enter(db->mutex);
   603         -  rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pzTail);
          603  +  rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed);
   604    604     if( rc==SQLITE4_SCHEMA ){
   605    605       sqlite4_finalize(*ppStmt);
   606         -    rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pzTail);
          606  +    rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed);
   607    607     }
   608    608     sqlite4_mutex_leave(db->mutex);
   609    609     return rc;
   610    610   }
   611    611   
   612    612   /*
   613    613   ** Rerun the compilation of a statement after a schema change.
................................................................................
   654    654   ** occurs.
   655    655   */
   656    656   int sqlite4_prepare(
   657    657     sqlite4 *db,              /* Database handle. */
   658    658     const char *zSql,         /* UTF-8 encoded SQL statement. */
   659    659     int nBytes,               /* Length of zSql in bytes. */
   660    660     sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   661         -  const char **pzTail       /* OUT: End of parsed string */
          661  +  int *pnUsed               /* OUT: Bytes read from zSql */
   662    662   ){
   663    663     int rc;
   664         -  rc = sqlite4LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail);
          664  +  rc = sqlite4LockAndPrepare(db, zSql, nBytes, 0, ppStmt, pnUsed);
   665    665     assert( rc==SQLITE4_OK || ppStmt==0 || *ppStmt==0 );  /* VERIFY: F13021 */
   666    666     return rc;
   667    667   }

Changes to src/shell.c.

   760    760   
   761    761   
   762    762   static int shell_handle_row(
   763    763     struct callback_data *p,
   764    764     sqlite4_stmt *pStmt
   765    765   ){
   766    766     int nData = sqlite4_data_count(pStmt);
   767         -  int nCol = sqlite4_column_count(pStmt);
   768    767     int i;
   769    768   
   770    769     assert( nData>0 );
   771    770   
   772    771     switch( p->mode ){
   773    772       case MODE_Line: {
   774    773         int w = 5;
................................................................................
  1078   1077     const char *zScript,            /* SQL script to be evaluated */
  1079   1078     struct callback_data *pArg      /* Pointer to struct callback_data */
  1080   1079   ){
  1081   1080     int rc = SQLITE4_OK;            /* Return Code */
  1082   1081     const char *zSql = zScript;     /* Unexecuted portion of SQL script */
  1083   1082   
  1084   1083     while( zSql[0] && SQLITE4_OK==rc ){
  1085         -    int bFirst = 1;
  1086         -    const char *zLeftover;        /* Tail of unprocessed SQL */
         1084  +    int nUsed;                    /* Bytes read from zSql */
  1087   1085       sqlite4_stmt *pStmt = 0;      /* Next statement to execute. */
  1088   1086   
  1089         -    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover);
         1087  +    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed);
  1090   1088       if( rc!=SQLITE4_OK ) return rc;
  1091         -    zSql = zLeftover;
         1089  +    zSql += nUsed;
  1092   1090       if( pStmt==0 ) continue;      /* A comment or whitespace */
  1093   1091   
  1094   1092       if( pArg->echoOn ){
  1095   1093         const char *zStmtSql = sqlite4_sql(pStmt);
  1096   1094         fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
  1097   1095       }
  1098   1096   
................................................................................
  1117   1115         display_stats(db, pStmt, pArg, 0);
  1118   1116       }
  1119   1117   
  1120   1118       /* Finalize the statement just executed. If this fails, save a 
  1121   1119       ** copy of the error message. Otherwise, set zSql to point to the
  1122   1120       ** next statement to execute. */
  1123   1121       rc = sqlite4_finalize(pStmt);
  1124         -    zSql = zLeftover;
  1125   1122     } /* end while */
  1126   1123   
  1127   1124     return rc;
  1128   1125   }
  1129   1126   
  1130   1127   
  1131   1128   /*

Changes to src/sqlite.h.in.

  1689   1689   ** the nByte-th byte, whichever comes first. If the caller knows
  1690   1690   ** that the supplied string is nul-terminated, then there is a small
  1691   1691   ** performance advantage to be gained by passing an nByte parameter that
  1692   1692   ** is equal to the number of bytes in the input string <i>including</i>
  1693   1693   ** the nul-terminator bytes as this saves SQLite from having to
  1694   1694   ** make a copy of the input string.
  1695   1695   **
  1696         -** ^If pzTail is not NULL then *pzTail is made to point to the first byte
  1697         -** past the end of the first SQL statement in zSql.  These routines only
  1698         -** compile the first statement in zSql, so *pzTail is left pointing to
  1699         -** what remains uncompiled.
         1696  +** ^If pnUsed is not NULL then *pnUsed is set to the number of bytes read
         1697  +** from zSql. That is, the offset within zSql of the first byte past the
         1698  +** end of the SQL statement compiled. 
  1700   1699   **
  1701   1700   ** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
  1702   1701   ** executed using [sqlite4_step()].  ^If there is an error, *ppStmt is set
  1703   1702   ** to NULL.  ^If the input text contains no SQL (if the input is an empty
  1704         -** string or a comment) then *ppStmt is set to NULL.
  1705         -** The calling procedure is responsible for deleting the compiled
  1706         -** SQL statement using [sqlite4_finalize()] after it has finished with it.
  1707         -** ppStmt may not be NULL.
         1703  +** string or a comment) then *ppStmt is set to NULL. The calling procedure 
         1704  +** is responsible for deleting the compiled SQL statement using 
         1705  +** [sqlite4_finalize()] after it has finished with it. ppStmt may not be NULL.
  1708   1706   **
  1709   1707   ** ^On success, the sqlite4_prepare() family of routines return [SQLITE4_OK];
  1710   1708   ** otherwise an [error code] is returned.
  1711   1709   */
  1712   1710   int sqlite4_prepare(
  1713   1711     sqlite4 *db,            /* Database handle */
  1714   1712     const char *zSql,       /* SQL statement, UTF-8 encoded */
  1715   1713     int nByte,              /* Maximum length of zSql in bytes. */
  1716   1714     sqlite4_stmt **ppStmt,  /* OUT: Statement handle */
  1717         -  const char **pzTail
         1715  +  int *pnUsed             /* OUT: Number of bytes read from zSql */
  1718   1716   );
  1719   1717   
  1720   1718   /*
  1721   1719   ** CAPIREF: Retrieving Statement SQL
  1722   1720   **
  1723   1721   ** ^This interface can be used to retrieve a saved copy of the original
  1724   1722   ** SQL text used to create a [prepared statement] if that statement was

Changes to src/tclsqlite.c.

   761    761       }
   762    762     }
   763    763     
   764    764     /* If no prepared statement was found. Compile the SQL text. Also allocate
   765    765     ** a new SqlPreparedStmt structure.  */
   766    766     if( pPreStmt==0 ){
   767    767       int nByte;
          768  +    int nUsed;
   768    769   
   769         -    if( SQLITE4_OK!=sqlite4_prepare(pDb->db, zSql, -1, &pStmt, pzOut) ){
          770  +    if( SQLITE4_OK!=sqlite4_prepare(pDb->db, zSql, -1, &pStmt, &nUsed) ){
   770    771         Tcl_SetObjResult(interp, dbTextToObj(sqlite4_errmsg(pDb->db)));
   771    772         return TCL_ERROR;
   772    773       }
          774  +    *pzOut = &zSql[nUsed];
   773    775       if( pStmt==0 ){
   774    776         if( SQLITE4_OK!=sqlite4_errcode(pDb->db) ){
   775    777           /* A compile-time error in the statement. */
   776    778           Tcl_SetObjResult(interp, dbTextToObj(sqlite4_errmsg(pDb->db)));
   777    779           return TCL_ERROR;
   778    780         }else{
   779    781           /* The statement was a no-op.  Continue to the next statement
................................................................................
   786    788       assert( pPreStmt==0 );
   787    789       nVar = sqlite4_bind_parameter_count(pStmt);
   788    790       nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *);
   789    791       pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte);
   790    792       memset(pPreStmt, 0, nByte);
   791    793   
   792    794       pPreStmt->pStmt = pStmt;
   793         -    pPreStmt->nSql = (*pzOut - zSql);
          795  +    pPreStmt->nSql = nUsed;
   794    796       pPreStmt->zSql = sqlite4_sql(pStmt);
   795    797       pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1];
   796    798   #ifdef SQLITE4_TEST
   797    799       if( pPreStmt->zSql==0 ){
   798    800         char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1);
   799    801         memcpy(zCopy, zSql, pPreStmt->nSql);
   800    802         zCopy[pPreStmt->nSql] = '\0';

Changes to test/test_main.c.

  2927   2927     Tcl_Interp *interp,
  2928   2928     int objc,
  2929   2929     Tcl_Obj *CONST objv[]
  2930   2930   ){
  2931   2931     sqlite4 *db;
  2932   2932     const char *zSql;
  2933   2933     int bytes;
  2934         -  const char *zTail = 0;
         2934  +  int nUsed;
  2935   2935     sqlite4_stmt *pStmt = 0;
  2936   2936     char zBuf[50];
  2937   2937     int rc;
  2938   2938   
  2939   2939     if( objc!=5 && objc!=4 ){
  2940   2940       Tcl_AppendResult(interp, "wrong # args: should be \"", 
  2941   2941          Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
  2942   2942       return TCL_ERROR;
  2943   2943     }
  2944   2944     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
  2945   2945     zSql = Tcl_GetString(objv[2]);
  2946   2946     if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
  2947   2947   
  2948         -  rc = sqlite4_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
         2948  +  rc = sqlite4_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &nUsed : 0);
  2949   2949     Tcl_ResetResult(interp);
  2950   2950     if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  2951         -  if( zTail && objc>=5 ){
         2951  +  if( objc>=5 ){
         2952  +    const char *zTail = &zSql[nUsed];
         2953  +    int nTail = -1;
  2952   2954       if( bytes>=0 ){
  2953         -      bytes = bytes - (zTail-zSql);
         2955  +      nTail = bytes - nUsed;
  2954   2956       }
  2955         -    if( strlen(zTail)<bytes ){
  2956         -      bytes = strlen(zTail);
  2957         -    }
  2958         -    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
         2957  +    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, nTail), 0);
  2959   2958     }
  2960   2959     if( rc!=SQLITE4_OK ){
  2961   2960       assert( pStmt==0 );
  2962   2961       sprintf(zBuf, "(%d) ", rc);
  2963   2962       Tcl_AppendResult(interp, zBuf, sqlite4_errmsg(db), 0);
  2964   2963       return TCL_ERROR;
  2965   2964     }

Changes to test/test_thread.c.

   490    490   ** system may become deadlocked.
   491    491   */
   492    492   int sqlite4_blocking_prepare(
   493    493     sqlite4 *db,              /* Database handle. */
   494    494     const char *zSql,         /* UTF-8 encoded SQL statement. */
   495    495     int nSql,                 /* Length of zSql in bytes. */
   496    496     sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
   497         -  const char **pz           /* OUT: End of parsed string */
          497  +  int *pn                   /* OUT: Bytes read from zSql */
   498    498   ){
   499    499     int rc;
   500         -  while( SQLITE4_LOCKED==(rc = sqlite4_prepare(db, zSql, nSql, ppStmt, pz)) ){
          500  +  while( SQLITE4_LOCKED==(rc = sqlite4_prepare(db, zSql, nSql, ppStmt, pn)) ){
   501    501       rc = wait_for_unlock_notify(db);
   502    502       if( rc!=SQLITE4_OK ) break;
   503    503     }
   504    504     return rc;
   505    505   }
   506    506   /* END_SQLITE4_BLOCKING_STEP */
   507    507   
................................................................................
   541    541     Tcl_Interp *interp,
   542    542     int objc,
   543    543     Tcl_Obj *CONST objv[]
   544    544   ){
   545    545     sqlite4 *db;
   546    546     const char *zSql;
   547    547     int bytes;
   548         -  const char *zTail = 0;
          548  +  int nUsed;
   549    549     sqlite4_stmt *pStmt = 0;
   550    550     char zBuf[50];
   551    551     int rc;
   552    552     int isBlocking = !(clientData==0);
   553    553   
   554    554     if( objc!=5 && objc!=4 ){
   555    555       Tcl_AppendResult(interp, "wrong # args: should be \"", 
................................................................................
   557    557       return TCL_ERROR;
   558    558     }
   559    559     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
   560    560     zSql = Tcl_GetString(objv[2]);
   561    561     if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
   562    562   
   563    563     if( isBlocking ){
   564         -    rc = sqlite4_blocking_prepare(db, zSql, bytes, &pStmt, &zTail);
          564  +    rc = sqlite4_blocking_prepare(db, zSql, bytes, &pStmt, &nUsed);
   565    565     }else{
   566         -    rc = sqlite4_prepare(db, zSql, bytes, &pStmt, &zTail);
          566  +    rc = sqlite4_prepare(db, zSql, bytes, &pStmt, &nUsed);
   567    567     }
   568    568   
   569    569     assert(rc==SQLITE4_OK || pStmt==0);
   570         -  if( zTail && objc>=5 ){
          570  +  if( objc>=5 ){
          571  +    const char *zTail = zSql[nUsed];
          572  +    int nTail = -1;
   571    573       if( bytes>=0 ){
   572         -      bytes = bytes - (zTail-zSql);
          574  +      nTail = bytes - nUsed;
   573    575       }
   574         -    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
          576  +    Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, nTail), 0);
   575    577     }
   576    578     if( rc!=SQLITE4_OK ){
   577    579       assert( pStmt==0 );
   578    580       sprintf(zBuf, "%s ", (char *)sqlite4TestErrorName(rc));
   579    581       Tcl_AppendResult(interp, zBuf, sqlite4_errmsg(db), 0);
   580    582       return TCL_ERROR;
   581    583     }