⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdbeaux.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
      p->nMem = nMem;      p->aVar = &p->aMem[nMem];      p->nVar = nVar;      p->okVar = 0;      p->apArg = (Mem**)&p->aVar[nVar];      p->azVar = (char**)&p->apArg[nArg];      p->apCsr = (Cursor**)&p->azVar[nVar];      p->nCursor = nCursor;      for(n=0; n<nVar; n++){        p->aVar[n].flags = MEM_Null;      }    }  }  for(n=0; n<p->nMem; n++){    p->aMem[n].flags = MEM_Null;  }  p->pTos = &p->aStack[-1];  p->pc = -1;  p->rc = SQLITE_OK;  p->uniqueCnt = 0;  p->returnDepth = 0;  p->errorAction = OE_Abort;  p->popStack =  0;  p->explain |= isExplain;  p->magic = VDBE_MAGIC_RUN;  p->nChange = 0;  p->cacheCtr = 1;  p->minWriteFileFormat = 255;  p->openedStatement = 0;#ifdef VDBE_PROFILE  {    int i;    for(i=0; i<p->nOp; i++){      p->aOp[i].cnt = 0;      p->aOp[i].cycles = 0;    }  }#endif}/*** Close a cursor and release all the resources that cursor happens** to hold.*/void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){  if( pCx==0 ){    return;  }  if( pCx->pCursor ){    sqlite3BtreeCloseCursor(pCx->pCursor);  }  if( pCx->pBt ){    sqlite3BtreeClose(pCx->pBt);  }#ifndef SQLITE_OMIT_VIRTUALTABLE  if( pCx->pVtabCursor ){    sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;    const sqlite3_module *pModule = pCx->pModule;    p->inVtabMethod = 1;    sqlite3SafetyOff(p->db);    pModule->xClose(pVtabCursor);    sqlite3SafetyOn(p->db);    p->inVtabMethod = 0;  }#endif  sqliteFree(pCx->pData);  sqliteFree(pCx->aType);  sqliteFree(pCx);}/*** Close all cursors*/static void closeAllCursors(Vdbe *p){  int i;  if( p->apCsr==0 ) return;  for(i=0; i<p->nCursor; i++){    if( !p->inVtabMethod || (p->apCsr[i] && !p->apCsr[i]->pVtabCursor) ){      sqlite3VdbeFreeCursor(p, p->apCsr[i]);      p->apCsr[i] = 0;    }  }}/*** Clean up the VM after execution.**** This routine will automatically close any cursors, lists, and/or** sorters that were left open.  It also deletes the values of** variables in the aVar[] array.*/static void Cleanup(Vdbe *p){  int i;  if( p->aStack ){    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));    p->pTos = &p->aStack[-1];  }  closeAllCursors(p);  releaseMemArray(p->aMem, p->nMem);  sqlite3VdbeFifoClear(&p->sFifo);  if( p->contextStack ){    for(i=0; i<p->contextStackTop; i++){      sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);    }    sqliteFree(p->contextStack);  }  p->contextStack = 0;  p->contextStackDepth = 0;  p->contextStackTop = 0;  sqliteFree(p->zErrMsg);  p->zErrMsg = 0;  p->resOnStack = 0;}/*** Set the number of result columns that will be returned by this SQL** statement. This is now set at compile time, rather than during** execution of the vdbe program so that sqlite3_column_count() can** be called on an SQL statement before sqlite3_step().*/void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){  Mem *pColName;  int n;  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);  sqliteFree(p->aColName);  n = nResColumn*COLNAME_N;  p->nResColumn = nResColumn;  p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n );  if( p->aColName==0 ) return;  while( n-- > 0 ){    (pColName++)->flags = MEM_Null;  }}/*** Set the name of the idx'th column to be returned by the SQL statement.** zName must be a pointer to a nul terminated string.**** This call must be made after a call to sqlite3VdbeSetNumCols().**** If N==P3_STATIC  it means that zName is a pointer to a constant static** string and we can just copy the pointer. If it is P3_DYNAMIC, then ** the string is freed using sqliteFree() when the vdbe is finished with** it. Otherwise, N bytes of zName are copied.*/int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){  int rc;  Mem *pColName;  assert( idx<p->nResColumn );  assert( var<COLNAME_N );  if( sqlite3MallocFailed() ) return SQLITE_NOMEM;  assert( p->aColName!=0 );  pColName = &(p->aColName[idx+var*p->nResColumn]);  if( N==P3_DYNAMIC || N==P3_STATIC ){    rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC);  }else{    rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT);  }  if( rc==SQLITE_OK && N==P3_DYNAMIC ){    pColName->flags = (pColName->flags&(~MEM_Static))|MEM_Dyn;    pColName->xDel = 0;  }  return rc;}/*** A read or write transaction may or may not be active on database handle** db. If a transaction is active, commit it. If there is a** write-transaction spanning more than one database file, this routine** takes care of the master journal trickery.*/static int vdbeCommit(sqlite3 *db){  int i;  int nTrans = 0;  /* Number of databases with an active write-transaction */  int rc = SQLITE_OK;  int needXcommit = 0;  /* Before doing anything else, call the xSync() callback for any  ** virtual module tables written in this transaction. This has to  ** be done before determining whether a master journal file is   ** required, as an xSync() callback may add an attached database  ** to the transaction.  */  rc = sqlite3VtabSync(db, rc);  if( rc!=SQLITE_OK ){    return rc;  }  /* This loop determines (a) if the commit hook should be invoked and  ** (b) how many database files have open write transactions, not   ** including the temp database. (b) is important because if more than   ** one database file has an open write transaction, a master journal  ** file is required for an atomic commit.  */   for(i=0; i<db->nDb; i++){     Btree *pBt = db->aDb[i].pBt;    if( pBt && sqlite3BtreeIsInTrans(pBt) ){      needXcommit = 1;      if( i!=1 ) nTrans++;    }  }  /* If there are any write-transactions at all, invoke the commit hook */  if( needXcommit && db->xCommitCallback ){    sqlite3SafetyOff(db);    rc = db->xCommitCallback(db->pCommitArg);    sqlite3SafetyOn(db);    if( rc ){      return SQLITE_CONSTRAINT;    }  }  /* The simple case - no more than one database file (not counting the  ** TEMP database) has a transaction active.   There is no need for the  ** master-journal.  **  ** If the return value of sqlite3BtreeGetFilename() is a zero length  ** string, it means the main database is :memory:.  In that case we do  ** not support atomic multi-file commits, so use the simple case then  ** too.  */  if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt ){        rc = sqlite3BtreeCommitPhaseOne(pBt, 0);      }    }    /* Do the commit only if all databases successfully complete phase 1.     ** If one of the BtreeCommitPhaseOne() calls fails, this indicates an    ** IO error while deleting or truncating a journal file. It is unlikely,    ** but could happen. In this case abandon processing and return the error.    */    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){      Btree *pBt = db->aDb[i].pBt;      if( pBt ){        rc = sqlite3BtreeCommitPhaseTwo(pBt);      }    }    if( rc==SQLITE_OK ){      sqlite3VtabCommit(db);    }  }  /* The complex case - There is a multi-file write-transaction active.  ** This requires a master journal file to ensure the transaction is  ** committed atomicly.  */#ifndef SQLITE_OMIT_DISKIO  else{    int needSync = 0;    char *zMaster = 0;   /* File-name for the master journal */    char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);    OsFile *master = 0;    /* Select a master journal file name */    do {      u32 random;      sqliteFree(zMaster);      sqlite3Randomness(sizeof(random), &random);      zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random&0x7fffffff);      if( !zMaster ){        return SQLITE_NOMEM;      }    }while( sqlite3OsFileExists(zMaster) );    /* Open the master journal. */    rc = sqlite3OsOpenExclusive(zMaster, &master, 0);    if( rc!=SQLITE_OK ){      sqliteFree(zMaster);      return rc;    }     /* Write the name of each database file in the transaction into the new    ** master journal file. If an error occurs at this point close    ** and delete the master journal file. All the individual journal files    ** still have 'null' as the master journal pointer, so they will roll    ** back independently if a failure occurs.    */    for(i=0; i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( i==1 ) continue;   /* Ignore the TEMP database */      if( pBt && sqlite3BtreeIsInTrans(pBt) ){        char const *zFile = sqlite3BtreeGetJournalname(pBt);        if( zFile[0]==0 ) continue;  /* Ignore :memory: databases */        if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){          needSync = 1;        }        rc = sqlite3OsWrite(master, zFile, strlen(zFile)+1);        if( rc!=SQLITE_OK ){          sqlite3OsClose(&master);          sqlite3OsDelete(zMaster);          sqliteFree(zMaster);          return rc;        }      }    }    /* Sync the master journal file. Before doing this, open the directory    ** the master journal file is store in so that it gets synced too.    */    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);    rc = sqlite3OsOpenDirectory(master, zMainFile);    if( rc!=SQLITE_OK ||          (needSync && (rc=sqlite3OsSync(master,0))!=SQLITE_OK) ){      sqlite3OsClose(&master);      sqlite3OsDelete(zMaster);      sqliteFree(zMaster);      return rc;    }    /* Sync all the db files involved in the transaction. The same call    ** sets the master journal pointer in each individual journal. If    ** an error occurs here, do not delete the master journal file.    **    ** If the error occurs during the first call to    ** sqlite3BtreeCommitPhaseOne(), then there is a chance that the    ** master journal file will be orphaned. But we cannot delete it,    ** in case the master journal file name was written into the journal    ** file before the failure occured.    */    for(i=0; rc==SQLITE_OK && i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt && sqlite3BtreeIsInTrans(pBt) ){        rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);      }    }    sqlite3OsClose(&master);    if( rc!=SQLITE_OK ){      sqliteFree(zMaster);      return rc;    }    /* Delete the master journal file. This commits the transaction. After    ** doing this the directory is synced again before any individual    ** transaction files are deleted.    */    rc = sqlite3OsDelete(zMaster);    sqliteFree(zMaster);    zMaster = 0;    if( rc ){      return rc;    }    rc = sqlite3OsSyncDirectory(zMainFile);    if( rc!=SQLITE_OK ){      /* This is not good. The master journal file has been deleted, but      ** the directory sync failed. There is no completely safe course of      ** action from here. The individual journals contain the name of the      ** master journal file, but there is no way of knowing if that      ** master journal exists now or if it will exist after the operating      ** system crash that may follow the fsync() failure.      */      return rc;    }    /* All files and directories have already been synced, so the following    ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and    ** deleting or truncating journals. If something goes wrong while    ** this is happening we don't really care. The integrity of the    ** transaction is already guaranteed, but some stray 'cold' journals    ** may be lying around. Returning an error code won't help matters.    */    disable_simulated_io_errors();    for(i=0; i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt ){        sqlite3BtreeCommitPhaseTwo(pBt);      }    }    enable_simulated_io_errors();    sqlite3VtabCommit(db);  }#endif  return rc;}/* ** This routine checks that the sqlite3.activeVdbeCnt count variable** matches the number of vdbe's in the list sqlite3.pVdbe that are** currently active. An assertion fails if the two counts do not match.** This is an internal self-check only - it is not an essential processing** step.**** This is a no-op if NDEBUG is defined.*/#ifndef NDEBUGstatic void checkActiveVdbeCnt(sqlite3 *db){  Vdbe *p;  int cnt = 0;  p = db->pVdbe;  while( p ){    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){      cnt++;    }    p = p->pNext;  }  assert( cnt==db->activeVdbeCnt );}#else#define checkActiveVdbeCnt(x)#endif/*** Find every active VM other than pVdbe and change its status to** aborted.  This happens when one VM causes a rollback due to an** ON CONFLICT ROLLBACK clause (for example).  The other VMs must be** aborted so that they do not have data rolled out from underneath** them leading to a segfault.*/void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){  Vdbe *pOther;  for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){    if( pOther==pExcept ) continue;    if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;    checkActiveVdbeCnt(db);    closeAllCursors(pOther);    checkActiveVdbeCnt(db);    pOther->aborted = 1;  }}/*** This routine is called the when a VDBE tries to halt.  If the VDBE** has made changes and is in autocommit mode, then commit those** changes.  If a rollback is needed, then do the rollback.**** This routine is the only way to move the state of a VM from** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT.**** Return an error code.  If the commit could not complete because of** lock contention, return SQLITE_BUSY.  If SQLITE_BUSY is returned, it** means the close did not happen and needs to be repeated.*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -