概述
繼創(chuàng)建數(shù)據(jù)庫連接和履行SQL語句并獲得結(jié)果以后,我們繼續(xù)對OCI中關(guān)閉數(shù)據(jù)庫連接的源碼進行剖析。該操作主要是由CDbCloseDb函數(shù)完成的。
下面對這個函數(shù)的源碼進行分析。
OCI中履行關(guān)閉數(shù)據(jù)庫連接的源碼剖析
在OCI中,CDbCloseDb函數(shù)的代碼以下:
void CDbCloseDb(void *hDb)
{
CDb *pCDb = NULL;
if (NULL == hDb)
{
return;
}
pCDb = (CDb *)hDb;
DoDbFree(pCDb->hdbc);
DoRecFree(pCDb->hRec);
OsRetUB((UINT8*)hDb);
return;
}
從該函數(shù)的代碼實現(xiàn)中,我們可以看到:
1)該函數(shù)的輸入?yún)?shù)只有1個:數(shù)據(jù)庫連接句柄。同時,該函數(shù)還調(diào)用了3個函數(shù),DoDbFree用于釋放數(shù)據(jù)庫連接,DoRecFree用于釋放數(shù)據(jù)庫結(jié)果集行數(shù)據(jù)緩沖區(qū),OsRetUB用于釋放操作系統(tǒng)的數(shù)據(jù)庫內(nèi)存。
2)CDb結(jié)構(gòu)體用于寄存數(shù)據(jù)庫連接句柄數(shù)據(jù),其聲明以下:
typedef struct CDbTag
{
INT32 iDbType; /* 數(shù)據(jù)庫類型 0:sqlservr1:sybase 2:oracle*/
OCIHDBC hdbc; /* 全局OCI句柄 */
CDbRecordset *hRec; /* 行結(jié)果集數(shù)據(jù)結(jié)構(gòu)指針 */
}CDb;
釋放數(shù)據(jù)庫連接的DoDbFree函數(shù)的代碼以下:
static void DoDbFree(OCIHDBC hdbc)
{
if (NULL == hdbc)
{
return;
}
OCISessionEnd(hdbc->svchp, hdbc->errhp, hdbc->authp, (ub4)0);
OCIServerDetach(hdbc->srvhp, hdbc->errhp, (ub4)OCI_DEFAULT);
OCIHandleFree((dvoid *)hdbc->srvhp, (ub4)OCI_HTYPE_SERVER);
OCIHandleFree((dvoid *)hdbc->svchp, (ub4)OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *)hdbc->errhp, (ub4)OCI_HTYPE_ERROR);
OCIHandleFree((dvoid *)hdbc->authp, (ub4)OCI_HTYPE_SESSION);
OCIHandleFree((dvoid *)hdbc->envhp, (ub4)OCI_HTYPE_ENV);
OsRetUB((UINT8*)hdbc);
hdbc = NULL;
}
從該函數(shù)的代碼實現(xiàn)中,我們可以看到:
1)該函數(shù)調(diào)用OCI底層的函數(shù)來分別釋放與數(shù)據(jù)庫相干的句柄,這些句柄定義在OCIHDBC結(jié)構(gòu)體中。
2)OCIHDBC結(jié)構(gòu)體的聲明以下:
/* 所有OCI主要句柄數(shù)據(jù)結(jié)構(gòu) */
typedef struct
{
OCIEnv *envhp; /* 環(huán)境句柄 */
OCIError *errhp; /* 毛病句柄 */
OCIServer *srvhp; /* 服務(wù)器句柄 */
OCISvcCtx *svchp; /* 服務(wù)環(huán)境句柄 */
OCISession *authp; /* 會話句柄 */
OCIStmt *stmthp; /* 語句句柄 */
}t_envctx;
typedef t_envctx *OCIHDBC;
釋放數(shù)據(jù)庫結(jié)果集行數(shù)據(jù)緩沖區(qū)的DoRecFree函數(shù)的代碼以下:
static void DoRecFree(CDbRecordset*hRecordset)
{
if (NULL != hRecordset)
{
OsRetUB((UINT8*)hRecordset);
}
}
從該函數(shù)的代碼實現(xiàn)中,我們可以看到:
1)該函數(shù)調(diào)用OsRetUB函數(shù)來釋放數(shù)據(jù)緩沖區(qū)。
2)結(jié)果集行數(shù)據(jù)結(jié)構(gòu)體的聲明以下:
typedef struct CDbRecordsetTag
{
void *cmd; /* 命令緩沖區(qū) */
int sqltype; /* 1:select 2:other*/
int colCount; /* 返回列數(shù) */
char colfieldname[CDB_MAX_COL_NUM][40];/*每列列名 */
int colfieldlength[CDB_MAX_COL_NUM]; /* 列名寬度 */
int pColWidth[CDB_MAX_COL_NUM]; /* 每列寬度 */
int pColType[CDB_MAX_COL_NUM]; /* 列類型 */
char pRecordBuf[CDB_MAX_COL_NUM][CDB_MAX_COL_WIDTH];/* 列數(shù)據(jù) */
int pRetColWidth[CDB_MAX_COL_NUM];
short pRetIndicator[CDB_MAX_COL_NUM];
} CDbRecordset;
關(guān)閉數(shù)據(jù)庫連接CDbCloseDb函數(shù)調(diào)用
當我們獲得到了數(shù)據(jù)庫的返回結(jié)果以后,如果不再需要使用數(shù)據(jù)庫了,那末就要調(diào)用CDbCloseDb函數(shù)關(guān)閉數(shù)據(jù)庫連接。
CDbCloseDb函數(shù)調(diào)用的示例代碼以下:
INT32 main(void)
{
INT8 szDBServerName[50] = {0};
INT8 szDBName[50] = {0};
INT8 szDBUser[50] = {0};
INT8 szDBPwd[50] = {0};
INT8 szSqlBuf[100] = {0};
INT8 szRcvBuf[100] = {0};
INT32 iRetVal = 0;
void *pDBHandle = NULL;
// 獲得數(shù)據(jù)庫各參數(shù)的值
memcpy(szDBServerName, "db192_1_8_13",strlen("db192_1_8_13"));
memcpy(szDBName, "dbp_166", strlen("dbp_166"));
memcpy(szDBUser, "dbp_166", strlen("dbp_166"));
memcpy(szDBPwd, "dbp_166", strlen("dbp_166"));
// 連接數(shù)據(jù)庫
pDBHandle = CDbCreateDb("Oracle", szDBServerName, szDBName, szDBUser,szDBPwd);
if (pDBHandle == NULL) // 連接失敗
{
printf("ConnectDB failed! ServiceName:%s, DBName:%s, User:%s,Pwd:%s\n", szDBServerName, szDBName, szDBUser, szDBPwd);
return -1;
}
printf("ConnectDB success! ServiceName:%s, DBName:%s, User:%s,Pwd:%s\n", szDBServerName, szDBName, szDBUser, szDBPwd);
// 履行SQL語句并獲得結(jié)果
// 獲得SQL語句
memcpy(szSqlBuf, "select boxnumber from tb_test where id=1",strlen("select boxnumber from tb_test where id=1"));
// 調(diào)用CDbExecSql函數(shù)履行SQL語句
iRetVal = CDbExecSql(pDBHandle, szSqlBuf);
if (iRetVal != 0) // 履行失敗
{
printf("CDbExecSql failed! RetVal=%d (ServiceName:%s, DBName:%s,User:%s, Pwd:%s)\n", iRetVal, szDBServerName, szDBName, szDBUser, szDBPwd);
return -1;
}
// 調(diào)用CDbFetch函數(shù)獲得數(shù)據(jù)庫返回的結(jié)果
iRetVal = CDbFetch(pDBHandle, szRcvBuf, 100);
if (iRetVal != 0) // 履行失敗
{
printf("CDbFetch failed! RetVal=%d (ServiceName:%s, DBName:%s,User:%s, Pwd:%s)\n", iRetVal, szDBServerName, szDBName, szDBUser,szDBPwd);
return -1;
}
// 打印從數(shù)據(jù)庫中獲得到的結(jié)果
printf("RcvBuf=%s\n", szRcvBuf);
// 調(diào)用CDbCloseDb函數(shù)關(guān)閉數(shù)據(jù)庫連接
CDbCloseDb(pDBHandle);
pDBHandle = NULL; // 將數(shù)據(jù)庫句柄指針置為空
return 0;
}
說明:
1)CDbCloseDb函數(shù)的輸入?yún)?shù)是:數(shù)據(jù)庫句柄指針,數(shù)據(jù)庫句柄是由CDbCreateDb函數(shù)履行以后取得的。
2)CDbCloseDb函數(shù)履行完成以后,還要單獨編寫語句將數(shù)據(jù)庫句柄指針置為空,避免該指針在后面的流程中被隨便使用。