勇芳软件工作室.汉化:  SQLite3 API Functions > Database Connection >

sqlite3_close

Previous pageReturn to chapter overviewNext page

描述

 

用于sqlite3对象的析构函数。

 

C / C ++语法

 

int sqlite3_close(sqlite3 *);

 

PB语法

 

FUNCTION sqlite3_close ( _

BYVAL hDbc AS DWORD _

) AS LONG

 

参数

 

pDb

 

[in]数据库连接句柄。必须是从sqlite3_opensqlite3_open16sqlite3_open_v2获取的NULL指针或sqlite3对象指针,而不是先前关闭。使用NULL指针参数调用sqlite3_close是无害的操作。

 

返回值

 

如果sqlite3对象被成功销毁并且所有关联的资源被释放,SQLITE_OK。

 

备注

 

在尝试关闭对象之前,应用程序必须完成所有准备好的语句并关闭与sqlite3对象关联的所有BLOB句柄。如果在仍然有未完成的准备语句或BLOB句柄的数据库连接上调用sqlite3_close,则返回SQLITE_BUSY。

 

如果在事务打开时调用sqlite3_close,则事务将自动回滚。

 

C ++实现代码

 

/*

** Close an existing SQLite database

*/

SQLITE_API int sqlite3_close(sqlite3 *db){

HashElem *i;                    /* Hash table iterator */

int j;

 

if( !db ){

  return SQLITE_OK;

}

if( !sqlite3SafetyCheckSickOrOk(db) ){

  return SQLITE_MISUSE_BKPT;

}

sqlite3_mutex_enter(db->mutex);

 

/* Force xDisconnect calls on all virtual tables */

disconnectAllVtab(db);

 

/* If a transaction is open, the disconnectAllVtab() call above

** will not have called the xDisconnect() method on any virtual

** tables in the db->aVTrans[] array. The following sqlite3VtabRollback()

** call will do so. We need to do this before the check for active

** SQL statements below, as the v-table implementation may be storing

** some prepared statements internally.

*/

sqlite3VtabRollback(db);

 

/* If there are any outstanding VMs, return SQLITE_BUSY. */

if( db->pVdbe ){

  sqlite3Error(db, SQLITE_BUSY,

      "unable to close due to unfinalised statements");

  sqlite3_mutex_leave(db->mutex);

  return SQLITE_BUSY;

}

assert( sqlite3SafetyCheckSickOrOk(db) );

 

for(j=0; j<db->nDb; j++){

  Btree *pBt = db->aDb[j].pBt;

  if( pBt && sqlite3BtreeIsInBackup(pBt) ){

    sqlite3Error(db, SQLITE_BUSY,

        "unable to close due to unfinished backup operation");

    sqlite3_mutex_leave(db->mutex);

    return SQLITE_BUSY;

  }

}

 

/* Free any outstanding Savepoint structures. */

sqlite3CloseSavepoints(db);

 

/* Close all database connections */

for(j=0; j<db->nDb; j++){

  struct Db *pDb = &db->aDb[j];

  if( pDb->pBt ){

    sqlite3BtreeClose(pDb->pBt);

    pDb->pBt = 0;

    if( j!=1 ){

      pDb->pSchema = 0;

    }

  }

}

/* Clear the TEMP schema separately and last */

if( db->aDb[1].pSchema ){

  sqlite3SchemaClear(db->aDb[1].pSchema);

}

sqlite3VtabUnlockList(db);

 

/* Free up the array of auxiliary databases */

sqlite3CollapseDatabaseArray(db);

assert( db->nDb<=2 );

assert( db->aDb==db->aDbStatic );

 

/* Tell the code in notify.c that the connection no longer holds any

** locks and does not require any further unlock-notify callbacks.

*/

sqlite3ConnectionClosed(db);

 

for(j=0; j<ArraySize(db->aFunc.a); j++){

  FuncDef *pNext, *pHash, *p;

  for(p=db->aFunc.a[j]; p; p=pHash){

    pHash = p->pHash;

    while( p ){

      functionDestroy(db, p);

      pNext = p->pNext;

      sqlite3DbFree(db, p);

      p = pNext;

    }

  }

}

for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){

  CollSeq *pColl = (CollSeq *)sqliteHashData(i);

  /* Invoke any destructors registered for collation sequence user data. */

  for(j=0; j<3; j++){

    if( pColl[j].xDel ){

      pColl[j].xDel(pColl[j].pUser);

    }

  }

  sqlite3DbFree(db, pColl);

}

sqlite3HashClear(&db->aCollSeq);

#ifndef SQLITE_OMIT_VIRTUALTABLE

for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){

  Module *pMod = (Module *)sqliteHashData(i);

  if( pMod->xDestroy ){

    pMod->xDestroy(pMod->pAux);

  }

  sqlite3DbFree(db, pMod);

}

sqlite3HashClear(&db->aModule);

#endif

 

sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */

if( db->pErr ){

  sqlite3ValueFree(db->pErr);

}

sqlite3CloseExtensions(db);

 

db->magic = SQLITE_MAGIC_ERROR;

 

/* The temp-database schema is allocated differently from the other schema

** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).

** So it needs to be freed here. Todo: Why not roll the temp schema into

** the same sqliteMalloc() as the one that allocates the database

** structure?

*/

sqlite3DbFree(db, db->aDb[1].pSchema);

sqlite3_mutex_leave(db->mutex);

db->magic = SQLITE_MAGIC_CLOSED;

sqlite3_mutex_free(db->mutex);

assert( db->lookaside.nOut==0 );  /* Fails on a lookaside memory leak */

if( db->lookaside.bMalloced ){

  sqlite3_free(db->lookaside.pStart);

}

sqlite3_free(db);

return SQLITE_OK;

}