/ Check-in [2f3376eb]
Login

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

Overview
Comment:Delete the OP_VerifySchema opcode. Enhance OP_Transaction to do the schema version checks that OP_VerifySchema used to do.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2f3376ebf13df44e6acf27cb1f07172cd8b34033
User & Date: drh 2014-02-06 23:56:27
Context
2014-02-07
02:29
Update comments in vdbe.c. No changes to code. check-in: 1122b410 user: drh tags: trunk
2014-02-06
23:56
Delete the OP_VerifySchema opcode. Enhance OP_Transaction to do the schema version checks that OP_VerifySchema used to do. check-in: 2f3376eb user: drh tags: trunk
13:18
Change the spellfix1 virtual table to deterministically names its shadow tables. check-in: 5219cdfc user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   465    465       pVTab = sqlite3GetVTable(db, pTab);
   466    466       if( pVTab->pVtab->pModule->xRename==0 ){
   467    467         pVTab = 0;
   468    468       }
   469    469     }
   470    470   #endif
   471    471   
   472         -  /* Begin a transaction and code the VerifyCookie for database iDb. 
          472  +  /* Begin a transaction for database iDb. 
   473    473     ** Then modify the schema cookie (since the ALTER TABLE modifies the
   474    474     ** schema). Open a statement transaction if the table is a virtual
   475    475     ** table.
   476    476     */
   477    477     v = sqlite3GetVdbe(pParse);
   478    478     if( v==0 ){
   479    479       goto exit_rename_table;

Changes to src/build.c.

   152    152       if( pParse->cookieGoto>0 ){
   153    153         yDbMask mask;
   154    154         int iDb, i, addr;
   155    155         sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
   156    156         for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
   157    157           if( (mask & pParse->cookieMask)==0 ) continue;
   158    158           sqlite3VdbeUsesBtree(v, iDb);
   159         -        sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
   160         -        if( db->init.busy==0 ){
   161         -          assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   162         -          sqlite3VdbeAddOp3(v, OP_VerifyCookie,
   163         -                            iDb, pParse->cookieValue[iDb],
   164         -                            db->aDb[iDb].pSchema->iGeneration);
   165         -        }
          159  +        sqlite3VdbeAddOp4Int(v,
          160  +          OP_Transaction,                    /* Opcode */
          161  +          iDb,                               /* P1 */
          162  +          (mask & pParse->writeMask)!=0,     /* P2 */
          163  +          pParse->cookieValue[iDb],          /* P3 */
          164  +          db->aDb[iDb].pSchema->iGeneration  /* P4 */
          165  +        );
          166  +        if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
   166    167         }
   167    168   #ifndef SQLITE_OMIT_VIRTUALTABLE
   168    169         for(i=0; i<pParse->nVtabLock; i++){
   169    170           char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
   170    171           sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
   171    172         }
   172    173         pParse->nVtabLock = 0;

Changes to src/expr.c.

  1580   1580       assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
  1581   1581       assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
  1582   1582       assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
  1583   1583       pTab = p->pSrc->a[0].pTab;
  1584   1584       pExpr = p->pEList->a[0].pExpr;
  1585   1585       iCol = (i16)pExpr->iColumn;
  1586   1586      
  1587         -    /* Code an OP_VerifyCookie and OP_TableLock for <table>. */
         1587  +    /* Code an OP_Transaction and OP_TableLock for <table>. */
  1588   1588       iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  1589   1589       sqlite3CodeVerifySchema(pParse, iDb);
  1590   1590       sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
  1591   1591   
  1592   1592       /* This function is only called from two places. In both cases the vdbe
  1593   1593       ** has already been allocated. So assume sqlite3GetVdbe() is always
  1594   1594       ** successful here.

Changes to src/vdbe.c.

  2942   2942                      "cannot commit - no transaction is active"));
  2943   2943            
  2944   2944       rc = SQLITE_ERROR;
  2945   2945     }
  2946   2946     break;
  2947   2947   }
  2948   2948   
  2949         -/* Opcode: Transaction P1 P2 * * *
         2949  +/* Opcode: Transaction P1 P2 P3 P4 P5
  2950   2950   **
  2951   2951   ** Begin a transaction.  The transaction ends when a Commit or Rollback
  2952   2952   ** opcode is encountered.  Depending on the ON CONFLICT setting, the
  2953   2953   ** transaction might also be rolled back if an error is encountered.
  2954   2954   **
  2955   2955   ** P1 is the index of the database file on which the transaction is
  2956   2956   ** started.  Index 0 is the main database file and index 1 is the
................................................................................
  2972   2972   ** connection is currently not in autocommit mode, or if there are other
  2973   2973   ** active statements. A statement transaction allows the changes made by this
  2974   2974   ** VDBE to be rolled back after an error without having to roll back the
  2975   2975   ** entire transaction. If no error is encountered, the statement transaction
  2976   2976   ** will automatically commit when the VDBE halts.
  2977   2977   **
  2978   2978   ** If P2 is zero, then a read-lock is obtained on the database file.
         2979  +**
         2980  +** If P5!=0 then this opcode also checks the schema cookie against P3
         2981  +** and the schema generation counter against P4.
         2982  +** The cookie changes its value whenever the database schema changes.
         2983  +** This operation is used to detect when that the cookie has changed
         2984  +** and that the current process needs to reread the schema.
  2979   2985   */
  2980   2986   case OP_Transaction: {
  2981   2987     Btree *pBt;
         2988  +  int iMeta;
         2989  +  int iGen;
  2982   2990   
  2983   2991     assert( p->bIsReader );
  2984   2992     assert( p->readOnly==0 || pOp->p2==0 );
  2985   2993     assert( pOp->p1>=0 && pOp->p1<db->nDb );
  2986   2994     assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  2987   2995     if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
  2988   2996       rc = SQLITE_READONLY;
................................................................................
  3018   3026   
  3019   3027         /* Store the current value of the database handles deferred constraint
  3020   3028         ** counter. If the statement transaction needs to be rolled back,
  3021   3029         ** the value of this counter needs to be restored too.  */
  3022   3030         p->nStmtDefCons = db->nDeferredCons;
  3023   3031         p->nStmtDefImmCons = db->nDeferredImmCons;
  3024   3032       }
         3033  +
         3034  +    /* Gather the schema version number for checking */
         3035  +    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
         3036  +    iGen = db->aDb[pOp->p1].pSchema->iGeneration;
         3037  +  }else{
         3038  +    iGen = iMeta = 0;
         3039  +  }
         3040  +  assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
         3041  +  if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
         3042  +    sqlite3DbFree(db, p->zErrMsg);
         3043  +    p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
         3044  +    /* If the schema-cookie from the database file matches the cookie 
         3045  +    ** stored with the in-memory representation of the schema, do
         3046  +    ** not reload the schema from the database file.
         3047  +    **
         3048  +    ** If virtual-tables are in use, this is not just an optimization.
         3049  +    ** Often, v-tables store their data in other SQLite tables, which
         3050  +    ** are queried from within xNext() and other v-table methods using
         3051  +    ** prepared queries. If such a query is out-of-date, we do not want to
         3052  +    ** discard the database schema, as the user code implementing the
         3053  +    ** v-table would have to be ready for the sqlite3_vtab structure itself
         3054  +    ** to be invalidated whenever sqlite3_step() is called from within 
         3055  +    ** a v-table method.
         3056  +    */
         3057  +    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
         3058  +      sqlite3ResetOneSchema(db, pOp->p1);
         3059  +    }
         3060  +    p->expired = 1;
         3061  +    rc = SQLITE_SCHEMA;
  3025   3062     }
  3026   3063     break;
  3027   3064   }
  3028   3065   
  3029   3066   /* Opcode: ReadCookie P1 P2 P3 * *
  3030   3067   **
  3031   3068   ** Read cookie number P3 from database P1 and write it into register P2.
................................................................................
  3089   3126     }
  3090   3127     if( pOp->p1==1 ){
  3091   3128       /* Invalidate all prepared statements whenever the TEMP database
  3092   3129       ** schema is changed.  Ticket #1644 */
  3093   3130       sqlite3ExpirePreparedStatements(db);
  3094   3131       p->expired = 0;
  3095   3132     }
  3096         -  break;
  3097         -}
  3098         -
  3099         -/* Opcode: VerifyCookie P1 P2 P3 * *
  3100         -**
  3101         -** Check the value of global database parameter number 0 (the
  3102         -** schema version) and make sure it is equal to P2 and that the
  3103         -** generation counter on the local schema parse equals P3.
  3104         -**
  3105         -** P1 is the database number which is 0 for the main database file
  3106         -** and 1 for the file holding temporary tables and some higher number
  3107         -** for auxiliary databases.
  3108         -**
  3109         -** The cookie changes its value whenever the database schema changes.
  3110         -** This operation is used to detect when that the cookie has changed
  3111         -** and that the current process needs to reread the schema.
  3112         -**
  3113         -** Either a transaction needs to have been started or an OP_Open needs
  3114         -** to be executed (to establish a read lock) before this opcode is
  3115         -** invoked.
  3116         -*/
  3117         -case OP_VerifyCookie: {
  3118         -  int iMeta;
  3119         -  int iGen;
  3120         -  Btree *pBt;
  3121         -
  3122         -  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  3123         -  assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
  3124         -  assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
  3125         -  assert( p->bIsReader );
  3126         -  pBt = db->aDb[pOp->p1].pBt;
  3127         -  if( pBt ){
  3128         -    sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
  3129         -    iGen = db->aDb[pOp->p1].pSchema->iGeneration;
  3130         -  }else{
  3131         -    iGen = iMeta = 0;
  3132         -  }
  3133         -  if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){
  3134         -    sqlite3DbFree(db, p->zErrMsg);
  3135         -    p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
  3136         -    /* If the schema-cookie from the database file matches the cookie 
  3137         -    ** stored with the in-memory representation of the schema, do
  3138         -    ** not reload the schema from the database file.
  3139         -    **
  3140         -    ** If virtual-tables are in use, this is not just an optimization.
  3141         -    ** Often, v-tables store their data in other SQLite tables, which
  3142         -    ** are queried from within xNext() and other v-table methods using
  3143         -    ** prepared queries. If such a query is out-of-date, we do not want to
  3144         -    ** discard the database schema, as the user code implementing the
  3145         -    ** v-table would have to be ready for the sqlite3_vtab structure itself
  3146         -    ** to be invalidated whenever sqlite3_step() is called from within 
  3147         -    ** a v-table method.
  3148         -    */
  3149         -    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
  3150         -      sqlite3ResetOneSchema(db, pOp->p1);
  3151         -    }
  3152         -
  3153         -    p->expired = 1;
  3154         -    rc = SQLITE_SCHEMA;
  3155         -  }
  3156   3133     break;
  3157   3134   }
  3158   3135   
  3159   3136   /* Opcode: OpenRead P1 P2 P3 P4 P5
  3160   3137   ** Synopsis: root=P2 iDb=P3
  3161   3138   **
  3162   3139   ** Open a read-only cursor for the database table whose root page is

Changes to src/vdbeblob.c.

   130    130     ** blob_bytes() functions.
   131    131     **
   132    132     ** The sqlite3_blob_close() function finalizes the vdbe program,
   133    133     ** which closes the b-tree cursor and (possibly) commits the 
   134    134     ** transaction.
   135    135     */
   136    136     static const VdbeOpList openBlob[] = {
   137         -    {OP_Transaction, 0, 0, 0},     /* 0: Start a transaction */
   138         -    {OP_VerifyCookie, 0, 0, 0},    /* 1: Check the schema cookie */
   139         -    {OP_TableLock, 0, 0, 0},       /* 2: Acquire a read or write lock */
          137  +    /* {OP_Transaction, 0, 0, 0},  // 0: Inserted separately */
          138  +    {OP_TableLock, 0, 0, 0},       /* 1: Acquire a read or write lock */
   140    139   
   141    140       /* One of the following two instructions is replaced by an OP_Noop. */
   142         -    {OP_OpenRead, 0, 0, 0},        /* 3: Open cursor 0 for reading */
   143         -    {OP_OpenWrite, 0, 0, 0},       /* 4: Open cursor 0 for read/write */
          141  +    {OP_OpenRead, 0, 0, 0},        /* 2: Open cursor 0 for reading */
          142  +    {OP_OpenWrite, 0, 0, 0},       /* 3: Open cursor 0 for read/write */
   144    143   
   145         -    {OP_Variable, 1, 1, 1},        /* 5: Push the rowid to the stack */
   146         -    {OP_NotExists, 0, 10, 1},      /* 6: Seek the cursor */
   147         -    {OP_Column, 0, 0, 1},          /* 7  */
   148         -    {OP_ResultRow, 1, 0, 0},       /* 8  */
   149         -    {OP_Goto, 0, 5, 0},            /* 9  */
   150         -    {OP_Close, 0, 0, 0},           /* 10 */
   151         -    {OP_Halt, 0, 0, 0},            /* 11 */
          144  +    {OP_Variable, 1, 1, 1},        /* 4: Push the rowid to the stack */
          145  +    {OP_NotExists, 0, 10, 1},      /* 5: Seek the cursor */
          146  +    {OP_Column, 0, 0, 1},          /* 6  */
          147  +    {OP_ResultRow, 1, 0, 0},       /* 7  */
          148  +    {OP_Goto, 0, 4, 0},            /* 8  */
          149  +    {OP_Close, 0, 0, 0},           /* 9  */
          150  +    {OP_Halt, 0, 0, 0},            /* 10 */
   152    151     };
   153    152   
   154    153     int rc = SQLITE_OK;
   155    154     char *zErr = 0;
   156    155     Table *pTab;
   157    156     Parse *pParse = 0;
   158    157     Incrblob *pBlob = 0;
