概述
继创建数据库连接和执行sql语句并获取结果之后,我们继续对OCI中关闭数据库连接的源码进行剖析。该操作主要是由CDbCloseDb函数完成的。
下面对这个函数的源码进行分析。
OCI中执行关闭数据库连接的源码剖析
在OCI中,CDbCloseDb函数的代码如下:
- void CDbCloseDb(void *hDb)
- {
- CDb *pCDb = NULL;
-
- if (NULL == hDb)
- {
- return;
- }
- pCDb = (CDb *)hDb;
-
- DoDbFree(pCDb->hdbc);
- DoRecFree(pCDb->hRec);
- OsRetUB((UINT8*)hDb);
- return;
- }
从该函数的代码实现中,我们可以看到:
1)该函数的输入参数只有一个:数据库连接句柄。同时,该函数还调用了三个函数,DoDbFree用于释放数据库连接,DoRecFree用于释放数据库结果集行数据缓冲区,OsRetUB用于释放操作系统的数据库内存。
2)CDb结构体用于存放数据库连接句柄数据,其声明如下:
- static void DoDbFree(OCIHDBC hdbc)
- {
- if (NULL == hdbc)
- {
- return;
- }
- OCISessionEnd(hdbc->svchp,hdbc->errhp,hdbc->authp,(ub4)0);
- OCIServerDetach(hdbc->srvhp,(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;
- }
从该函数的代码实现中,我们可以看到:
1)该函数调用OCI底层的函数来分别释放与数据库相关的句柄,这些句柄定义在OCIHDBC结构体中。
2)OCIHDBC结构体的声明如下:
- /* 所有OCI主要句柄数据结构 */
- typedef struct
- {
- OCIEnv *envhp; /* 环境句柄 */
- OCIError *errhp; /* 错误句柄 */
- OCIServer *srvhp; /* 服务器句柄 */
- OCISvcCtx *svchp; /* 服务环境句柄 */
- OCISession *authp; /* 会话句柄 */
- OCIStmt *stmthp; /* 语句句柄 */
- }t_envctx;
- typedef t_envctx *OCIHDBC;
释放数据库结果集行数据缓冲区的DoRecFree函数的代码如下:
- static void DoRecFree(CDbRecordset*hRecordset)
- {
- if (NULL != hRecordset)
- {
- OsRetUB((UINT8*)hRecordset);
- }
- }
从该函数的代码实现中,我们可以看到:
1)该函数调用OsRetUB函数来释放数据缓冲区。
2)结果集行数据结构体的声明如下:
- typedef struct CDbRecordsetTag
- {
- void *cmd; /* 命令缓冲区 */
- int sqltype; /* 1:select 2:other*/
- int colCount; /* 返回列数 */
- 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];/* 列数据 */
- int pRetColWidth[CDB_MAX_COL_NUM];
- short pRetIndicator[CDB_MAX_COL_NUM];
- } CDbRecordset;
关闭数据库连接CDbCloseDb函数调用
当我们获取到了数据库的返回结果之后,如果不再需要使用数据库了,那么就要调用CDbCloseDb函数关闭数据库连接。
- 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;
-
- // 获取数据库各参数的值
- memcpy(szDBServerName,"db192_1_8_13",strlen("db192_1_8_13"));
- memcpy(szDBName,"dbp_166",strlen("dbp_166"));
- memcpy(szDBUser,strlen("dbp_166"));
- memcpy(szDBPwd,strlen("dbp_166"));
-
- // 连接数据库
- pDBHandle = CDbCreateDb("Oracle",szDBServerName,szDBName,szDBUser,szDBPwd);
-
- if (pDBHandle == NULL) // 连接失败
- {
- printf("ConnectDB Failed! ServiceName:%s,DBName:%s,User:%s,Pwd:%s\n",szDBPwd);
-
- return -1;
- }
-
- printf("ConnectDB success! ServiceName:%s,szDBPwd);
- // 执行sql语句并获取结果
- // 获取sql语句
- memcpy(szsqlBuf,"select Boxnumber from tb_test where id=1",strlen("select Boxnumber from tb_test where id=1"));
- // 调用CDbExecsql函数执行sql语句
- iRetVal = CDbExecsql(pDBHandle,szsqlBuf);
- if (iRetVal != 0) // 执行失败
- {
- printf("CDbExecsql Failed! RetVal=%d (ServiceName:%s,Pwd:%s)\n",iRetVal,szDBPwd);
- return -1;
- }
- // 调用CDbFetch函数获取数据库返回的结果
- iRetVal = CDbFetch(pDBHandle,szRcvBuf,100);
- if (iRetVal != 0) // 执行失败
- {
- printf("CDbFetch Failed! RetVal=%d (ServiceName:%s,szDBPwd);
- return -1;
- }
- // 打印从数据库中获取到的结果
- printf("RcvBuf=%s\n",szRcvBuf);
- // 调用CDbCloseDb函数关闭数据库连接
- CDbCloseDb(pDBHandle);
- pDBHandle = NULL; // 将数据库句柄指针置为空
- return 0;
- }
说明:
1)CDbCloseDb函数的输入参数是:数据库句柄指针,数据库句柄是由CDbCreateDb函数执行之后获得的。