/ Check-in [92f26a8b]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Changes to savepoint in virtual tables for simpler and more consistent operation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 92f26a8b8f18832cb1f8ba7dd8e5b020e71a5883
User & Date: drh 2011-05-25 01:16:42
Context
2011-05-25
15:54
Fix a compiler warning. check-in: 6df99e52 user: drh tags: trunk
01:16
Changes to savepoint in virtual tables for simpler and more consistent operation. check-in: 92f26a8b user: drh tags: trunk
2011-05-24
15:36
Do not invoke the xRollbackTo or xRelease methods of a virtual table without having first invoked an appropriate xSavepoint method. Add assert() statements to FTS3/4 to verify that this is happening in all cases. check-in: 651ef242 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  3670   3670     TESTONLY( p->mxSavepoint = iSavepoint );
  3671   3671     return sqlite3Fts3PendingTermsFlush(p);
  3672   3672   }
  3673   3673   static int fts3ReleaseMethod(sqlite3_vtab *pVtab, int iSavepoint){
  3674   3674     TESTONLY( Fts3Table *p = (Fts3Table*)pVtab );
  3675   3675     assert( p->inTransaction );
  3676   3676     assert( p->mxSavepoint >= iSavepoint );
  3677         -  TESTONLY( p->mxSavepoint = iSavepoint>0 ? iSavepoint-1 : 0 );
         3677  +  TESTONLY( p->mxSavepoint = iSavepoint-1 );
  3678   3678     return SQLITE_OK;
  3679   3679   }
  3680   3680   static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
  3681   3681     Fts3Table *p = (Fts3Table*)pVtab;
  3682   3682     assert( p->inTransaction );
  3683   3683     assert( p->mxSavepoint >= iSavepoint );
  3684   3684     TESTONLY( p->mxSavepoint = iSavepoint );

Changes to src/sqliteInt.h.

  1231   1231   */
  1232   1232   struct VTable {
  1233   1233     sqlite3 *db;              /* Database connection associated with this table */
  1234   1234     Module *pMod;             /* Pointer to module implementation */
  1235   1235     sqlite3_vtab *pVtab;      /* Pointer to vtab instance */
  1236   1236     int nRef;                 /* Number of pointers to this structure */
  1237   1237     u8 bConstraint;           /* True if constraints are supported */
  1238         -  u8 bInSavepoint;          /* True if within a SAVEPOINT */
         1238  +  u32 iSavepoint;           /* Depth of the SAVEPOINT stack */
  1239   1239     VTable *pNext;            /* Next in linked list (see above) */
  1240   1240   };
  1241   1241   
  1242   1242   /*
  1243   1243   ** Each SQL table is represented in memory by an instance of the
  1244   1244   ** following structure.
  1245   1245   **

Changes to src/vdbe.c.

  2836   2836         assert( sqlite3BtreeIsInTrans(pBt) );
  2837   2837         if( p->iStatement==0 ){
  2838   2838           assert( db->nStatement>=0 && db->nSavepoint>=0 );
  2839   2839           db->nStatement++; 
  2840   2840           p->iStatement = db->nSavepoint + db->nStatement;
  2841   2841         }
  2842   2842   
  2843         -      rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement);
         2843  +      rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
  2844   2844         if( rc==SQLITE_OK ){
  2845   2845           rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
  2846   2846         }
  2847   2847   
  2848   2848         /* Store the current value of the database handles deferred constraint
  2849   2849         ** counter. If the statement transaction needs to be rolled back,
  2850   2850         ** the value of this counter needs to be restored too.  */

Changes to src/vdbeaux.c.

  2198   2198       }
  2199   2199     
  2200   2200       /* If eStatementOp is non-zero, then a statement transaction needs to
  2201   2201       ** be committed or rolled back. Call sqlite3VdbeCloseStatement() to
  2202   2202       ** do so. If this operation returns an error, and the current statement
  2203   2203       ** error code is SQLITE_OK or SQLITE_CONSTRAINT, then promote the
  2204   2204       ** current statement error code.
  2205         -    **
  2206         -    ** Note that sqlite3VdbeCloseStatement() can only fail if eStatementOp
  2207         -    ** is SAVEPOINT_ROLLBACK.  But if p->rc==SQLITE_OK then eStatementOp
  2208         -    ** must be SAVEPOINT_RELEASE.  Hence the NEVER(p->rc==SQLITE_OK) in 
  2209         -    ** the following code.
  2210   2205       */
  2211   2206       if( eStatementOp ){
  2212   2207         rc = sqlite3VdbeCloseStatement(p, eStatementOp);
  2213   2208         if( rc ){
  2214         -        assert( eStatementOp==SAVEPOINT_ROLLBACK );
  2215         -        if( NEVER(p->rc==SQLITE_OK) || p->rc==SQLITE_CONSTRAINT ){
         2209  +        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
  2216   2210             p->rc = rc;
  2217   2211             sqlite3DbFree(db, p->zErrMsg);
  2218   2212             p->zErrMsg = 0;
  2219   2213           }
  2220   2214           invalidateCursorsOnModifiedBtrees(db);
  2221   2215           sqlite3RollbackAll(db);
  2222   2216           sqlite3CloseSavepoints(db);

Changes to src/vtab.c.

   749    749         VTable *pVTab = db->aVTrans[i];
   750    750         sqlite3_vtab *p = pVTab->pVtab;
   751    751         if( p ){
   752    752           int (*x)(sqlite3_vtab *);
   753    753           x = *(int (**)(sqlite3_vtab *))((char *)p->pModule + offset);
   754    754           if( x ) x(p);
   755    755         }
          756  +      pVTab->iSavepoint = 0;
   756    757         sqlite3VtabUnlock(pVTab);
   757    758       }
   758    759       sqlite3DbFree(db, db->aVTrans);
   759    760       db->nVTrans = 0;
   760    761       db->aVTrans = 0;
   761    762     }
   762    763   }
................................................................................
   866    867   ** function immediately. If all calls to virtual table methods are successful,
   867    868   ** SQLITE_OK is returned.
   868    869   */
   869    870   int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
   870    871     int rc = SQLITE_OK;
   871    872   
   872    873     assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
          874  +  assert( iSavepoint>=0 );
   873    875     if( db->aVTrans ){
   874    876       int i;
   875    877       for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
   876    878         VTable *pVTab = db->aVTrans[i];
   877    879         const sqlite3_module *pMod = pVTab->pMod->pModule;
   878         -      if( pMod->iVersion>=2 && (pVTab->bInSavepoint || op==SAVEPOINT_BEGIN) ){
          880  +      if( pMod->iVersion>=2 ){
   879    881           int (*xMethod)(sqlite3_vtab *, int);
   880    882           switch( op ){
   881    883             case SAVEPOINT_BEGIN:
   882    884               xMethod = pMod->xSavepoint;
   883         -            pVTab->bInSavepoint = 1;
          885  +            pVTab->iSavepoint = iSavepoint+1;
   884    886               break;
   885    887             case SAVEPOINT_ROLLBACK:
   886    888               xMethod = pMod->xRollbackTo;
   887    889               break;
   888    890             default:
   889    891               xMethod = pMod->xRelease;
   890    892               break;
   891    893           }
   892         -        if( xMethod ) rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
          894  +        if( xMethod && pVTab->iSavepoint>iSavepoint ){
          895  +          rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
          896  +        }
   893    897         }
   894    898       }
   895    899     }
   896    900     return rc;
   897    901   }
   898    902   
   899    903   /*