| Index: third_party/sqlite/src/src/vdbeapi.c
 | 
| diff --git a/third_party/sqlite/src/src/vdbeapi.c b/third_party/sqlite/src/src/vdbeapi.c
 | 
| index 634c29c45da0ebd97528401035cc3d63897abc90..90baaccc68a4e087f6ac6ddb5b146d1777b7d8d2 100644
 | 
| --- a/third_party/sqlite/src/src/vdbeapi.c
 | 
| +++ b/third_party/sqlite/src/src/vdbeapi.c
 | 
| @@ -12,8 +12,6 @@
 | 
|  **
 | 
|  ** This file contains code use to implement APIs that are part of the
 | 
|  ** VDBE.
 | 
| -**
 | 
| -** $Id: vdbeapi.c,v 1.167 2009/06/25 01:47:12 drh Exp $
 | 
|  */
 | 
|  #include "sqliteInt.h"
 | 
|  #include "vdbeInt.h"
 | 
| @@ -34,6 +32,28 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
 | 
|  #endif
 | 
|  
 | 
|  /*
 | 
| +** Check on a Vdbe to make sure it has not been finalized.  Log
 | 
| +** an error and return true if it has been finalized (or is otherwise
 | 
| +** invalid).  Return false if it is ok.
 | 
| +*/
 | 
| +static int vdbeSafety(Vdbe *p){
 | 
| +  if( p->db==0 ){
 | 
| +    sqlite3_log(SQLITE_MISUSE, "API called with finalized prepared statement");
 | 
| +    return 1;
 | 
| +  }else{
 | 
| +    return 0;
 | 
| +  }
 | 
| +}
 | 
| +static int vdbeSafetyNotNull(Vdbe *p){
 | 
| +  if( p==0 ){
 | 
| +    sqlite3_log(SQLITE_MISUSE, "API called with NULL prepared statement");
 | 
| +    return 1;
 | 
| +  }else{
 | 
| +    return vdbeSafety(p);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +/*
 | 
|  ** The following routine destroys a virtual machine that is created by
 | 
|  ** the sqlite3_compile() routine. The integer returned is an SQLITE_
 | 
|  ** success/failure code that describes the result of executing the virtual
 | 
| @@ -45,12 +65,18 @@ int sqlite3_expired(sqlite3_stmt *pStmt){
 | 
|  int sqlite3_finalize(sqlite3_stmt *pStmt){
 | 
|    int rc;
 | 
|    if( pStmt==0 ){
 | 
| +    /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
 | 
| +    ** pointer is a harmless no-op. */
 | 
|      rc = SQLITE_OK;
 | 
|    }else{
 | 
|      Vdbe *v = (Vdbe*)pStmt;
 | 
|      sqlite3 *db = v->db;
 | 
|  #if SQLITE_THREADSAFE
 | 
| -    sqlite3_mutex *mutex = v->db->mutex;
 | 
| +    sqlite3_mutex *mutex;
 | 
| +#endif
 | 
| +    if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
 | 
| +#if SQLITE_THREADSAFE
 | 
| +    mutex = v->db->mutex;
 | 
|  #endif
 | 
|      sqlite3_mutex_enter(mutex);
 | 
|      rc = sqlite3VdbeFinalize(v);
 | 
| @@ -99,6 +125,9 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
 | 
|      sqlite3VdbeMemRelease(&p->aVar[i]);
 | 
|      p->aVar[i].flags = MEM_Null;
 | 
|    }
 | 
| +  if( p->isPrepareV2 && p->expmask ){
 | 
| +    p->expired = 1;
 | 
| +  }
 | 
|    sqlite3_mutex_leave(mutex);
 | 
|    return rc;
 | 
|  }
 | 
| @@ -114,7 +143,7 @@ const void *sqlite3_value_blob(sqlite3_value *pVal){
 | 
|      sqlite3VdbeMemExpandBlob(p);
 | 
|      p->flags &= ~MEM_Str;
 | 
|      p->flags |= MEM_Blob;
 | 
| -    return p->z;
 | 
| +    return p->n ? p->z : 0;
 | 
|    }else{
 | 
|      return sqlite3_value_text(pVal);
 | 
|    }
 | 
| @@ -280,6 +309,27 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| +** This function is called after a transaction has been committed. It 
 | 
| +** invokes callbacks registered with sqlite3_wal_hook() as required.
 | 
| +*/
 | 
