Google
 
Web itpro-blogger.blogspot.com
金曜日, 6月 18, 2010

[C言語・C++]OCI(Oracle Call Interface)サンプル(接続プール版)

次のテーブルを使用した接続プールのサンプルを示す。

CREATE TABLE TEST_TBL (
"NO" NUMBER(3), /* 番号 */
"DT_NUMBER" NUMBER(12,2), /* NUMBER型 */
"DT_CHAR" CHAR(10), /* CHAR型 */
"DT_VARCHAR2" VARCHAR2(32), /* VARCHAR2型 */
"DT_DATE" DATE /* DATE型 */
)

①追加のインクルードディレクトリ
インストールされたoracleパス\product\10.2.0\db_1\OCI\include

②追加のライブラリディレクトリ
インストールされたoracleパス\product\10.2.0\db_1\OCI\lib\MSVC

③追加の依存ファイル
oci.lib kernel32.lib msvcrt.lib



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>

typedef struct _OCI_TIMESTAMP_STRUCT
{
short year;
unsigned short month;
unsigned short day;
unsigned short hour;
unsigned short minute;
unsigned short second;
unsigned long fraction;
} OCI_TIMESTAMP_STRUCT_T;

typedef OCI_TIMESTAMP_STRUCT_T OCI_TIME;

static text *database = (text *)"データベース名";
static text *username = (text *)"ユーザー名";
static text *password = (text *)"パスワード";

static OraText *poolName;
static sb4 poolNameLen;

//static text *SEL_TEST_TBL = (text *) "SELECT * FROM TEST_TBL WHERE NO = :NO";
static text *SEL_TEST_TBL = (text *) "SELECT * FROM TEST_TBL ORDER BY NO";

static OCIEnv *envhp;
static OCIError *errhp;
OCICPool *poolhp;

OCIThreadId *thrid[MAXTHREAD];
OCIThreadHandle *thrhp[MAXTHREAD];
static int employeeNum[MAXTHREAD];

static sword checkerr( OCIError *errhp, sword status );
static void cleanup(/*_ void _*/);

sword OCI_DefineByPos( OCIStmt *stmtp, OCIDefine **defnp, OCIError *errhp,
ub4 position, dvoid *valuep, sb4 value_sz,
ub2 dty, dvoid *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode );
sword OCI_GetDataNumber( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCINumber *TargetValuePtr );
sword OCI_GetDataInt( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, int *TargetValuePtr );
sword OCI_GetDataShort( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, short *TargetValuePtr );
sword OCI_GetDataLong( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, long *TargetValuePtr );
sword OCI_GetDataFloat( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, float *TargetValuePtr );
sword OCI_GetDataDouble( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, double *TargetValuePtr );
sword OCI_GetDataChar( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, char *TargetValuePtr, unsigned int BufferLength );
sword OCI_GetDataTimeStamp( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCIDate *TargetValuePtr );
sword threadFunction( dvoid *arg );
void threadFunctionEnd( OCISvcCtx *svchp, OCIError *errhp, OCIStmt *stmthp, sword status );


int main( int argc, char* argv[] )
{
sword ret = 0;
sword no = 1;
int i = 0;

ub4 connMin = 1; // 最小接続プール数(有効値:0以上)
ub4 connMax = 5; // 最大接続プール数(有効値:1以上)
ub4 connIncr = 1; // 増分接続プール数(有効値:0以上)

OCIBind *bndhp[1]; // バインド・ハンドル
OCIDefine *defhp[6]; // 定義ハンドル

memset( bndhp, 0x00, sizeof( bndhp ) );
memset( defhp, 0x00, sizeof( defhp ) );

//ret = OCIInitialize( (ub4)(OCI_THREADED | OCI_OBJECT), (dvoid *)0,
// ( dvoid * (*)(dvoid *, size_t) )0,
// ( dvoid * (*)(dvoid *, dvoid *, size_t) )0,
// ( void (*)(dvoid *, dvoid *) )0 );
//if ( ret != OCI_SUCCESS ) {
// checkerr( NULL, ret );
// return ret;
//}

//ret = OCIEnvInit( (OCIEnv **)&envhp, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0 );
//if ( ret != OCI_SUCCESS ) {
// checkerr( NULL, ret );
// return ret;
//}

ret = OCIEnvCreate( (OCIEnv **)&envhp, (ub4)OCI_THREADED, (dvoid *)0,
( dvoid * (*)(dvoid *, size_t) )0,
( dvoid * (*)(dvoid *, dvoid *, size_t) )0,
( void (*)(dvoid *, dvoid *) )0, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
return ret;
}

ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **) &errhp, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
return ret;
}

