/ Check-in [854ba304]
Login

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

Overview
Comment:If a virtual table xSync() returns an error message, copy it into a buffer allocated by sqlite3DbMalloc() before transfering it to Vdbe.zErrMsg.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 854ba3049005adf033e07e6740a36e63f2a56758
User & Date: dan 2013-08-21 17:35:48
Context
2013-08-21
19:13
Update sqlite3MemCompare() to try common cases first, for a modest speed improvement. check-in: b25bac79 user: drh tags: trunk
17:35
If a virtual table xSync() returns an error message, copy it into a buffer allocated by sqlite3DbMalloc() before transfering it to Vdbe.zErrMsg. check-in: 854ba304 user: dan tags: trunk
15:52
Performance enhancement in btreeParseCellPtr(). check-in: a17190a2 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

  3149   3149   #  define sqlite3VtabUnlock(X)
  3150   3150   #  define sqlite3VtabUnlockList(X)
  3151   3151   #  define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
  3152   3152   #  define sqlite3GetVTable(X,Y)  ((VTable*)0)
  3153   3153   #else
  3154   3154      void sqlite3VtabClear(sqlite3 *db, Table*);
  3155   3155      void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
  3156         -   int sqlite3VtabSync(sqlite3 *db, char **);
         3156  +   int sqlite3VtabSync(sqlite3 *db, Vdbe*);
  3157   3157      int sqlite3VtabRollback(sqlite3 *db);
  3158   3158      int sqlite3VtabCommit(sqlite3 *db);
  3159   3159      void sqlite3VtabLock(VTable *);
  3160   3160      void sqlite3VtabUnlock(VTable *);
  3161   3161      void sqlite3VtabUnlockList(sqlite3*);
  3162   3162      int sqlite3VtabSavepoint(sqlite3 *, int, int);
         3163  +   void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
  3163   3164      VTable *sqlite3GetVTable(sqlite3*, Table*);
  3164   3165   #  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
  3165   3166   #endif
  3166   3167   void sqlite3VtabMakeWritable(Parse*,Table*);
  3167   3168   void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
  3168   3169   void sqlite3VtabFinishParse(Parse*, Token*);
  3169   3170   void sqlite3VtabArgInit(Parse*);