| +static int doWalCallbacks(sqlite3 *db){
 | 
| +  int rc = SQLITE_OK;
 | 
| +#ifndef SQLITE_OMIT_WAL
 | 
| +  int i;
 | 
| +  for(i=0; i<db->nDb; i++){
 | 
| +    Btree *pBt = db->aDb[i].pBt;
 | 
| +    if( pBt ){
 | 
| +      int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
 | 
| +      if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
 | 
| +        rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry);
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +#endif
 | 
| +  return rc;
 | 
| +}
 | 
| +
 | 
| +/*
 | 
|  ** Execute the statement pStmt, either until a row of data is ready, the
 | 
|  ** statement is completely executed or an error occurs.
 | 
|  **
 | 
| @@ -294,26 +344,45 @@ static int sqlite3Step(Vdbe *p){
 | 
|  
 | 
|    assert(p);
 | 
|    if( p->magic!=VDBE_MAGIC_RUN ){
 | 
| -    return SQLITE_MISUSE;
 | 
| +    /* We used to require that sqlite3_reset() be called before retrying
 | 
| +    ** sqlite3_step() after any error or after SQLITE_DONE.  But beginning
 | 
| +    ** with version 3.7.0, we changed this so that sqlite3_reset() would
 | 
| +    ** be called automatically instead of throwing the SQLITE_MISUSE error.
 | 
| +    ** This "automatic-reset" change is not technically an incompatibility, 
 | 
| +    ** since any application that receives an SQLITE_MISUSE is broken by
 | 
| +    ** definition.
 | 
| +    **
 | 
| +    ** Nevertheless, some published applications that were originally written
 | 
| +    ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE 
 | 
| +    ** returns, and the so were broken by the automatic-reset change.  As a
 | 
| +    ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
 | 
| +    ** legacy behavior of returning SQLITE_MISUSE for cases where the 
 | 
| +    ** previous sqlite3_step() returned something other than a SQLITE_LOCKED
 | 
| +    ** or SQLITE_BUSY error.
 | 
| +    */
 | 
| +#ifdef SQLITE_OMIT_AUTORESET
 | 
| +    if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
 | 
| +      sqlite3_reset((sqlite3_stmt*)p);
 | 
| +    }else{
 | 
| +      return SQLITE_MISUSE_BKPT;
 | 
| +    }
 | 
| +#else
 | 
| +    sqlite3_reset((sqlite3_stmt*)p);
 | 
| +#endif
 | 
|    }
 | 
|  
 | 
| -  /* Assert that malloc() has not failed */
 | 
| +  /* Check that malloc() has not failed. If it has, return early. */
 | 
|    db = p->db;
 | 
|    if( db->mallocFailed ){
 | 
| +    p->rc = SQLITE_NOMEM;
 | 
|      return SQLITE_NOMEM;
 | 
|    }
 | 
|  
 | 
|    if( p->pc<=0 && p->expired ){
 | 
| -    if( ALWAYS(p->rc==SQLITE_OK) ){
 | 
| -      p->rc = SQLITE_SCHEMA;
 | 
| -    }
 | 
| +    p->rc = SQLITE_SCHEMA;
 | 
|      rc = SQLITE_ERROR;
 | 
|      goto end_of_step;
 | 
|    }
 | 
| -  if( sqlite3SafetyOn(db) ){
 | 
| -    p->rc = SQLITE_MISUSE;
 | 
| -    return SQLITE_MISUSE;
 | 
| -  }
 | 
|    if( p->pc<0 ){
 | 
|      /* If there are no other statements currently running, then
 | 
|      ** reset the interrupt flag.  This prevents a call to sqlite3_interrupt
 | 
| @@ -323,11 +392,11 @@ static int sqlite3Step(Vdbe *p){
 | 
|        db->u1.isInterrupted = 0;
 | 
|      }
 | 
|  
 | 
| +    assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
 | 
| +
 | 
|  #ifndef SQLITE_OMIT_TRACE
 | 
|      if( db->xProfile && !db->init.busy ){
 | 
| -      double rNow;
 | 
| -      sqlite3OsCurrentTime(db->pVfs, &rNow);
 | 
| -      p->startTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
 | 
| +      sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
 | 
|      }
 | 
|  #endif
 | 
|  
 | 
| @@ -341,27 +410,29 @@ static int sqlite3Step(Vdbe *p){
 | 
|    }else
 | 
|  #endif /* SQLITE_OMIT_EXPLAIN */
 | 
|    {
 | 
| +    db->vdbeExecCnt++;
 | 
|      rc = sqlite3VdbeExec(p);
 | 
| -  }
 | 
| -
 | 
| -  if( sqlite3SafetyOff(db) ){
 | 
| -    rc = SQLITE_MISUSE;
 | 
| +    db->vdbeExecCnt--;
 | 
|    }
 | 
|  
 | 
|  #ifndef SQLITE_OMIT_TRACE
 | 
|    /* Invoke the profile callback if there is one
 | 
|    */
 | 
|    if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
 | 
| -    double rNow;
 | 
| -    u64 elapseTime;
 | 
| -
 | 
| -    sqlite3OsCurrentTime(db->pVfs, &rNow);
 | 
| -    elapseTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
 | 
| -    elapseTime -= p->startTime;
 | 
| -    db->xProfile(db->pProfileArg, p->zSql, elapseTime);
 | 
| +    sqlite3_int64 iNow;
 | 
| +    sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
 | 
| +    db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
 | 
|    }
 | 
