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);