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

📄 vdbeaux.c

📁 调用sqlite开源数据的小程序
💻 C
📖 第 1 页 / 共 4 页
字号:
  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 ){    int rc;    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 = sqlite3BtreeSync(pBt, 0);      }    }    /* Do the commit only if all databases successfully synced */    if( rc==SQLITE_OK ){      for(i=0; i<db->nDb; i++){        Btree *pBt = db->aDb[i].pBt;        if( pBt ){          sqlite3BtreeCommit(pBt);        }      }    }  }  /* 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;    /* 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. */    memset(&master, 0, sizeof(master));    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(zMainFile, &master);    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 sqlite3BtreeSync(),    ** 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; i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt && sqlite3BtreeIsInTrans(pBt) ){        rc = sqlite3BtreeSync(pBt, zMaster);        if( rc!=SQLITE_OK ){          sqlite3OsClose(&master);          sqliteFree(zMaster);          return rc;        }      }    }    sqlite3OsClose(&master);    /* 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);    assert( rc==SQLITE_OK );    sqliteFree(zMaster);    zMaster = 0;    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 sqlite3BtreeCommit() are only closing files and deleting    ** 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.    */    for(i=0; i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt ){        sqlite3BtreeCommit(pBt);      }    }  }#endif  return rc;}/*** 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.*/static void abortOtherActiveVdbes(Vdbe *pVdbe){  Vdbe *pOther;  for(pOther=pVdbe->db->pVdbe; pOther; pOther=pOther->pNext){    if( pOther==pVdbe ) continue;    if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;    closeAllCursors(pOther);    pOther->aborted = 1;  }}/* ** 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/*** 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.*/int sqlite3VdbeHalt(Vdbe *p){  sqlite3 *db = p->db;  int i;  int (*xFunc)(Btree *pBt) = 0;  /* Function to call on each btree backend */  if( p->magic!=VDBE_MAGIC_RUN ){    /* Already halted.  Nothing to do. */    assert( p->magic==VDBE_MAGIC_HALT );    return SQLITE_OK;  }  closeAllCursors(p);  checkActiveVdbeCnt(db);  if( p->pc<0 ){    /* No commit or rollback needed if the program never started */  }else if( db->autoCommit && db->activeVdbeCnt==1 ){    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){      /* The auto-commit flag is true, there are no other active queries      ** using this handle and the vdbe program was successful or hit an      ** 'OR FAIL' constraint. This means a commit is required.      */      int rc = vdbeCommit(db);      if( rc==SQLITE_BUSY ){        return SQLITE_BUSY;      }else if( rc!=SQLITE_OK ){        p->rc = rc;        xFunc = sqlite3BtreeRollback;      }    }else{      xFunc = sqlite3BtreeRollback;    }  }else{    if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){      xFunc = sqlite3BtreeCommitStmt;    }else if( p->errorAction==OE_Abort ){      xFunc = sqlite3BtreeRollbackStmt;    }else{      xFunc = sqlite3BtreeRollback;      db->autoCommit = 1;      abortOtherActiveVdbes(p);    }  }  /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback,  ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on  ** each backend. If an error occurs and the return code is still  ** SQLITE_OK, set the return code to the new error value.  */  for(i=0; xFunc && i<db->nDb; i++){     int rc;    Btree *pBt = db->aDb[i].pBt;    if( pBt ){      rc = xFunc(pBt);      if( p->rc==SQLITE_OK ) p->rc = rc;    }  }  /* If this was an INSERT, UPDATE or DELETE, set the change counter. */  if( p->changeCntOn && p->pc>=0 ){    if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){      sqlite3VdbeSetChanges(db, p->nChange);    }else{      sqlite3VdbeSetChanges(db, 0);    }    p->nChange = 0;  }  /* Rollback or commit any schema changes that occurred. */  if( p->rc!=SQLITE_OK ){    sqlite3RollbackInternalChanges(db);  }else if( db->flags & SQLITE_InternChanges ){    sqlite3CommitInternalChanges(db);  }  /* We have successfully halted and closed the VM.  Record this fact. */  if( p->pc>=0 ){    db->activeVdbeCnt--;  }  p->magic = VDBE_MAGIC_HALT;  checkActiveVdbeCnt(db);  return SQLITE_OK;}/*** Clean up a VDBE after execution but do not delete the VDBE just yet.** Write any error messages into *pzErrMsg.  Return the result code.**** After this routine is run, the VDBE should be ready to be executed** again.**** To look at it another way, this routine resets the state of the** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to** VDBE_MAGIC_INIT.*/int sqlite3VdbeReset(Vdbe *p){  if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){    sqlite3Error(p->db, SQLITE_MISUSE, 0);    return SQLITE_MISUSE;  }  /* If the VM did not run to completion or if it encountered an  ** error, then it might not have been halted properly.  So halt  ** it now.  */  sqlite3VdbeHalt(p);  /* If the VDBE has be run even partially, then transfer the error code  ** and error message from the VDBE into the main database structure.  But  ** if the VDBE has just been set to run but has not actually executed any  ** instructions yet, leave the main database error information unchanged.  */  if( p->pc>=0 ){    if( p->zErrMsg ){      sqlite3Error(p->db, p->rc, "%s", p->zErrMsg);      sqliteFree(p->zErrMsg);      p->zErrMsg = 0;    }else if( p->rc ){      sqlite3Error(p->db, p->rc, 0);    }else{      sqlite3Error(p->db, SQLITE_OK, 0);    }  }else if( p->rc && p->expired ){    /* The expired flag was set on the VDBE before the first call    ** to sqlite3_step(). For consistency (since sqlite3_step() was    ** called), set the database error in this case as well.    */    sqlite3Error(p->db, p->rc, 0);  }  /* Reclaim all memory used by the VDBE  */  Cleanup(p);  /* Save profiling information from this VDBE run.  */  assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 );#ifdef VDBE_PROFILE  {    FILE *out = fopen("vdbe_profile.out", "a");    if( out ){      int i;      fprintf(out, "---- ");      for(i=0; i<p->nOp; i++){        fprintf(out, "%02x", p->aOp[i].opcode);      }      fprintf(out, "\n");      for(i=0; i<p->nOp; i++){        fprintf(out, "%6d %10lld %8lld ",           p->aOp[i].cnt,           p->aOp[i].cycles,           p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0        );        sqlite3VdbePrintOp(out, i, &p->aOp[i]);      }      fclose(out);    }  }#endif  p->magic = VDBE_MAGIC_INIT;  p->aborted = 0;  if( p->rc==SQLITE_SCHEMA ){    sqlite3ResetInternalSchema(p->db, 0);  }  return p->rc;} /*** Clean up and delete a VDBE after execution.  Return an integer which is** the result code.  Write any error message text into *pzErrMsg.*/int sqlite3VdbeFinalize(Vdbe *p){  int rc = SQLITE_OK;  if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){    rc = sqlite3VdbeReset(p);  }else if( p->magic!=VDBE_MAGIC_INIT ){    return SQLITE_MISUSE;  }  sqlite3VdbeDelete(p);  return rc;}/*** Call the destructor for each auxdata entry in pVdbeFunc for which** the corresponding bit in mask is clear.  Auxdata entries beyond 31** are always destroyed.  To destroy all auxdata entries, call this** routine with mask==0.*/void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){  int i;  for(i=0; i<pVdbeFunc->nAux; i++){    struct AuxData *pAux = &pVdbeFunc->apAux[i];    if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){      if( pAux->xDelete ){        pAux->xDelete(pAux->pAux);      }      pAux->pAux = 0;    }  }}/*** Delete an entire VDBE.*/void sqlite3VdbeDelete(Vdbe *p){  int i;  if( p==0 ) return;  Cleanup(p);  if( p->pPrev ){    p->pPrev->pNext = p->pNext;  }else{    assert( p->db->pVdbe==p );    p->db->pVdbe = p->pNext;  }  if( p->pNext ){    p->pNext->pPrev = p->pPrev;  }  if( p->aOp ){    for(i=0; i<p->nOp; i++){      Op *pOp = &p->aOp[i];      freeP3(pOp->p3type, pOp->p3);

⌨️ 快捷键说明

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