|  #endif
 | 
|  
 | 
| +  if( rc==SQLITE_DONE ){
 | 
| +    assert( p->rc==SQLITE_OK );
 | 
| +    p->rc = doWalCallbacks(db);
 | 
| +    if( p->rc!=SQLITE_OK ){
 | 
| +      rc = SQLITE_ERROR;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    db->errCode = rc;
 | 
|    if( SQLITE_NOMEM==sqlite3ApiExit(p->db, p->rc) ){
 | 
|      p->rc = SQLITE_NOMEM;
 | 
| @@ -394,39 +465,44 @@ end_of_step:
 | 
|  ** call sqlite3Reprepare() and try again.
 | 
|  */
 | 
|  int sqlite3_step(sqlite3_stmt *pStmt){
 | 
| -  int rc = SQLITE_MISUSE;
 | 
| -  if( pStmt ){
 | 
| -    int cnt = 0;
 | 
| -    Vdbe *v = (Vdbe*)pStmt;
 | 
| -    sqlite3 *db = v->db;
 | 
| -    sqlite3_mutex_enter(db->mutex);
 | 
| -    while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
 | 
| -           && cnt++ < 5
 | 
| -           && (rc = sqlite3Reprepare(v))==SQLITE_OK ){
 | 
| -      sqlite3_reset(pStmt);
 | 
| -      v->expired = 0;
 | 
| -    }
 | 
| -    if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
 | 
| -      /* This case occurs after failing to recompile an sql statement. 
 | 
| -      ** The error message from the SQL compiler has already been loaded 
 | 
| -      ** into the database handle. This block copies the error message 
 | 
| -      ** from the database handle into the statement and sets the statement
 | 
| -      ** program counter to 0 to ensure that when the statement is 
 | 
| -      ** finalized or reset the parser error message is available via
 | 
| -      ** sqlite3_errmsg() and sqlite3_errcode().
 | 
| -      */
 | 
| -      const char *zErr = (const char *)sqlite3_value_text(db->pErr); 
 | 
| -      sqlite3DbFree(db, v->zErrMsg);
 | 
| -      if( !db->mallocFailed ){
 | 
| -        v->zErrMsg = sqlite3DbStrDup(db, zErr);
 | 
| -      } else {
 | 
| -        v->zErrMsg = 0;
 | 
| -        v->rc = SQLITE_NOMEM;
 | 
| -      }
 | 
| +  int rc = SQLITE_OK;      /* Result from sqlite3Step() */
 | 
| +  int rc2 = SQLITE_OK;     /* Result from sqlite3Reprepare() */
 | 
| +  Vdbe *v = (Vdbe*)pStmt;  /* the prepared statement */
 | 
| +  int cnt = 0;             /* Counter to prevent infinite loop of reprepares */
 | 
| +  sqlite3 *db;             /* The database connection */
 | 
| +
 | 
| +  if( vdbeSafetyNotNull(v) ){
 | 
| +    return SQLITE_MISUSE_BKPT;
 | 
| +  }
 | 
| +  db = v->db;
 | 
| +  sqlite3_mutex_enter(db->mutex);
 | 
| +  while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
 | 
| +         && cnt++ < 5
 | 
| +         && (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
 | 
| +    sqlite3_reset(pStmt);
 | 
| +    v->expired = 0;
 | 
| +  }
 | 
| +  if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
 | 
| +    /* This case occurs after failing to recompile an sql statement. 
 | 
| +    ** The error message from the SQL compiler has already been loaded 
 | 
| +    ** into the database handle. This block copies the error message 
 | 
| +    ** from the database handle into the statement and sets the statement
 | 
| +    ** program counter to 0 to ensure that when the statement is 
 | 
| +    ** finalized or reset the parser error message is available via
 | 
| +    ** sqlite3_errmsg() and sqlite3_errcode().
 | 
| +    */
 | 
| +    const char *zErr = (const char *)sqlite3_value_text(db->pErr); 
 | 
| +    sqlite3DbFree(db, v->zErrMsg);
 | 
| +    if( !db->mallocFailed ){
 | 
| +      v->zErrMsg = sqlite3DbStrDup(db, zErr);
 | 
| +      v->rc = rc2;
 | 
| +    } else {
 | 
| +      v->zErrMsg = 0;
 | 
| +      v->rc = rc = SQLITE_NOMEM;
 | 
|      }
 | 
| -    rc = sqlite3ApiExit(db, rc);
 | 
| -    sqlite3_mutex_leave(db->mutex);
 | 
|    }
 | 
| +  rc = sqlite3ApiExit(db, rc);
 | 
| +  sqlite3_mutex_leave(db->mutex);
 | 
|    return rc;
 | 
|  }
 | 
|  
 | 
| @@ -442,6 +518,12 @@ void *sqlite3_user_data(sqlite3_context *p){
 | 
|  /*
 | 
|  ** Extract the user data from a sqlite3_context structure and return a
 | 
|  ** pointer to it.
 | 
| +**
 | 
| +** IMPLEMENTATION-OF: R-46798-50301 The sqlite3_context_db_handle() interface
 | 
| +** returns a copy of the pointer to the database connection (the 1st
 | 
| +** parameter) of the sqlite3_create_function() and
 | 
| +** sqlite3_create_function16() routines that originally registered the
 | 
| +** application defined function.
 | 
|  */
 | 
|  sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
 | 
|    assert( p && p->pFunc );
 | 
| @@ -480,8 +562,9 @@ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
 | 
|    assert( p && p->pFunc && p->pFunc->xStep );
 | 
|    assert( sqlite3_mutex_held(p->s.db->mutex) );
 | 
|    pMem = p->pMem;
 | 
| +  testcase( nByte<0 );
 | 
|    if( (pMem->flags & MEM_Agg)==0 ){
 | 
| -    if( nByte==0 ){
 | 
| +    if( nByte<=0 ){
 | 
|        sqlite3VdbeMemReleaseExternal(pMem);
 | 
|        pMem->flags = MEM_Null;
 | 
|        pMem->z = 0;
 | 
| @@ -599,13 +682,11 @@ int sqlite3_data_count(sqlite3_stmt *pStmt){
 | 
|  */
 | 
|  static Mem *columnMem(sqlite3_stmt *pStmt, int i){
 | 
|    Vdbe *pVm;
 | 
| -  int vals;
 | 
|    Mem *pOut;
 | 
|  
 | 
|    pVm = (Vdbe *)pStmt;
 | 
|    if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
 | 
|      sqlite3_mutex_enter(pVm->db->mutex);
 | 
| -    vals = sqlite3_data_count(pStmt);
 | 
|      pOut = &pVm->pResultSet[i];
 | 
|    }else{
 | 
|      /* If the value passed as the second argument is out of range, return
 | 
| @@ -623,7 +704,11 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
 | 
|  #if defined(SQLITE_DEBUG) && defined(__GNUC__)
 | 
|        __attribute__((aligned(8))) 
 | 
|  #endif
 | 
| -      = {{0}, (double)0, 0, "", 0, MEM_Null, SQLITE_NULL, 0, 0, 0 };
 | 
| +      = {0, "", (double)0, {0}, 0, MEM_Null, SQLITE_NULL, 0,
 | 
| +#ifdef SQLITE_DEBUG
 | 
| +         0, 0,  /* pScopyFrom, pFiller */
 | 
| +#endif
 | 
| +         0, 0 };
 | 
|  
 | 
|      if( pVm && ALWAYS(pVm->db) ){
 | 
|        sqlite3_mutex_enter(pVm->db->mutex);
 | 
| @@ -650,8 +735,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
 | 
|  **     sqlite3_column_real()
 | 
|  **     sqlite3_column_bytes()
 | 
|  **     sqlite3_column_bytes16()
 | 
| -**
 | 
| -** But not for sqlite3_column_blob(), which never calls malloc().
 | 
| +**     sqiite3_column_blob()
 | 
|  */
 | 
|  static void columnMallocFailure(sqlite3_stmt *pStmt)
 | 
|  {
 | 
| @@ -895,12 +979,16 @@ const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
 | 
|  */
 | 
|  static int vdbeUnbind(Vdbe *p, int i){
 | 
|    Mem *pVar;
 | 
| -  if( p==0 ) return SQLITE_MISUSE;
 | 
| +  if( vdbeSafetyNotNull(p) ){
 | 
| +    return SQLITE_MISUSE_BKPT;
 | 
| +  }
 | 
|    sqlite3_mutex_enter(p->db->mutex);
 | 
|    if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
 | 
|      sqlite3Error(p->db, SQLITE_MISUSE, 0);
 | 
|      sqlite3_mutex_leave(p->db->mutex);
 | 
| -    return SQLITE_MISUSE;
 | 
| +    sqlite3_log(SQLITE_MISUSE, 
 | 
| +        "bind on a busy prepared statement: [%s]", p->zSql);
 | 
| +    return SQLITE_MISUSE_BKPT;
 | 
|    }
 | 
|    if( i<1 || i>p->nVar ){
 | 
|      sqlite3Error(p->db, SQLITE_RANGE, 0);
 | 
| @@ -912,6 +1000,21 @@ static int vdbeUnbind(Vdbe *p, int i){
 | 
|    sqlite3VdbeMemRelease(pVar);
 | 
|    pVar->flags = MEM_Null;
 | 
|    sqlite3Error(p->db, SQLITE_OK, 0);
 | 
| +
 | 
| +  /* If the bit corresponding to this variable in Vdbe.expmask is set, then 
 | 
| +  ** binding a new value to this variable invalidates the current query plan.
 | 
| +  **
 | 
| +  ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
 | 
| +  ** parameter in the WHERE clause might influence the choice of query plan
 | 
| +  ** for a statement, then the statement will be automatically recompiled,
 | 
| +  ** as if there had been a schema change, on the first sqlite3_step() call
 | 
| +  ** following any change to the bindings of that parameter.
 | 
| +  */
 | 
| +  if( p->isPrepareV2 &&
 | 
| +     ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
 | 
| +  ){
 | 
| +    p->expired = 1;
 | 
| +  }
 | 
|    return SQLITE_OK;
 | 
|  }
 | 
|  
 | 
| @@ -942,6 +1045,8 @@ static int bindText(
 | 
|        rc = sqlite3ApiExit(p->db, rc);
 | 
|      }
 | 
|      sqlite3_mutex_leave(p->db->mutex);
 | 
| +  }else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
 | 
| +    xDel((void*)zData);
 | 
|    }
 | 
|    return rc;
 | 
|  }
 | 
| @@ -1108,8 +1213,7 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
 | 
|  ** with that name.  If there is no variable with the given name,
 | 
|  ** return 0.
 | 
|  */
 | 
| -int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
 | 
| -  Vdbe *p = (Vdbe*)pStmt;
 | 
| +int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
 | 
|    int i;
 | 
|    if( p==0 ){
 | 
|      return 0;
 | 
| @@ -1118,13 +1222,16 @@ int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
 | 
|    if( zName ){
 | 
|      for(i=0; i<p->nVar; i++){
 | 
|        const char *z = p->azVar[i];
 | 
| -      if( z && strcmp(z,zName)==0 ){
 | 
| +      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
 | 
|          return i+1;
 | 
|        }
 | 
|      }
 | 
|    }
 | 
|    return 0;
 | 
|  }
 | 
| +int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
 | 
| +  return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
 | 
| +}
 | 
|  
 | 
|  /*
 | 
|  ** Transfer all bindings from the first statement over to the second.
 | 
| @@ -1162,6 +1269,12 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
 | 
|    if( pFrom->nVar!=pTo->nVar ){
 | 
|      return SQLITE_ERROR;
 | 
|    }
 | 
| +  if( pTo->isPrepareV2 && pTo->expmask ){
 | 
| +    pTo->expired = 1;
 | 
| +  }
 | 
| +  if( pFrom->isPrepareV2 && pFrom->expmask ){
 | 
| +    pFrom->expired = 1;
 | 
| +  }
 | 
|    return sqlite3TransferBindings(pFromStmt, pToStmt);
 | 
|  }
 | 
|  #endif
 | 
| @@ -1177,6 +1290,14 @@ sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
 | 
|  }
 | 
|  
 | 
|  /*
 | 
| +** Return true if the prepared statement is guaranteed to not modify the
 | 
| +** database.
 | 
| +*/
 | 
| +int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
 | 
| +  return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
 | 
| +}
 | 
| +
 | 
| +/*
 | 
|  ** Return a pointer to the next prepared statement after pStmt associated
 | 
|  ** with database connection pDb.  If pStmt is NULL, return the first
 | 
|  ** prepared statement for the database connection.  Return NULL if there
 | 
| 
 |