IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]Oracle调用接口(OCI)源码剖析(3):关闭数据库连接

    zhouzxi发表于 2016-09-20 21:11:23
    love 0

    概述
    继创建数据库连接和执行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结构体用于存放数据库连接句柄数据,其声明如下:

    typedef struct CDbTag
    {
        INT32         iDbType;  /* 数据库类型 0:sqlservr1:sybase 2:oracle*/
        OCIHDBC       hdbc;     /* 全局OCI句柄 */
        CDbRecordset *hRec;     /* 行结果集数据结构指针 */
    }CDb;

    释放数据库连接的DoDbFree函数的代码如下:

    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;
    }

    从该函数的代码实现中,我们可以看到:
    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函数关闭数据库连接。

    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,      "dbp_166",     strlen("dbp_166"));
       memcpy(szDBPwd,       "dbp_166",     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", szDBServerName, szDBName, szDBUser, szDBPwd);
    
           return -1;
       }
    
       printf("ConnectDB success! ServiceName:%s, DBName:%s, User:%s,Pwd:%s\n", szDBServerName, szDBName, szDBUser, 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, DBName:%s,User:%s, Pwd:%s)\n", iRetVal, szDBServerName, szDBName, szDBUser, szDBPwd);
    
           return -1;
       }
    
       // 调用CDbFetch函数获取数据库返回的结果
       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;
       }
    
       // 打印从数据库中获取到的结果
       printf("RcvBuf=%s\n", szRcvBuf);
    
       // 调用CDbCloseDb函数关闭数据库连接
       CDbCloseDb(pDBHandle);
       pDBHandle = NULL;      // 将数据库句柄指针置为空
    
       return 0;
    }

    说明:
    1)CDbCloseDb函数的输入参数是:数据库句柄指针,数据库句柄是由CDbCreateDb函数执行之后获得的。

    2)CDbCloseDb函数执行完成之后,还要单独编写语句将数据库句柄指针置为空,防止该指针在后面的流程中被随意使用。



沪ICP备19023445号-2号
友情链接