// 接続プール・ハンドル割当て
ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&poolhp, (ub4)OCI_HTYPE_CPOOL, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
cleanup();
return ret;
}

/* CREATE THE CONNECTION POOL */
// OCI_DEFAULT:通常。
// OCI_CPOOL_REINITIALIZE:プール属性を動的に変更する場合(connMin、connMax、connIncrの各パラメータを変更する場合)。
ret = OCIConnectionPoolCreate( envhp, errhp, poolhp,
(OraText **)&poolName, (ub4 *)&poolNameLen,
(CONST OraText *)database, (ub4)strlen( (char*)database ),
connMin, connMax, connIncr,
(CONST OraText *)username, (ub4)strlen( (char*)username ),
(CONST OraText *)password, (ub4)strlen( (char*)password ),
OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}

{
OCIThreadProcessInit();

ret = OCIThreadInit( envhp, errhp );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}

for ( i = 0 ; i < MAXTHREAD ; i++ ) {
ret = OCIThreadIdInit( envhp, errhp, &thrid[i] );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}
ret = OCIThreadHndInit( envhp, errhp, &thrhp[i] );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}
}

for ( i = 0 ; i < MAXTHREAD ; i++ ) {
employeeNum[i] = i;
ret = OCIThreadCreate( envhp, errhp, threadFunction, (dvoid *)&employeeNum[i], thrid[i], thrhp[i] );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}
}

for ( i = 0 ; i < MAXTHREAD ; i++ ) {
// コールスレッド結合
checkerr( errhp, OCIThreadJoin( envhp, errhp, thrhp[i] ) );
// スレッド・ハンドルクローズ
checkerr( errhp, OCIThreadClose( envhp, errhp, thrhp[i] ) );
// スレッド・ハンドル破棄・割当て解除
checkerr( errhp, OCIThreadHndDestroy( envhp, errhp, &(thrhp[i]) ) );
// スレッドID破棄・割当て解除
checkerr( errhp, OCIThreadIdDestroy( envhp, errhp, &(thrid[i]) ) );
}

// OCIThreadコンテキスト割当てメモリー解放
checkerr( errhp, OCIThreadTerm( envhp, errhp ) );

if ( poolhp ) {
checkerr( errhp, OCIConnectionPoolDestroy( poolhp, errhp, (ub4)OCI_DEFAULT ) );
checkerr( NULL, OCIHandleFree( (dvoid *)poolhp, (ub4)OCI_HTYPE_CPOOL ) );
}
}

// 終了処理
cleanup();

return 0;
}

