OCI編程高級篇(二十) 使用連接池的例子
訪問www.tomcoding.com網站,學習Oracle內部數據結構,詳細文檔說明,下載Oracle的exp/imp,DUL,logminer,ASM工具的源代碼,學習高技術含量的內容。
這一節我們用代碼實現一個實際的例子,來演示連接池的用法。例子中我們僅使用單線程來演示用法,例子的步驟如下。
1. 創建一個OCI環境,分配錯誤句柄。
2. 創建一個連接池。
3. 從連接池中獲取一個會話。
4. 通過這個會話從數據庫中查詢一個數字,SQL語句為select 10 from dual。
5. 釋放會話。
6. 銷毀連接池。
7. 釋放OCI環境。
例子代碼如下,關鍵處有詳細注釋。
#include "stdio.h" #include "stdlib.h" #include "stdint.h" #include "memory.h" #include "string.h" #include "time.h" #include "errno.h" #include "oci.h" /* global variable defination */ OCIEnv *envhp = NULL; /* env handle */ OCIError *errhp = NULL; /* error handle */ OCISvcCtx *svchp = NULL; /* service context handle */ OCICPool *poolhp = NULL; /* connection pool handle */ OCIAuthInfo *authp = NULL; /* authentication information handle */ OCIStmt *stmthp = NULL; /* statement handle */ text errbuf[512]; /* error message text */ struct { char uname[32]; /* 認證用戶名稱 */ char upwd[32]; /* 認證用戶密碼 */ } inputs; static void usage(const char *prg){ fprintf(stderr, "Usage: %s user/password\n\n" " user oracle user\n" " password user password\n" , prg ); } /* 解析命令行中的認證用戶和密碼 */
static int parse_inputs(int argc, char *argv[]){ char *p; if (argc < 2) { usage(argv[0]); return (-1); } if ((p=strchr(argv[1], '/')) == NULL) { usage(argv[0]); return (-1); } *p++ = '\0'; memset(&inputs, 0, sizeof(inputs)); strncpy(inputs.uname, argv[1], 31); strncpy(inputs.upwd, p, 31); return (0); } static char ora_env[][16] = { "ORACLE_HOME", "ORACLE_SID", "" }; /* 檢查Oracle運行的環境變量 */
static int check_ora_env(void){ int i; for (i=0; ora_env[i][0]; i++) { if (getenv(ora_env[i]) == NULL) { fprintf(stderr, "env %s not set.\n", ora_env[i]); return (-1); } } return (0); } /* 創建連接池函數 */
static int create_connection_pool(void){ sword rc; sb4 ec; ub4 conn_min; ub4 conn_max; ub4 conn_inc; sb4 pool_name_len; char *pool_name; /* 創建環境句柄 */ rc = OCIEnvCreate( &envhp, /* envhpp */ OCI_DEFAULT, /* mode */ (void *)NULL, /* ctxp */ NULL, NULL, NULL, (size_t)0, (void **)NULL ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIEnvCreate() - allocate OCI env handle error !\n"); return (-1); } /* 分配錯誤句柄 */ rc = OCIHandleAlloc( (void *)envhp, (void **)&errhp, OCI_HTYPE_ERROR, 0, (void **)NULL ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc() - allocate OCI error handle error !\n"); return (-1); } /* 分配連接池句柄 */ rc = OCIHandleAlloc( (void *)envhp, (void **)&poolhp, OCI_HTYPE_CPOOL, (size_t)0, (void **)NULL ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc() - allocate connection pool handle error !\n"); return (-1); } /* 創建連接池,初始連接數為2,最大連接數為5,每次增長1個連接 */ conn_min = 2; conn_max = 5; conn_inc = 1; rc = OCIConnectionPoolCreate( envhp, errhp, poolhp, (OraText **)&pool_name, &pool_name_len, (const OraText *)"", 0, (ub4)conn_min, (ub4)conn_max, (ub4)conn_inc, (OraText *)inputs.uname, strlen(inputs.uname), (OraText *)inputs.upwd, strlen(inputs.upwd), OCI_DEFAULT ); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIConnectionPoolCreate() - [%d] %s\n", ec, errbuf); return (-1); } /* 顯示一下連接池的名稱 */ fprintf(stdout, "connection pool name: [%d]%s\n", pool_name_len, pool_name); return (0); } /* 銷毀連接池 */
static int destroy_connection_pool(void){ sword rc; sb4 ec; /* 銷毀連接池 */ if (poolhp != NULL) { rc = OCIConnectionPoolDestroy(poolhp, errhp, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIConnectionPoolDestroy() - [%d] %s\n", ec, errbuf); return (-1); } /* 釋放連接池句柄 */ rc = OCIHandleFree((void *)poolhp, OCI_HTYPE_CPOOL); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleFree() - free connection pool handle error !\n"); return (-1); } } /* 釋放錯誤句柄 */ if (errhp != NULL) { rc = OCIHandleFree( errhp, OCI_HTYPE_ERROR ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleFree() - free error handle error !\n"); return (-1); } } /* 釋放環境句柄 */ if (envhp != NULL) { rc = OCIHandleFree( envhp, OCI_HTYPE_ENV ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleFree() - free env handle error !\n"); return (-1); } } return (0); }
/* 從數據庫中查詢數值 */
static int query_from_dual(void){ sword rc; sb4 ec; int slen; ub4 u4; char sqltxt[1024]; OCIDefine *defp; /* 分配認證信息句柄 */ rc = OCIHandleAlloc( (void *)envhp, (void **)&authp, OCI_HTYPE_AUTHINFO, (size_t)0, (void **)NULL ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc() - allocate authentication handle error !\n"); return (-1); } /* 設置認證用戶名稱 */ rc = OCIAttrSet( (void *)authp, OCI_HTYPE_AUTHINFO, (dvoid *)inputs.uname, strlen(inputs.uname), OCI_ATTR_USERNAME, errhp ); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "Set User Attribute - [%d] %s\n", ec, errbuf); return (-1); } /* 設置認證用戶密碼 */ rc = OCIAttrSet( (void *)authp, OCI_HTYPE_AUTHINFO, (void *)inputs.upwd, strlen(inputs.upwd), OCI_ATTR_PASSWORD, errhp ); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "Set Password Attribute - [%d] %s\n", ec, errbuf); return (-1); } /* 從連接池獲取會話 */ rc = OCISessionGet(envhp, errhp, &svchp, authp, (OraText *)pool_name, pool_name_len, NULL, 0, NULL, NULL, NULL, OCI_SESSGET_CPOOL ); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCISessionGet() - [%d] %s\n", ec, errbuf); return (-1); } /* 分配OCI語句句柄 */ rc = OCIHandleAlloc( (void *)envhp, (void **)&stmthp, OCI_HTYPE_STMT, 0, (void **)NULL ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleAlloc() - allocate statement handle error !\n"); return (-1); } /* 產生SQL語句文本 */ strcpy(sqltxt, "select 10 from dual"); slen = strlen(sqltxt); /* 準備語句 */ rc = OCIStmtPrepare(stmthp, errhp, (const OraText *)sqltxt, slen, OCI_NTV_SYNTAX, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIStmtPrepare() - [%d] %s\n", ec, errbuf); return (-1); } /* 定義輸出變量 */ rc = OCIDefineByPos(stmthp, &defp, errhp, (ub4)1, (void *)&u4, (sb4)4, (ub2)SQLT_INT, (void *)NULL, (ub2 *)NULL, (ub2 *)NULL, (ub4)OCI_DEFAULT ); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIDefineByPos() - [%d] %s\n", ec, errbuf); return (-1); } /* 執行查詢語句 */ rc = OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIStmtExecute() - [%d] %s\n", ec, errbuf); return (-1); } /* 取回結果集 */ rc = OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCIStmtFetch2() - [%d] %s\n", ec, errbuf); return (-1); } /* 顯示從數據庫查詢到的數值 */ fprintf(stdout, "number from dual is: %d\n", u4); /* 釋放語句句柄 */ rc = OCIHandleFree( stmthp, OCI_HTYPE_STMT ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleFree() - free statement handle error !\n"); return (-1); } /* 釋放連接池會話 */ rc = OCISessionRelease(svchp, errhp, NULL, 0, OCI_DEFAULT); if (rc != OCI_SUCCESS) { OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR); fprintf(stderr, "OCISessionRelease() - [%d] %s\n", ec, errbuf); return (-1); } /* 釋放認證信息句柄 */ rc = OCIHandleFree( authp, OCI_HTYPE_AUTHINFO ); if (rc != OCI_SUCCESS) { fprintf(stderr, "OCIHandleFree() - free authentication handle error !\n"); return (-1); } return (0); } /* 主函數 */
int main(int argc, char *argv[]){ /* 解析命令行參數 */ if (parse_inputs(argc, argv) < 0) return (-1); /* 檢查Oracle運行環境變量是否設置 */ if (check_ora_env() < 0) return (-1); /* 創建連接池 */ if (create_connection_pool() < 0) goto error_exit; /* 從數據庫中查詢數值 */ if (query_from_dual() < 0) fprintf(stderr, "query operation error !\n"); /* 銷毀連接池 */ destroy_connection_pool(); return (0); error_exit: destroy_connection_pool(); return (-1); }
例子中使用了OCISessionGet()函數來獲取連接池會話,要比使用OCILogon2()函數復雜一些,仔細看一下,Oracle提供的示例代碼中沒有演示OCISessionGet()函數的用法。
/* 從數據庫中查詢數值 */static int query_from_dual(void){
sword rc;
sb4 ec;
int slen;
ub4 u4;
char sqltxt[1024];
OCIDefine *defp;
/* 分配認證信息句柄 */
rc = OCIHandleAlloc(
(void *)envhp,
(void **)&authp,
OCI_HTYPE_AUTHINFO,
(size_t)0,
(void **)NULL
);
if (rc != OCI_SUCCESS) {
fprintf(stderr, "OCIHandleAlloc() - allocate authentication handle error !\n");
return (-1);
}
/* 設置認證用戶名稱 */
rc = OCIAttrSet(
(void *)authp,
OCI_HTYPE_AUTHINFO,
(dvoid *)inputs.uname,
strlen(inputs.uname),
OCI_ATTR_USERNAME,
errhp
);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "Set User Attribute - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 設置認證用戶密碼 */
rc = OCIAttrSet(
(void *)authp,
OCI_HTYPE_AUTHINFO,
(void *)inputs.upwd,
strlen(inputs.upwd),
OCI_ATTR_PASSWORD,
errhp
);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "Set Password Attribute - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 從連接池獲取會話 */
rc = OCISessionGet(envhp, errhp, &svchp, authp,
(OraText *)pool_name, pool_name_len,
NULL, 0, NULL, NULL, NULL,
OCI_SESSGET_CPOOL
);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCISessionGet() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 分配OCI語句句柄 */
rc = OCIHandleAlloc(
(void *)envhp,
(void **)&stmthp,
OCI_HTYPE_STMT,
0,
(void **)NULL
);
if (rc != OCI_SUCCESS) {
fprintf(stderr, "OCIHandleAlloc() - allocate statement handle error !\n");
return (-1);
}
/* 產生SQL語句文本 */
strcpy(sqltxt, "select 10 from dual");
slen = strlen(sqltxt);
/* 準備語句 */
rc = OCIStmtPrepare(stmthp, errhp, (const OraText *)sqltxt, slen,
OCI_NTV_SYNTAX, OCI_DEFAULT);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCIStmtPrepare() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 定義輸出變量 */
rc = OCIDefineByPos(stmthp,
&defp,
errhp,
(ub4)1,
(void *)&u4,
(sb4)4,
(ub2)SQLT_INT,
(void *)NULL,
(ub2 *)NULL,
(ub2 *)NULL,
(ub4)OCI_DEFAULT
);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCIDefineByPos() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 執行查詢語句 */
rc = OCIStmtExecute(svchp, stmthp, errhp, 0, 0, NULL, NULL, OCI_DEFAULT);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCIStmtExecute() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 取回結果集 */
rc = OCIStmtFetch2(stmthp, errhp, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCIStmtFetch2() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 顯示從數據庫查詢到的數值 */
fprintf(stdout, "number from dual is: %d\n", u4);
/* 釋放語句句柄 */
rc = OCIHandleFree(
stmthp,
OCI_HTYPE_STMT
);
if (rc != OCI_SUCCESS) {
fprintf(stderr, "OCIHandleFree() - free statement handle error !\n");
return (-1);
}
/* 釋放連接池會話 */
rc = OCISessionRelease(svchp, errhp, NULL, 0, OCI_DEFAULT);
if (rc != OCI_SUCCESS) {
OCIErrorGet(errhp, 1, NULL, &ec, errbuf, 512, OCI_HTYPE_ERROR);
fprintf(stderr, "OCISessionRelease() - [%d] %s\n", ec, errbuf);
return (-1);
}
/* 釋放認證信息句柄 */
rc = OCIHandleFree(
authp,
OCI_HTYPE_AUTHINFO
);
if (rc != OCI_SUCCESS) {
fprintf(stderr, "OCIHandleFree() - free authentication handle error !\n");
return (-1);
}
return (0);
}
/* 主函數 */int main(int argc, char *argv[]){
/* 解析命令行參數 */
if (parse_inputs(argc, argv) < 0)
return (-1);
/* 檢查Oracle運行環境變量是否設置 */
if (check_ora_env() < 0)
return (-1);
/* 創建連接池 */
if (create_connection_pool() < 0)
goto error_exit;
/* 從數據庫中查詢數值 */
if (query_from_dual() < 0)
fprintf(stderr, "query operation error !\n");
/* 銷毀連接池 */
destroy_connection_pool();
return (0);
error_exit:
destroy_connection_pool();
return (-1);
}

浙公網安備 33010602011771號