Changes to src/vdbe.c.

   493    493     Savepoint *p;
   494    494     for(p=db->pSavepoint; p; p=p->pNext) n++;
   495    495     assert( n==(db->nSavepoint + db->isTransactionSavepoint) );
   496    496     return 1;
   497    497   }
   498    498   #endif
   499    499   
   500         -/*
   501         -** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
   502         -** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
   503         -** in memory obtained from sqlite3DbMalloc).
   504         -*/
   505         -static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
   506         -  sqlite3 *db = p->db;
   507         -  sqlite3DbFree(db, p->zErrMsg);
   508         -  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
   509         -  sqlite3_free(pVtab->zErrMsg);
   510         -  pVtab->zErrMsg = 0;
   511         -}
   512         -
   513    500   
   514    501   /*
   515    502   ** Execute as much of a VDBE program as we can then return.
   516    503   **
   517    504   ** sqlite3VdbeMakeReady() must be called before this routine in order to
   518    505   ** close the program with a final OP_Halt and to set up the callbacks
   519    506   ** and the error message pointer.
................................................................................
  4346   4333       v = pC->movetoTarget;
  4347   4334   #ifndef SQLITE_OMIT_VIRTUALTABLE
  4348   4335     }else if( pC->pVtabCursor ){
  4349   4336       pVtab = pC->pVtabCursor->pVtab;
  4350   4337       pModule = pVtab->pModule;
  4351   4338       assert( pModule->xRowid );
  4352   4339       rc = pModule->xRowid(pC->pVtabCursor, &v);
  4353         -    importVtabErrMsg(p, pVtab);
         4340  +    sqlite3VtabImportErrmsg(p, pVtab);
  4354   4341   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  4355   4342     }else{
  4356   4343       assert( pC->pCursor!=0 );
  4357   4344       rc = sqlite3VdbeCursorMoveto(pC);
  4358   4345       if( rc ) goto abort_due_to_error;
  4359   4346       if( pC->rowidIsValid ){
  4360   4347         v = pC->lastRowid;
................................................................................
  5739   5726   ** within a callback to a virtual table xSync() method. If it is, the error
  5740   5727   ** code will be set to SQLITE_LOCKED.
  5741   5728   */
  5742   5729   case OP_VBegin: {
  5743   5730     VTable *pVTab;
  5744   5731     pVTab = pOp->p4.pVtab;
  5745   5732     rc = sqlite3VtabBegin(db, pVTab);
  5746         -  if( pVTab ) importVtabErrMsg(p, pVTab->pVtab);
         5733  +  if( pVTab ) sqlite3VtabImportErrmsg(p, pVTab->pVtab);
  5747   5734     break;
  5748   5735   }
  5749   5736   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  5750   5737   
  5751   5738   #ifndef SQLITE_OMIT_VIRTUALTABLE
  5752   5739   /* Opcode: VCreate P1 * * P4 *
  5753   5740   **
................................................................................
  5790   5777     assert( p->bIsReader );
  5791   5778     pCur = 0;
  5792   5779     pVtabCursor = 0;
  5793   5780     pVtab = pOp->p4.pVtab->pVtab;
  5794   5781     pModule = (sqlite3_module *)pVtab->pModule;
  5795   5782     assert(pVtab && pModule);
  5796   5783     rc = pModule->xOpen(pVtab, &pVtabCursor);
  5797         -  importVtabErrMsg(p, pVtab);
         5784  +  sqlite3VtabImportErrmsg(p, pVtab);
  5798   5785     if( SQLITE_OK==rc ){
  5799   5786       /* Initialize sqlite3_vtab_cursor base class */
  5800   5787       pVtabCursor->pVtab = pVtab;
  5801   5788   
  5802   5789       /* Initialize vdbe cursor object */
  5803   5790       pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
  5804   5791       if( pCur ){
................................................................................
  5868   5855         apArg[i] = &pArgc[i+1];
  5869   5856         sqlite3VdbeMemStoreType(apArg[i]);
  5870   5857       }
  5871   5858   
  5872   5859       p->inVtabMethod = 1;
  5873   5860       rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
  5874   5861       p->inVtabMethod = 0;
  5875         -    importVtabErrMsg(p, pVtab);
         5862  +    sqlite3VtabImportErrmsg(p, pVtab);
  5876   5863       if( rc==SQLITE_OK ){
  5877   5864         res = pModule->xEof(pVtabCursor);
  5878   5865       }
  5879   5866   
  5880   5867       if( res ){
  5881   5868         pc = pOp->p2 - 1;
  5882   5869       }