sword threadFunction( dvoid *arg )
{
sword ret = 0;
int out_no = 0;
OCINumber out_number;
int out_int = 0;
short out_short = 0;
long out_long = 0;
float out_float = 0;
double out_double = 0;
char out_char[10+1];
char out_varchar2[32+1];
OCIDate out_date;
OCI_TIME out_time;
long rows = 0;

int empno = *(int *)arg;
OCISvcCtx *svchp = (OCISvcCtx *)arg;
OCIStmt *stmthp = (OCIStmt *)0;

memset( out_char, 0x00, sizeof( out_char ) );
memset( out_varchar2, 0x00, sizeof( out_varchar2 ) );
memset( &out_date, 0x00, sizeof( out_date ) );
memset( &out_time, 0x00, sizeof( OCI_TIME ) );

/* ■データベース接続開始 */

// モード選択型ログイン
// OCI_DEFAULT:シングルセッション・ログイン。OCILogon()と同等。
// OCI_LOGON2_CPOOL:接続プーリングを使用する場合に設定する。
// OCI_LOGON2_SPOOL:セッション・プーリングを使用する場合に設定する。
// OCI_LOGON2_STMTCACHE:文キャッシュを使用可能にする。
// OCI_LOGON2_PROXY:プロキシ認証を使用可能にする。
ret = OCILogon2( envhp, errhp, (OCISvcCtx **)&svchp,
(CONST OraText *)username, (ub4)strlen( (char *)username ),
(CONST OraText *)password, (ub4)strlen( (char *)password ),
(CONST OraText *)poolName, (ub4)poolNameLen,
(ub4)OCI_LOGON2_CPOOL );
if ( ret != OCI_SUCCESS ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
return ret;
}

/* ■テーブル操作開始 */

// 文ハンドル割当て
ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&stmthp, (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
return ret;
}

// 実行するSQL文・PL/SQL文の準備
ret = OCIStmtPrepare( stmthp, errhp, (OraText *)SEL_TEST_TBL, (ub4)strlen( (char*)SEL_TEST_TBL ),
(ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
return ret;
}

/* ■WHERE句の変数定義 */

// 入力変数のバインド
//ret = OCIBindByName( stmthp, (OCIBind **)&bndhp[0], errhp,
// (OraText *)":NO", (sb4)strlen( ":NO" ), (dvoid *)&no, (sb4)sizeof( sword ),
// (ub2)SQLT_INT, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT );
//if ( ret != OCI_SUCCESS ) {
// checkerr( errhp, ret );
// return ret;
//}

// SQL文・PL/SQL文のサーバー送信実行
ret = OCIStmtExecute( svchp, stmthp, errhp, (ub4)0, (ub4)0,
(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
return ret;
}

/* ■出力変数の定義 */

// NUMBER(3,0)型データ取得
(void)OCI_GetDataInt( stmthp, errhp, 1, &out_no );

// NUMBER(12,2)型データ取得

// OCINumber型で取得
//(void)OCI_GetDataNumber( stmthp, errhp, 2, &out_number );

// int型で取得
(void)OCI_GetDataInt( stmthp, errhp, 2, &out_int );

// short型で取得
(void)OCI_GetDataShort( stmthp, errhp, 2, &out_short );

// long型で取得
(void)OCI_GetDataLong( stmthp, errhp, 2, &out_long );

// float型で取得
//(void)OCI_GetDataFloat( stmthp, errhp, 2, &out_float );

// double型で取得
//(void)OCI_GetDataDouble( stmthp, errhp, 2, &out_double );

// CHAR型データ取得
(void)OCI_GetDataChar( stmthp, errhp, 3, (char*)&out_char, sizeof( out_char ) );

// VARCHAR2型データ取得
(void)OCI_GetDataChar( stmthp, errhp, 4, (char*)&out_varchar2, sizeof( out_varchar2 ) );

// DATE型データ取得
(void)OCI_GetDataTimeStamp( stmthp, errhp, 5, &out_date );

// 問合せから行の読込み実行
ret = OCIStmtFetch( stmthp, errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
return ret;
}
else {
while ( (OCI_NO_DATA != ret) && (OCI_SUCCESS_WITH_INFO != ret) )
{
rows++;
printf( "[%03d],[%d],[%d],[%d],[%13.2f],[%13.2f],[%s],[%s],[%04d/%02d/%02d %02d:%02d:%02d]\n",
out_no, out_int, out_short, out_long, out_float, out_double, out_char, out_varchar2,
out_date.OCIDateYYYY, out_date.OCIDateMM, out_date.OCIDateDD, out_date.OCIDateTime.OCITimeHH, out_date.OCIDateTime.OCITimeMI, out_date.OCIDateTime.OCITimeSS );
// 問合せから行の読込み実行
ret = OCIStmtFetch( stmthp, errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
if ( OCI_NO_DATA != ret ) {
threadFunctionEnd( svchp, errhp, stmthp, ret );
break;
}
}
}
}

return ret;
}

/*
* スレッド処理.
*/
void threadFunctionEnd( OCISvcCtx *svchp, OCIError *errhp, OCIStmt *stmthp, sword status )
{
sword ret = 0;

checkerr( errhp, status );

if ( stmthp ) {
// 文ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT ) );
}

/* ■データベース接続終了 */

// シングルセッション・ログオフ
ret = OCILogoff( svchp, errhp );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}

}

/*
* チェックエラー処理.
*/
sword checkerr( OCIError *errhp, sword status )
{
text errbuf[512];
sb4 errcode = 0;

switch ( status )
{
case OCI_SUCCESS:
// 関数は正常に終了しました。
break;
case OCI_SUCCESS_WITH_INFO:
// 関数は正常に終了しました。OCIErrorGet()をコールすると、追加診断情報が戻されます。
// これには、警告が含まれる場合があります。
(void)printf( "Error - OCI_SUCCESS_WITH_INFO\n" );
break;
case OCI_NEED_DATA:
// アプリケーションで、ランタイム・データを提供する必要があります。
(void)printf( "Error - OCI_NEED_DATA\n" );
break;
case OCI_NO_DATA:
// 関数が終了しました。これ以上データはありません。
(void)printf( "Error - OCI_NODATA\n" );
break;
case OCI_ERROR:
// 関数が失敗しました。OCIErrorGet()をコールすると、エラーの追加情報が戻されます。
if ( errhp ) {
(void)OCIErrorGet( (dvoid *)errhp, (ub4)1, (text *)NULL, &errcode, errbuf, (ub4)sizeof( errbuf ), OCI_HTYPE_ERROR );
(void)printf( "Error - %.*s\n", 512, errbuf );
}
else {
(void)printf( "Error - OCI_ERROR\n" );
}
break;
case OCI_INVALID_HANDLE:
// 無効なハンドルがパラメータとして渡されたか、ユーザー・コールバックで無効なハンドルまたは無効なコンテキストが渡されました。
// 追加診断情報はありません。
(void)printf( "Error - OCI_INVALID_HANDLE\n" );
break;
case OCI_STILL_EXECUTING:
// サービス・コンテキストが非ブロック化モードで確立されたため、現行の操作は即時完了できませんでした。
// この操作を完了するには、これを再度コールする必要があります。OCIErrorGet()がエラー・コードとしてORA-03123を戻します。
(void)printf( "Error - OCI_STILL_EXECUTE\n" );
break;
case OCI_CONTINUE:
// このコードはコールバック関数からのみ戻されます。
// これは、コールバック関数が、OCIライブラリの標準処理再開を示唆していることを示します。
(void)printf( "Error - OCI_CONTINUE\n" );
break;
default:
break;
}
return status;
}

/*
* 終了処理.
*/
void cleanup()
{
int i = 0;

if ( errhp ) {
// エラー・ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)errhp, (ub4)OCI_HTYPE_ERROR ) );
}
if ( envhp ) {
// 環境ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)envhp, (ub4)OCI_HTYPE_ENV ) );
}
// プロセスの終了と共有メモリー解放
checkerr( NULL, OCITerminate( OCI_DEFAULT ) );
return;
}

/*
* 出力変数定義処理.
*/
sword OCI_DefineByPos( OCIStmt *stmtp, OCIDefine **defhp, OCIError *errhp,
ub4 position, dvoid *valuep, sb4 value_sz,
ub2 dty, dvoid *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode )
{
sword ret = OCIDefineByPos( stmtp, defhp, errhp, position, valuep, value_sz, dty, indp, rlenp, rcodep, mode );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}
return ret;
}


