SQLite

Check-in [b6e268fce1]
Login

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

Overview
Comment:The changes to fix [f7b4edece25c9948] mean that the schema is always loaded whenever a prepared statement is running. This means that a couple of branches can be eliminated and one operand of OP_ParseSchema can be removed.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b6e268fce12829f058f1dfa223731ec8479493f8
User & Date: drh 2011-03-24 01:34:03.589
Context
2011-03-24
17:37
Fix problem with tableapi.test on Windows. (check-in: 69fe0c873d user: shaneh tags: trunk)
01:34
The changes to fix [f7b4edece25c9948] mean that the schema is always loaded whenever a prepared statement is running. This means that a couple of branches can be eliminated and one operand of OP_ParseSchema can be removed. (check-in: b6e268fce1 user: drh tags: trunk)
2011-03-23
22:54
Fix a signed/unsigned comparison compiler warning. (check-in: c81da6f98d user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
  Index *pIndex;
  int len;
  Hash *pHash = &db->aDb[iDb].pSchema->idxHash;

  len = sqlite3Strlen30(zIdxName);
  pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
  if( pIndex ){
    if( pIndex->pTable->pIndex==pIndex ){
      pIndex->pTable->pIndex = pIndex->pNext;
    }else{
      Index *p;
      /* Justification of ALWAYS();  The index must be on the list of
      ** indices. */
      p = pIndex->pTable->pIndex;







|







364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
  Index *pIndex;
  int len;
  Hash *pHash = &db->aDb[iDb].pSchema->idxHash;

  len = sqlite3Strlen30(zIdxName);
  pIndex = sqlite3HashInsert(pHash, zIdxName, len, 0);
  if( ALWAYS(pIndex) ){
    if( pIndex->pTable->pIndex==pIndex ){
      pIndex->pTable->pIndex = pIndex->pNext;
    }else{
      Index *p;
      /* Justification of ALWAYS();  The index must be on the list of
      ** indices. */
      p = pIndex->pTable->pIndex;
Changes to src/vdbe.c.
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
    flags = BTREE_BLOBKEY;
  }
  rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
  pOut->u.i = pgno;
  break;
}

/* Opcode: ParseSchema P1 P2 * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4.  P2 is the "force" flag.   Always do
** the parsing if P2 is true.  If P2 is false, then this routine is a
** no-op if the schema is not currently loaded.  In other words, if P2
** is false, the SQLITE_MASTER table is only parsed if the rest of the
** schema is already loaded into the symbol table.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );

  /* If pOp->p2 is 0, then this opcode is being executed to read a
  ** single row, for example the row corresponding to a new index
  ** created by this VDBE, from the sqlite_master table. It only
  ** does this if the corresponding in-memory schema is currently
  ** loaded. Otherwise, the new index definition can be loaded along
  ** with the rest of the schema when it is required.
  **
  ** Although the mutex on the BtShared object that corresponds to
  ** database iDb (the database containing the sqlite_master table
  ** read by this instruction) is currently held, it is necessary to
  ** obtain the mutexes on all attached databases before checking if
  ** the schema of iDb is loaded. This is because, at the start of
  ** the sqlite3_exec() call below, SQLite will invoke 
  ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the
  ** iDb mutex may be temporarily released to avoid deadlock. If 
  ** this happens, then some other thread may delete the in-memory 
  ** schema of database iDb before the SQL statement runs. The schema
  ** will not be reloaded becuase the db->init.busy flag is set. This
  ** can result in a "no such table: sqlite_master" or "malformed
  ** database schema" error being returned to the user.
  */
  assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  sqlite3BtreeEnterAll(db);
  if( pOp->p2 || DbHasProperty(db, iDb, DB_SchemaLoaded) ){
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zName, zMaster, pOp->p4.z);







|


|
<
<
<
<













<
<
<
<
<
<
<
|















|







4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614




4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627







4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
    flags = BTREE_BLOBKEY;
  }
  rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
  pOut->u.i = pgno;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 




**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );








  /* Although the mutex on the BtShared object that corresponds to
  ** database iDb (the database containing the sqlite_master table
  ** read by this instruction) is currently held, it is necessary to
  ** obtain the mutexes on all attached databases before checking if
  ** the schema of iDb is loaded. This is because, at the start of
  ** the sqlite3_exec() call below, SQLite will invoke 
  ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the
  ** iDb mutex may be temporarily released to avoid deadlock. If 
  ** this happens, then some other thread may delete the in-memory 
  ** schema of database iDb before the SQL statement runs. The schema
  ** will not be reloaded becuase the db->init.busy flag is set. This
  ** can result in a "no such table: sqlite_master" or "malformed
  ** database schema" error being returned to the user.
  */
  assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  sqlite3BtreeEnterAll(db);
  if( ALWAYS(DbHasProperty(db, iDb, DB_SchemaLoaded)) ){
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zName, zMaster, pOp->p4.z);
Changes to src/vtab.c.
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
    );
    sqlite3DbFree(db, zStmt);
    v = sqlite3GetVdbe(pParse);
    sqlite3ChangeCookie(pParse, iDb);

    sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
    zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC);
    sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, 
                         pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
  }

  /* If we are rereading the sqlite_master table create the in-memory
  ** record of the table. The xConnect() method is not called until
  ** the first time the virtual table is used in an SQL statement. This







|







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
    );
    sqlite3DbFree(db, zStmt);
    v = sqlite3GetVdbe(pParse);
    sqlite3ChangeCookie(pParse, iDb);

    sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
    zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
    sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0, 
                         pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
  }

  /* If we are rereading the sqlite_master table create the in-memory
  ** record of the table. The xConnect() method is not called until
  ** the first time the virtual table is used in an SQL statement. This