................................................................................
  5919   5906     ** can use the already allocated buffer instead of allocating a 
  5920   5907     ** new one.
  5921   5908     */
  5922   5909     sqlite3VdbeMemMove(&sContext.s, pDest);
  5923   5910     MemSetTypeFlag(&sContext.s, MEM_Null);
  5924   5911   
  5925   5912     rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
  5926         -  importVtabErrMsg(p, pVtab);
         5913  +  sqlite3VtabImportErrmsg(p, pVtab);
  5927   5914     if( sContext.isError ){
  5928   5915       rc = sContext.isError;
  5929   5916     }
  5930   5917   
  5931   5918     /* Copy the result of the function to the P3 register. We
  5932   5919     ** do this regardless of whether or not an error occurred to ensure any
  5933   5920     ** dynamic allocation in sContext.s (a Mem struct) is  released.
................................................................................
  5972   5959     ** xNext(). Instead, if an error occurs, true is returned (indicating that 
  5973   5960     ** data is available) and the error code returned when xColumn or
  5974   5961     ** some other method is next invoked on the save virtual table cursor.
  5975   5962     */
  5976   5963     p->inVtabMethod = 1;
  5977   5964     rc = pModule->xNext(pCur->pVtabCursor);
  5978   5965     p->inVtabMethod = 0;
  5979         -  importVtabErrMsg(p, pVtab);
         5966  +  sqlite3VtabImportErrmsg(p, pVtab);
  5980   5967     if( rc==SQLITE_OK ){
  5981   5968       res = pModule->xEof(pCur->pVtabCursor);
  5982   5969     }
  5983   5970   
  5984   5971     if( !res ){
  5985   5972       /* If there is data, jump to P2 */
  5986   5973       pc = pOp->p2 - 1;
................................................................................
  6009   5996     assert( pName->flags & MEM_Str );
  6010   5997     testcase( pName->enc==SQLITE_UTF8 );
  6011   5998     testcase( pName->enc==SQLITE_UTF16BE );
  6012   5999     testcase( pName->enc==SQLITE_UTF16LE );
  6013   6000     rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
  6014   6001     if( rc==SQLITE_OK ){
  6015   6002       rc = pVtab->pModule->xRename(pVtab, pName->z);
  6016         -    importVtabErrMsg(p, pVtab);
         6003  +    sqlite3VtabImportErrmsg(p, pVtab);
  6017   6004       p->expired = 0;
  6018   6005     }
  6019   6006     break;
  6020   6007   }
  6021   6008   #endif
  6022   6009   
  6023   6010   #ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  6071   6058         sqlite3VdbeMemStoreType(pX);
  6072   6059         apArg[i] = pX;
  6073   6060         pX++;
  6074   6061       }
  6075   6062       db->vtabOnConflict = pOp->p5;
  6076   6063       rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
  6077   6064       db->vtabOnConflict = vtabOnConflict;
  6078         -    importVtabErrMsg(p, pVtab);
         6065  +    sqlite3VtabImportErrmsg(p, pVtab);
  6079   6066       if( rc==SQLITE_OK && pOp->p1 ){
  6080   6067         assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
  6081   6068         db->lastRowid = lastRowid = rowid;
  6082   6069       }
  6083   6070       if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
  6084   6071         if( pOp->p5==OE_Ignore ){
  6085   6072           rc = SQLITE_OK;

Changes to src/vdbeaux.c.

  1761   1761   
  1762   1762     /* Before doing anything else, call the xSync() callback for any
  1763   1763     ** virtual module tables written in this transaction. This has to
  1764   1764     ** be done before determining whether a master journal file is 
  1765   1765     ** required, as an xSync() callback may add an attached database
  1766   1766     ** to the transaction.
  1767   1767     */
  1768         -  rc = sqlite3VtabSync(db, &p->zErrMsg);
         1768  +  rc = sqlite3VtabSync(db, p);
  1769   1769   
  1770   1770     /* This loop determines (a) if the commit hook should be invoked and
  1771   1771     ** (b) how many database files have open write transactions, not 
  1772   1772     ** including the temp database. (b) is important because if more than 
  1773   1773     ** one database file has an open write transaction, a master journal
  1774   1774     ** file is required for an atomic commit.
  1775   1775     */ 
................................................................................
  3300   3300     assert( iVar>0 );
  3301   3301     if( iVar>32 ){
  3302   3302       v->expmask = 0xffffffff;
  3303   3303     }else{
  3304   3304       v->expmask |= ((u32)1 << (iVar-1));
  3305   3305     }
  3306   3306   }
         3307  +
         3308  +#ifndef SQLITE_OMIT_VIRTUALTABLE
         3309  +/*
         3310  +** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
         3311  +** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
         3312  +** in memory obtained from sqlite3DbMalloc).
         3313  +*/
         3314  +void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
         3315  +  sqlite3 *db = p->db;
         3316  +  sqlite3DbFree(db, p->zErrMsg);
         3317  +  p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
         3318  +  sqlite3_free(pVtab->zErrMsg);
         3319  +  pVtab->zErrMsg = 0;
         3320  +}
         3321  +#endif /* SQLITE_OMIT_VIRTUALTABLE */

Changes to src/vtab.c.

   806    806   }
   807    807   
   808    808   /*
   809    809   ** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
   810    810   ** array. Return the error code for the first error that occurs, or
   811    811   ** SQLITE_OK if all xSync operations are successful.
   812    812   **
   813         -** Set *pzErrmsg to point to a buffer that should be released using 
   814         -** sqlite3DbFree() containing an error message, if one is available.
          813  +** If an error message is available, leave it in p->zErrMsg.
   815    814   */
   816         -int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
          815  +int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
   817    816     int i;
   818    817     int rc = SQLITE_OK;
   819    818     VTable **aVTrans = db->aVTrans;
   820    819   
   821    820     db->aVTrans = 0;
   822    821     for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
   823    822       int (*x)(sqlite3_vtab *);
   824    823       sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
   825    824       if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
   826    825         rc = x(pVtab);
   827         -      sqlite3DbFree(db, *pzErrmsg);
   828         -      *pzErrmsg = pVtab->zErrMsg;
   829         -      pVtab->zErrMsg = 0;
          826  +      sqlite3VtabImportErrmsg(p, pVtab);
   830    827       }
   831    828     }
   832    829     db->aVTrans = aVTrans;
   833    830     return rc;
   834    831   }
   835    832   
   836    833   /*