Index: src/legacy.c ================================================================== --- src/legacy.c +++ src/legacy.c @@ -33,11 +33,10 @@ int (*xCall)(void*,int,sqlite4_value**,const char**), /* Callback function */ void *pArg, /* First argument to xCall() */ char **pzErrMsg /* Write error messages here */ ){ int rc = SQLITE4_OK; /* Return code */ - const char *zLeftover; /* Tail of unprocessed SQL */ int nRetry = 0; /* Number of retry attempts */ int bAbort = 0; /* Set to true if callback returns non-zero */ if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT; if( zSql==0 ) zSql = ""; @@ -48,24 +47,25 @@ /* Loop until we run out of SQL to execute, or the callback function ** returns non-zero, or an error occurs. */ while( zSql[0] && bAbort==0 && (rc==SQLITE4_OK || (rc==SQLITE4_SCHEMA && (++nRetry)<2)) ){ + int nUsed; /* Length of first SQL statement in zSql */ int nCol; /* Number of returned columns */ sqlite4_stmt *pStmt = 0; /* The current SQL statement */ const char **azCol = 0; /* Names of result columns */ sqlite4_value **apVal = 0; /* Row of value objects */ pStmt = 0; - rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover); + rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed); assert( rc==SQLITE4_OK || pStmt==0 ); if( rc!=SQLITE4_OK ){ continue; } if( !pStmt ){ /* this happens for a comment or white-space */ - zSql = zLeftover; + zSql += nUsed; continue; } nCol = sqlite4_column_count(pStmt); do { @@ -103,11 +103,11 @@ if( bAbort || rc!=SQLITE4_ROW ){ rc = sqlite4VdbeFinalize((Vdbe *)pStmt); pStmt = 0; if( rc!=SQLITE4_SCHEMA ){ nRetry = 0; - zSql = zLeftover; + zSql += nUsed; while( sqlite4Isspace(zSql[0]) ) zSql++; } assert( rc!=SQLITE4_ROW ); } }while( rc==SQLITE4_ROW ); Index: src/prepare.c ================================================================== --- src/prepare.c +++ src/prepare.c @@ -469,11 +469,11 @@ sqlite4 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ Vdbe *pReprepare, /* VM being reprepared */ sqlite4_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ + int *pnUsed /* OUT: Bytes read from zSql */ ){ Parse *pParse; /* Parsing context */ char *zErrMsg = 0; /* Error message */ int rc = SQLITE4_OK; /* Result code */ int i; /* Loop counter */ @@ -524,12 +524,12 @@ schemaIsValid(pParse); } if( db->mallocFailed ){ pParse->rc = SQLITE4_NOMEM; } - if( pzTail ){ - *pzTail = pParse->zTail; + if( pnUsed ){ + *pnUsed = (pParse->zTail-zSql); } rc = pParse->rc; #ifndef SQLITE4_OMIT_EXPLAIN if( rc==SQLITE4_OK && pParse->pVdbe && pParse->explain ){ @@ -589,23 +589,23 @@ sqlite4 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ Vdbe *pOld, /* VM being reprepared */ sqlite4_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ + int *pnUsed /* OUT: Bytes read from zSql */ ){ int rc; assert( ppStmt!=0 ); *ppStmt = 0; if( !sqlite4SafetyCheckOk(db) ){ return SQLITE4_MISUSE_BKPT; } sqlite4_mutex_enter(db->mutex); - rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pzTail); + rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed); if( rc==SQLITE4_SCHEMA ){ sqlite4_finalize(*ppStmt); - rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pzTail); + rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed); } sqlite4_mutex_leave(db->mutex); return rc; } @@ -656,12 +656,12 @@ int sqlite4_prepare( sqlite4 *db, /* Database handle. */ const char *zSql, /* UTF-8 encoded SQL statement. */ int nBytes, /* Length of zSql in bytes. */ sqlite4_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ - const char **pzTail /* OUT: End of parsed string */ + int *pnUsed /* OUT: Bytes read from zSql */ ){ int rc; - rc = sqlite4LockAndPrepare(db,zSql,nBytes,0,ppStmt,pzTail); + rc = sqlite4LockAndPrepare(db, zSql, nBytes, 0, ppStmt, pnUsed); assert( rc==SQLITE4_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */ return rc; } Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -762,11 +762,10 @@ static int shell_handle_row( struct callback_data *p, sqlite4_stmt *pStmt ){ int nData = sqlite4_data_count(pStmt); - int nCol = sqlite4_column_count(pStmt); int i; assert( nData>0 ); switch( p->mode ){ @@ -1080,17 +1079,16 @@ ){ int rc = SQLITE4_OK; /* Return Code */ const char *zSql = zScript; /* Unexecuted portion of SQL script */ while( zSql[0] && SQLITE4_OK==rc ){ - int bFirst = 1; - const char *zLeftover; /* Tail of unprocessed SQL */ + int nUsed; /* Bytes read from zSql */ sqlite4_stmt *pStmt = 0; /* Next statement to execute. */ - rc = sqlite4_prepare(db, zSql, -1, &pStmt, &zLeftover); + rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed); if( rc!=SQLITE4_OK ) return rc; - zSql = zLeftover; + zSql += nUsed; if( pStmt==0 ) continue; /* A comment or whitespace */ if( pArg->echoOn ){ const char *zStmtSql = sqlite4_sql(pStmt); fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); @@ -1119,11 +1117,10 @@ /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc = sqlite4_finalize(pStmt); - zSql = zLeftover; } /* end while */ return rc; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -1691,32 +1691,30 @@ ** performance advantage to be gained by passing an nByte parameter that ** is equal to the number of bytes in the input string including ** the nul-terminator bytes as this saves SQLite from having to ** make a copy of the input string. ** -** ^If pzTail is not NULL then *pzTail is made to point to the first byte -** past the end of the first SQL statement in zSql. These routines only -** compile the first statement in zSql, so *pzTail is left pointing to -** what remains uncompiled. +** ^If pnUsed is not NULL then *pnUsed is set to the number of bytes read +** from zSql. That is, the offset within zSql of the first byte past the +** end of the SQL statement compiled. ** ** ^*ppStmt is left pointing to a compiled [prepared statement] that can be ** executed using [sqlite4_step()]. ^If there is an error, *ppStmt is set ** to NULL. ^If the input text contains no SQL (if the input is an empty -** string or a comment) then *ppStmt is set to NULL. -** The calling procedure is responsible for deleting the compiled -** SQL statement using [sqlite4_finalize()] after it has finished with it. -** ppStmt may not be NULL. +** string or a comment) then *ppStmt is set to NULL. The calling procedure +** is responsible for deleting the compiled SQL statement using +** [sqlite4_finalize()] after it has finished with it. ppStmt may not be NULL. ** ** ^On success, the sqlite4_prepare() family of routines return [SQLITE4_OK]; ** otherwise an [error code] is returned. */ int sqlite4_prepare( sqlite4 *db, /* Database handle */ const char *zSql, /* SQL statement, UTF-8 encoded */ int nByte, /* Maximum length of zSql in bytes. */ sqlite4_stmt **ppStmt, /* OUT: Statement handle */ - const char **pzTail + int *pnUsed /* OUT: Number of bytes read from zSql */ ); /* ** CAPIREF: Retrieving Statement SQL ** Index: src/tclsqlite.c ================================================================== --- src/tclsqlite.c +++ src/tclsqlite.c @@ -763,15 +763,17 @@ /* If no prepared statement was found. Compile the SQL text. Also allocate ** a new SqlPreparedStmt structure. */ if( pPreStmt==0 ){ int nByte; + int nUsed; - if( SQLITE4_OK!=sqlite4_prepare(pDb->db, zSql, -1, &pStmt, pzOut) ){ + if( SQLITE4_OK!=sqlite4_prepare(pDb->db, zSql, -1, &pStmt, &nUsed) ){ Tcl_SetObjResult(interp, dbTextToObj(sqlite4_errmsg(pDb->db))); return TCL_ERROR; } + *pzOut = &zSql[nUsed]; if( pStmt==0 ){ if( SQLITE4_OK!=sqlite4_errcode(pDb->db) ){ /* A compile-time error in the statement. */ Tcl_SetObjResult(interp, dbTextToObj(sqlite4_errmsg(pDb->db))); return TCL_ERROR; @@ -788,11 +790,11 @@ nByte = sizeof(SqlPreparedStmt) + nVar*sizeof(Tcl_Obj *); pPreStmt = (SqlPreparedStmt*)Tcl_Alloc(nByte); memset(pPreStmt, 0, nByte); pPreStmt->pStmt = pStmt; - pPreStmt->nSql = (*pzOut - zSql); + pPreStmt->nSql = nUsed; pPreStmt->zSql = sqlite4_sql(pStmt); pPreStmt->apParm = (Tcl_Obj **)&pPreStmt[1]; #ifdef SQLITE4_TEST if( pPreStmt->zSql==0 ){ char *zCopy = Tcl_Alloc(pPreStmt->nSql + 1); Index: test/test_main.c ================================================================== --- test/test_main.c +++ test/test_main.c @@ -2929,11 +2929,11 @@ Tcl_Obj *CONST objv[] ){ sqlite4 *db; const char *zSql; int bytes; - const char *zTail = 0; + int nUsed; sqlite4_stmt *pStmt = 0; char zBuf[50]; int rc; if( objc!=5 && objc!=4 ){ @@ -2943,21 +2943,20 @@ } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; zSql = Tcl_GetString(objv[2]); if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; - rc = sqlite4_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); + rc = sqlite4_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &nUsed : 0); Tcl_ResetResult(interp); if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR; - if( zTail && objc>=5 ){ + if( objc>=5 ){ + const char *zTail = &zSql[nUsed]; + int nTail = -1; if( bytes>=0 ){ - bytes = bytes - (zTail-zSql); + nTail = bytes - nUsed; } - if( strlen(zTail)=5 ){ + if( objc>=5 ){ + const char *zTail = zSql[nUsed]; + int nTail = -1; if( bytes>=0 ){ - bytes = bytes - (zTail-zSql); + nTail = bytes - nUsed; } - Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0); + Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, nTail), 0); } if( rc!=SQLITE4_OK ){ assert( pStmt==0 ); sprintf(zBuf, "%s ", (char *)sqlite4TestErrorName(rc)); Tcl_AppendResult(interp, zBuf, sqlite4_errmsg(db), 0);