................................................................................
   257    256   
   258    257       pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
   259    258       assert( pBlob->pStmt || db->mallocFailed );
   260    259       if( pBlob->pStmt ){
   261    260         Vdbe *v = (Vdbe *)pBlob->pStmt;
   262    261         int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
   263    262   
          263  +
          264  +      sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, 
          265  +                           pTab->pSchema->schema_cookie,
          266  +                           pTab->pSchema->iGeneration);
          267  +      sqlite3VdbeChangeP5(v, 1);     
   264    268         sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
   265    269   
   266         -
   267         -      /* Configure the OP_Transaction */
   268         -      sqlite3VdbeChangeP1(v, 0, iDb);
   269         -      sqlite3VdbeChangeP2(v, 0, flags);
   270         -
   271         -      /* Configure the OP_VerifyCookie */
   272         -      sqlite3VdbeChangeP1(v, 1, iDb);
   273         -      sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
   274         -      sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
   275         -
   276    270         /* Make sure a mutex is held on the table to be accessed */
   277    271         sqlite3VdbeUsesBtree(v, iDb); 
   278    272   
   279    273         /* Configure the OP_TableLock instruction */
   280    274   #ifdef SQLITE_OMIT_SHARED_CACHE
   281         -      sqlite3VdbeChangeToNoop(v, 2);
          275  +      sqlite3VdbeChangeToNoop(v, 1);
   282    276   #else
   283         -      sqlite3VdbeChangeP1(v, 2, iDb);
   284         -      sqlite3VdbeChangeP2(v, 2, pTab->tnum);
   285         -      sqlite3VdbeChangeP3(v, 2, flags);
   286         -      sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
          277  +      sqlite3VdbeChangeP1(v, 1, iDb);
          278  +      sqlite3VdbeChangeP2(v, 1, pTab->tnum);
          279  +      sqlite3VdbeChangeP3(v, 1, flags);
          280  +      sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
   287    281   #endif
   288    282   
   289    283         /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
   290    284         ** parameter of the other to pTab->tnum.  */
   291         -      sqlite3VdbeChangeToNoop(v, 4 - flags);
   292         -      sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
   293         -      sqlite3VdbeChangeP3(v, 3 + flags, iDb);
          285  +      sqlite3VdbeChangeToNoop(v, 3 - flags);
          286  +      sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
          287  +      sqlite3VdbeChangeP3(v, 2 + flags, iDb);
   294    288   
   295    289         /* Configure the number of columns. Configure the cursor to
   296    290         ** think that the table has one more column than it really
   297    291         ** does. An OP_Column to retrieve this imaginary column will
   298    292         ** always return an SQL NULL. This is useful because it means
   299    293         ** we can invoke OP_Column to fill in the vdbe cursors type 
   300    294         ** and offset cache without causing any IO.
   301    295         */
   302         -      sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
   303         -      sqlite3VdbeChangeP2(v, 7, pTab->nCol);
          296  +      sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
          297  +      sqlite3VdbeChangeP2(v, 6, pTab->nCol);
   304    298         if( !db->mallocFailed ){
   305    299           pParse->nVar = 1;
   306    300           pParse->nMem = 1;
   307    301           pParse->nTab = 1;
   308    302           sqlite3VdbeMakeReady(v, pParse);
   309    303         }
   310    304       }