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

📄 vdbeaux.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
          needSync = 1;        }        rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset);        offset += strlen(zFile)+1;        if( rc!=SQLITE_OK ){          sqlite3OsCloseFree(pMaster);          sqlite3OsDelete(pVfs, zMaster, 0);          sqlite3DbFree(db, zMaster);          return rc;        }      }    }    /* Sync the master journal file. If the IOCAP_SEQUENTIAL device    ** flag is set this is not required.    */    zMainFile = sqlite3BtreeGetDirname(db->aDb[0].pBt);    if( (needSync      && (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL))     && (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){      sqlite3OsCloseFree(pMaster);      sqlite3OsDelete(pVfs, zMaster, 0);      sqlite3DbFree(db, 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 ){        rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster);      }    }    sqlite3OsCloseFree(pMaster);    if( rc!=SQLITE_OK ){      sqlite3DbFree(db, 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(pVfs, zMaster, 1);    sqlite3DbFree(db, zMaster);    zMaster = 0;    if( rc ){      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();    sqlite3BeginBenignMalloc();    for(i=0; i<db->nDb; i++){       Btree *pBt = db->aDb[i].pBt;      if( pBt ){        sqlite3BtreeCommitPhaseTwo(pBt);      }    }    sqlite3EndBenignMalloc();    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/*** For every Btree that in database connection db which ** has been modified, "trip" or invalidate each cursor in** that Btree might have been modified so that the cursor** can never be used again.  This happens when a rollback*** occurs.  We have to trip all the other cursors, even** cursor from other VMs in different database connections,** so that none of them try to use the data at which they** were pointing and which now may have been changed due** to the rollback.**** Remember that a rollback can delete tables complete and** reorder rootpages.  So it is not sufficient just to save** the state of the cursor.  We have to invalidate the cursor** so that it is never used again.*/static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){  int i;  for(i=0; i<db->nDb; i++){    Btree *p = db->aDb[i].pBt;    if( p && sqlite3BtreeIsInTrans(p) ){      sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);    }  }}/*** 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.  It is harmless to** call this on a VM that is in the SQLITE_MAGIC_HALT state.**** 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 */  int isSpecialError;            /* Set to true if SQLITE_NOMEM or IOERR */  /* This function contains the logic that determines if a statement or  ** transaction will be committed or rolled back as a result of the  ** execution of this virtual machine.   **  ** If any of the following errors occur:  **  **     SQLITE_NOMEM  **     SQLITE_IOERR  **     SQLITE_FULL  **     SQLITE_INTERRUPT  **  ** Then the internal cache might have been left in an inconsistent  ** state.  We need to rollback the statement transaction, if there is  ** one, or the complete transaction if there is no statement transaction.  */  if( p->db->mallocFailed ){    p->rc = SQLITE_NOMEM;  }  closeAllCursorsExceptActiveVtabs(p);  if( p->magic!=VDBE_MAGIC_RUN ){    return SQLITE_OK;  }  checkActiveVdbeCnt(db);  /* No commit or rollback needed if the program never started */  if( p->pc>=0 ){    int mrc;   /* Primary error code from p->rc */    /* Lock all btrees used by the statement */    sqlite3BtreeMutexArrayEnter(&p->aMutex);    /* Check for one of the special errors */    mrc = p->rc & 0xff;    isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR                     || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;    if( isSpecialError ){      /* This loop does static analysis of the query to see which of the      ** following three categories it falls into:      **      **     Read-only      **     Query with statement journal      **     Query without statement journal      **      ** We could do something more elegant than this static analysis (i.e.      ** store the type of query as part of the compliation phase), but       ** handling malloc() or IO failure is a fairly obscure edge case so       ** this is probably easier. Todo: Might be an opportunity to reduce       ** code size a very small amount though...      */      int notReadOnly = 0;      int isStatement = 0;      assert(p->aOp || p->nOp==0);      for(i=0; i<p->nOp; i++){         switch( p->aOp[i].opcode ){          case OP_Transaction:            notReadOnly |= p->aOp[i].p2;            break;          case OP_Statement:            isStatement = 1;            break;        }      }         /* If the query was read-only, we need do no rollback at all. Otherwise,      ** proceed with the special handling.      */      if( notReadOnly || mrc!=SQLITE_INTERRUPT ){        if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){          xFunc = sqlite3BtreeRollbackStmt;          p->rc = SQLITE_BUSY;        } else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){          xFunc = sqlite3BtreeRollbackStmt;        }else{          /* We are forced to roll back the active transaction. Before doing          ** so, abort any other statements this handle currently has active.          */          invalidateCursorsOnModifiedBtrees(db);          sqlite3RollbackAll(db);          db->autoCommit = 1;        }      }    }      /* If the auto-commit flag is set and this is the only active vdbe, then    ** we do either a commit or rollback of the current transaction.     **    ** Note: This block also runs if one of the special errors handled     ** above has occured.     */    if( db->autoCommit && db->activeVdbeCnt==1 ){      if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){        /* The auto-commit flag is true, and the vdbe program was         ** successful or hit an 'OR FAIL' constraint. This means a commit         ** is required.        */        int rc = vdbeCommit(db, p);        if( rc==SQLITE_BUSY ){          sqlite3BtreeMutexArrayLeave(&p->aMutex);          return SQLITE_BUSY;        }else if( rc!=SQLITE_OK ){          p->rc = rc;          sqlite3RollbackAll(db);        }else{          sqlite3CommitInternalChanges(db);        }      }else{        sqlite3RollbackAll(db);      }    }else if( !xFunc ){      if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){        if( p->openedStatement ){          xFunc = sqlite3BtreeCommitStmt;        }       }else if( p->errorAction==OE_Abort ){        xFunc = sqlite3BtreeRollbackStmt;      }else{        invalidateCursorsOnModifiedBtrees(db);        sqlite3RollbackAll(db);        db->autoCommit = 1;      }    }      /* If xFunc is not NULL, then it is one of 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.    */    assert(!xFunc ||      xFunc==sqlite3BtreeCommitStmt ||      xFunc==sqlite3BtreeRollbackStmt    );    for(i=0; xFunc && i<db->nDb; i++){       int rc;      Btree *pBt = db->aDb[i].pBt;      if( pBt ){        rc = xFunc(pBt);        if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){          p->rc = rc;          sqlite3DbFree(db, p->zErrMsg);          p->zErrMsg = 0;        }      }    }      /* If this was an INSERT, UPDATE or DELETE and the statement was committed,     ** 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 && db->flags&SQLITE_InternChanges ){      sqlite3ResetInternalSchema(db, 0);      db->flags = (db->flags | SQLITE_InternChanges);    }    /* Release the locks */    sqlite3BtreeMutexArrayLeave(&p->aMutex);  }  /* We have successfully halted and closed the VM.  Record this fact. */  if( p->pc>=0 ){    db->activeVdbeCnt--;  }  p->magic = VDBE_MAGIC_HALT;  checkActiveVdbeCnt(db);  if( p->db->mallocFailed ){    p->rc = SQLITE_NOMEM;  }  return SQLITE_OK;}/*** Each VDBE holds the result of the most recent sqlite3_step() call** in p->rc.  This routine sets that result back to SQLITE_OK.*/void sqlite3VdbeResetStepResult(Vdbe *p){  p->rc = 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){  sqlite3 *db;  db = p->db;  /* 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.  */  (void)sqlite3SafetyOn(db);  sqlite3VdbeHalt(p);  (void)sqlite3SafetyOff(db);  /* 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 ){      sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);      db->errCode = p->rc;      sqlite3DbFree(db, p->zErrMsg);      p->zErrMsg = 0;    }else if( p->rc ){      sqlite3Error(db, p->rc, 0);    }else{      sqlite3Error(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(db, p->rc, 0);    sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);    sqlite3DbFree(db, p->zErrMsg);    p->zErrMsg = 0;  }  /* Reclaim all memory used by the VDBE  */  Cleanup(p);  /* Save profiling information from this VDBE run.  */#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;  return p->rc & db->errMask;} /*** 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);    assert( (rc & p->db->errMask)==rc );  }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

⌨️ 快捷键说明

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