/*
* OCINumber型データ取得処理.
*/
sword OCI_GetDataNumber( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCINumber *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( OCINumber ), SQLT_VNU, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* int型データ取得処理.
*/
sword OCI_GetDataInt( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, int *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( int ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* short型データ取得処理.
*/
sword OCI_GetDataShort( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, short *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( short ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* long型データ取得処理.
*/
sword OCI_GetDataLong( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, long *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( long ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* float型データ取得処理.
*/
sword OCI_GetDataFloat( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, float *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( float ), SQLT_BFLOAT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* double型データ取得処理.
*/
sword OCI_GetDataDouble( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, double *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( double ), SQLT_BDOUBLE, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* char型データ取得処理.
*/
sword OCI_GetDataChar( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, char *TargetValuePtr, unsigned int BufferLength )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

memset( TargetValuePtr, 0x00, BufferLength );

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)BufferLength, SQLT_STR, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* OCIDate型データ取得処理.
*/
sword OCI_GetDataTimeStamp( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCIDate *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid *)TargetValuePtr, (sb4)sizeof( OCIDate ), SQLT_ODT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}



水曜日, 6月 16, 2010

[C言語・C++]OCIで次のエラー?!「kgepop: no error frame to pop to for error 21500」

▼質問
OCIThreadからOCIConnectionPoolを使ってOCILogon2にログインすると次のエラーが出るんだ。

「kgepop: no error frame to pop to for error 21500」

どうしてこうなるか教えてくれ!!

▼回答
OCIInitialize()をコールした時のmodeを確認してくれ!!

OCIThreadを使う時のmodeは、次の様な指定の仕方にするんだ。

「(ub4)(OCI_THREADED | OCI_OBJECT)」

OCIInitialize( (ub4)(OCI_THREADED | OCI_OBJECT), (dvoid *)0,
         ( dvoid * (*)(dvoid *, size_t) )0,
         ( dvoid * (*)(dvoid *, dvoid *, size_t) )0,
         ( void (*)(dvoid *, dvoid *) )0 );

OCIEnvCreate()をコールした時の指定の仕方。

OCIEnvCreate( (OCIEnv **)&envhp, (ub4)OCI_THREADED, (dvoid *)0,
( dvoid * (*)(dvoid *, size_t) )0,
( dvoid * (*)(dvoid *, dvoid *, size_t) )0,
( void (*)(dvoid *, dvoid *) )0, (size_t)0, (dvoid **)0 );

■参考サイト
Re: kgepop: no error frame to pop to for error 21500
Oracle ABC Wiki: Ora 19999 Ora 24279 Jp


[C言語・C++]OCI(Oracle Call Interface)サンプル(OCILogon版)

次のテーブルを使用したシングルセッション・ログイン(OCILogon)のサンプルを示す。

CREATE TABLE TEST_TBL (
"NO" NUMBER(3), /* 番号 */
"DT_NUMBER" NUMBER(12,2), /* NUMBER型 */
"DT_CHAR" CHAR(10), /* CHAR型 */
"DT_VARCHAR2" VARCHAR2(32), /* VARCHAR2型 */
"DT_DATE" DATE /* DATE型 */
)

①追加のインクルードディレクトリ
インストールされたoracleパス\product\10.2.0\db_1\OCI\include

②追加のライブラリディレクトリ
インストールされたoracleパス\product\10.2.0\db_1\OCI\lib\MSVC

③追加の依存ファイル
oci.lib kernel32.lib msvcrt.lib




#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>

typedef struct _OCI_TIMESTAMP_STRUCT
{
short year;
unsigned short month;
unsigned short day;
unsigned short hour;
unsigned short minute;
unsigned short second;
unsigned long fraction;
} OCI_TIMESTAMP_STRUCT_T;

typedef OCI_TIMESTAMP_STRUCT_T OCI_TIME;

static text *database = (text *)"データベース名";
static text *username = (text *)"ユーザー名";
static text *password = (text *)"パスワード";

//static text *SEL_TEST_TBL = (text *) "SELECT * FROM TEST_TBL WHERE NO = :NO";
static text *SEL_TEST_TBL = (text *) "SELECT * FROM TEST_TBL ORDER BY NO";

static OCIEnv *envhp;
static OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;

static sword checkerr( OCIError *errhp, sword status );
static void cleanup(/*_ void _*/);

sword OCI_DefineByPos( OCIStmt *stmtp, OCIDefine **defnp, OCIError *errhp,
ub4 position, dvoid *valuep, sb4 value_sz,
ub2 dty, dvoid *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode );
sword OCI_GetDataNumber( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCINumber *TargetValuePtr );
sword OCI_GetDataInt( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, int *TargetValuePtr );
sword OCI_GetDataShort( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, short *TargetValuePtr );
sword OCI_GetDataLong( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, long *TargetValuePtr );
sword OCI_GetDataFloat( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, float *TargetValuePtr );
sword OCI_GetDataDouble( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, double *TargetValuePtr );
sword OCI_GetDataChar( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, char *TargetValuePtr, unsigned int BufferLength );
sword OCI_GetDataTimeStamp( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCIDate *TargetValuePtr );


int main( int argc, char* argv[] )
{
sword ret = 0;
sword no = 1;
int out_no = 0;
OCINumber out_number;
int out_int = 0;
short out_short = 0;
long out_long = 0;
float out_float = 0;
double out_double = 0;
char out_char[10+1];
char out_varchar2[32+1];
OCIDate out_date;
OCI_TIME out_time;
long rows = 0;

OCIBind *bndhp[1]; // バインド・ハンドル
OCIDefine *defhp[6]; // 定義ハンドル

memset( bndhp, 0x00, sizeof( bndhp ) );
memset( defhp, 0x00, sizeof( defhp ) );
memset( out_char, 0x00, sizeof( out_char ) );
memset( out_varchar2, 0x00, sizeof( out_varchar2 ) );
memset( &out_date, 0x00, sizeof( out_date ) );
memset( &out_time, 0x00, sizeof( OCI_TIME ) );

ret = OCIInitialize( (ub4)OCI_DEFAULT, (dvoid *)0,
( dvoid * (*)(dvoid *, size_t) )0,
( dvoid * (*)(dvoid *, dvoid *, size_t) )0,
( void (*)(dvoid *, dvoid *) )0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
return ret;
}

ret = OCIEnvInit( (OCIEnv **)&envhp, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
return ret;
}

ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **) &errhp, (ub4)OCI_HTYPE_ERROR, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
return ret;
}

/* ■データベース接続開始 */

// サーバー・コンテキスト・ハンドル割当て
ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&svchp, (ub4)OCI_HTYPE_SVCCTX, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( NULL, ret );
cleanup();
return ret;
}

// シングルセッション・ログイン
ret = OCILogon( envhp, errhp, (OCISvcCtx **)&svchp,
(OraText *)username, (ub4)strlen( (char *)username ),
(OraText *)password, (ub4)strlen( (char *)password ),
(OraText *)database, (ub4)strlen( (char*)database ) );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}

/* ■テーブル操作開始 */

// 文ハンドル割当て
ret = OCIHandleAlloc( (dvoid *)envhp, (dvoid **)&stmthp, (ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0 );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}

// 実行するSQL文・PL/SQL文の準備
ret = OCIStmtPrepare( stmthp, errhp, (OraText *)SEL_TEST_TBL, (ub4)strlen( (char*)SEL_TEST_TBL ),
(ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}

/* ■WHERE句の変数定義 */

// 入力変数のバインド
//ret = OCIBindByName( stmthp, (OCIBind **)&bndhp[0], errhp,
// (OraText *)":NO", (sb4)strlen( ":NO" ), (dvoid *)&no, (sb4)sizeof( sword ),
// (ub2)SQLT_INT, (dvoid *)0, (ub2 *)0, (ub2 *)0, (ub4)0, (ub4 *)0, (ub4)OCI_DEFAULT );
//if ( ret != OCI_SUCCESS ) {
// checkerr( errhp, ret );
// cleanup();
// return ret;
//}

// SQL文・PL/SQL文のサーバー送信実行
ret = OCIStmtExecute( svchp, stmthp, errhp, (ub4)0, (ub4)0,
(CONST OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}

/* ■出力変数の定義 */

// NUMBER(3,0)型データ取得
(void)OCI_GetDataInt( stmthp, errhp, 1, &out_no );

// NUMBER(12,2)型データ取得

// OCINumber型で取得
//(void)OCI_GetDataNumber( stmthp, errhp, 2, &out_number );

// int型で取得
(void)OCI_GetDataInt( stmthp, errhp, 2, &out_int );

// short型で取得
(void)OCI_GetDataShort( stmthp, errhp, 2, &out_short );

// long型で取得
(void)OCI_GetDataLong( stmthp, errhp, 2, &out_long );

// float型で取得
//(void)OCI_GetDataFloat( stmthp, errhp, 2, &out_float );

// double型で取得
//(void)OCI_GetDataDouble( stmthp, errhp, 2, &out_double );

// CHAR型データ取得
(void)OCI_GetDataChar( stmthp, errhp, 3, (char*)&out_char, sizeof( out_char ) );

// VARCHAR2型データ取得
(void)OCI_GetDataChar( stmthp, errhp, 4, (char*)&out_varchar2, sizeof( out_varchar2 ) );

// DATE型データ取得
(void)OCI_GetDataTimeStamp( stmthp, errhp, 5, &out_date );

// 問合せから行の読込み実行
ret = OCIStmtFetch( stmthp, errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}
else {
while ( (OCI_NO_DATA != ret) && (OCI_SUCCESS_WITH_INFO != ret) )
{
rows++;
printf( "[%03d],[%d],[%d],[%d],[%13.2f],[%13.2f],[%s],[%s],[%04d/%02d/%02d %02d:%02d:%02d]\n",
out_no, out_int, out_short, out_long, out_float, out_double, out_char, out_varchar2,
out_date.OCIDateYYYY, out_date.OCIDateMM, out_date.OCIDateDD, out_date.OCIDateTime.OCITimeHH, out_date.OCIDateTime.OCITimeMI, out_date.OCIDateTime.OCITimeSS );
// 問合せから行の読込み実行
ret = OCIStmtFetch( stmthp, errhp, (ub4)1, (ub2)OCI_FETCH_NEXT, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
if ( OCI_NO_DATA != ret ) {
checkerr( errhp, ret );
}
}
}
}

/* ■データベース接続終了 */

// シングルセッション・ログオフ
ret = OCILogoff( svchp, errhp );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
}

// 終了処理
cleanup();

return 0;
}


/*
* チェックエラー処理.
*/
sword checkerr( OCIError *errhp, sword status )
{
text errbuf[512];
sb4 errcode = 0;

switch ( status )
{
case OCI_SUCCESS:
// 関数は正常に終了しました。
break;
case OCI_SUCCESS_WITH_INFO:
// 関数は正常に終了しました。OCIErrorGet()をコールすると、追加診断情報が戻されます。
// これには、警告が含まれる場合があります。
(void)printf( "Error - OCI_SUCCESS_WITH_INFO\n" );
break;
case OCI_NEED_DATA:
// アプリケーションで、ランタイム・データを提供する必要があります。
(void)printf( "Error - OCI_NEED_DATA\n" );
break;
case OCI_NO_DATA:
// 関数が終了しました。これ以上データはありません。
(void)printf( "Error - OCI_NODATA\n" );
break;
case OCI_ERROR:
// 関数が失敗しました。OCIErrorGet()をコールすると、エラーの追加情報が戻されます。
if ( errhp ) {
(void)OCIErrorGet( (dvoid *)errhp, (ub4)1, (text *)NULL, &errcode, errbuf, (ub4)sizeof( errbuf ), OCI_HTYPE_ERROR );
(void)printf( "Error - %.*s\n", 512, errbuf );
}
else {
(void)printf( "Error - OCI_ERROR\n" );
}
break;
case OCI_INVALID_HANDLE:
// 無効なハンドルがパラメータとして渡されたか、ユーザー・コールバックで無効なハンドルまたは無効なコンテキストが渡されました。
// 追加診断情報はありません。
(void)printf( "Error - OCI_INVALID_HANDLE\n" );
break;
case OCI_STILL_EXECUTING:
// サービス・コンテキストが非ブロック化モードで確立されたため、現行の操作は即時完了できませんでした。
// この操作を完了するには、これを再度コールする必要があります。OCIErrorGet()がエラー・コードとしてORA-03123を戻します。
(void)printf( "Error - OCI_STILL_EXECUTE\n" );
break;
case OCI_CONTINUE:
// このコードはコールバック関数からのみ戻されます。
// これは、コールバック関数が、OCIライブラリの標準処理再開を示唆していることを示します。
(void)printf( "Error - OCI_CONTINUE\n" );
break;
default:
break;
}
return status;
}

/*
* 終了処理.
*/
void cleanup()
{
if ( stmthp ) {
// 文ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)stmthp, (ub4)OCI_HTYPE_STMT ) );
}
if ( svchp ) {
// サーバー・コンテキスト・ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)svchp, (ub4)OCI_HTYPE_SVCCTX ) );
}
if ( errhp ) {
// エラー・ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)errhp, (ub4)OCI_HTYPE_ERROR ) );
}
if ( envhp ) {
// 環境ハンドル解放
checkerr( NULL, OCIHandleFree( (dvoid *)envhp, (ub4)OCI_HTYPE_ENV ) );
}
// プロセスの終了と共有メモリー解放
checkerr( NULL, OCITerminate( OCI_DEFAULT ) );
return;
}

/*
* 出力変数定義処理.
*/
sword OCI_DefineByPos( OCIStmt *stmtp, OCIDefine **defhp, OCIError *errhp,
ub4 position, dvoid *valuep, sb4 value_sz,
ub2 dty, dvoid *indp, ub2 *rlenp, ub2 *rcodep, ub4 mode )
{
sword ret = OCIDefineByPos( stmtp, defhp, errhp, position, valuep, value_sz, dty, indp, rlenp, rcodep, mode );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
cleanup();
return ret;
}
return ret;
}


/*
* OCINumber型データ取得処理.
*/
sword OCI_GetDataNumber( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCINumber *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( OCINumber ), SQLT_VNU, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* int型データ取得処理.
*/
sword OCI_GetDataInt( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, int *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( int ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* short型データ取得処理.
*/
sword OCI_GetDataShort( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, short *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( short ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* long型データ取得処理.
*/
sword OCI_GetDataLong( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, long *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( long ), SQLT_INT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* float型データ取得処理.
*/
sword OCI_GetDataFloat( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, float *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( float ), SQLT_BFLOAT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* double型データ取得処理.
*/
sword OCI_GetDataDouble( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, double *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)sizeof( double ), SQLT_BDOUBLE, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* char型データ取得処理.
*/
sword OCI_GetDataChar( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, char *TargetValuePtr, unsigned int BufferLength )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

memset( TargetValuePtr, 0x00, BufferLength );

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid*)TargetValuePtr, (sb4)BufferLength, SQLT_STR, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}

/*
* OCIDate型データ取得処理.
*/
sword OCI_GetDataTimeStamp( OCIStmt *stmtp, OCIError *errhp, int ColumnNumber, OCIDate *TargetValuePtr )
{
sword ret = 0;
OCIDefine *defhp = NULL; // 定義ハンドル

ret = OCIDefineByPos( stmtp, (OCIDefine **)&defhp, errhp, (ub4)ColumnNumber, (dvoid *)TargetValuePtr, (sb4)sizeof( OCIDate ), SQLT_ODT, (dvoid *)0, (ub2)0, (ub2)0, (ub4)OCI_DEFAULT );
if ( ret != OCI_SUCCESS ) {
checkerr( errhp, ret );
return ret;
}

return ret;
}




This page is powered by Blogger. Isn't yours?