PolarDB Oracle Call Interface (OCI) ドライバーは、PolarDB for PostgreSQL (Oracle 互換) 用のネイティブ C 言語インターフェイスです。これを使用して、ご利用のクラスターへの接続、クエリ文の実行、SQL 関数呼び出しを行うことができます。また、Java Database Connectivity (JDBC)、.NET、オープンデータベースコネクティビティ (ODBC) ドライバーなどの高レベルインターフェイスを構築するための基盤としても使用できます。
現在のドライバーのバージョンは PostgreSQL 3.0 です。
前提条件
開始する前に、以下が準備されていることを確認してください。
ご利用の PolarDB クラスターのデータベースアカウント。詳細については、「データベースアカウントの作成」をご参照ください。
クラスターのホワイトリストに追加されたホストの IP アドレス。詳細については、「クラスターのホワイトリストの設定」をご参照ください。
64 ビットの Linux または Windows オペレーティングシステム。
Oracle OCI ドライバー開発キットがインストールされていること。
POLARDB OCI ドライバーのダウンロード
ドライバーパッケージをダウンロードします: polardb-oci.tar.gz
POLARDB OCI ドライバーのインストール
ドライバーパッケージを展開し、ライブラリファイルをシステムにコピーして、コンパイラがそれらを見つけられるように環境変数を設定します。
Linux
次のファイルを
/usr/libにコピーします。libpolaroci.so.10.2libiconv.so.2libpq.so.5.11
シンボリックリンクを作成します。
ln -s /usr/lib/libpolaroci.so.10.2 /usr/lib/libpolaroci.so ln -s /usr/lib/libiconv.so.2 /usr/lib/libiconv.so ln -s /usr/lib/libpq.so.5.11 /usr/lib/libpq.so ln -s /usr/lib/libpq.so.5.11 /usr/lib/libpq.so.5ライブラリパスの環境変数を設定します。
export LD_LIBRARY_PATH=/usr/lib
システムにlibiconv.soファイルが既に存在する場合は、それらを直接使用してください。または、libiconv ドキュメントから libiconv をダウンロード、コンパイル、インストールし、コンパイルされた.soファイルを使用することもできます。PolarDB OCI ドライバーパッケージに含まれるlibiconv.soファイルは、参照用にのみ提供されています。
Windows
このセクションでは、Visual Studio を例として使用します。
Visual Studio でドライバーのリンクファイルパスを追加して、環境変数を設定します。
プロジェクトのプロパティページで、左側のナビゲーションにある [リンカー] > [全般] を展開し、[追加のライブラリ ディレクトリ] 設定項目を見つけます。
プロジェクトのプロパティタブで、ドライバーディレクトリ内の
.dllファイルを [追加のライブラリ ディレクトリ] に追加します。
接続パラメーター
コードを記述する前に、ご利用の PolarDB クラスターに関する以下の情報を収集してください。
| パラメーター | 例 | 説明 |
|---|---|---|
text *username | (text *) "postgres" | PolarDB クラスターのユーザー名 |
text *passwd | (text *) "" | ユーザー名のパスワード |
text *server | (text *) "//localhost:5432" | PolarDB クラスターのエンドポイントとポート。接続情報の確認方法については、「エンドポイントの表示または申請」をご参照ください。 |
接続文字列のフォーマットは //host:port/database です。デモでは、デフォルト値は //localhost:5432/postgres です。
コードの記述
ドライバーパッケージ内の polardb_demo サンプルは、クラスターへの接続、テーブルの作成、データの挿入、結果セットのクエリ、IN OUT および OUT パラメーターを持つストアドプロシージャの呼び出し、そしてクリーンアップという一連のワークフローを示しています。
すべての例では、標準の OCI ハンドル初期化シーケンス (環境ハンドル → エラーハンドル → サービスコンテキストハンドル → セッションハンドル → サーバーハンドル) を使用しています。
/* ============================================================================
* Copyright (c) 2004-2019 POLARDB Corporation. All Rights Reserved.
* ===========================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oci.h>
#ifdef WIN32
#include <time.h>
#else
#include <sys/time.h>
#endif
/* エラーを処理するためのマクロを定義 */
#define HANDLE_ERROR(x,y) check_oci_error(x,y)
#define DATE_FMT "DAY, MONTH DD, YYYY"
#define DATE_LANG "American"
sword ConvertStringToDATE( char *datep, char *formatp, dvoid *datepp );
/* エラーを処理するカスタムルーチン */
/* OCI でのエラー/例外処理を示します */
void check_oci_error (dvoid * errhp, sword status);
/*
* <<<<<<<<<<<<<<<<<<< 関数のプロトタイプ<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
*/
/* すべてのハンドルを初期化および割り当て */
void
initHandles (OCISvcCtx **, OCIServer **, OCISession **, OCIError **,
OCIEnv **);
/* データベースにログインし、ユーザーセッションを開始 */
void
logon (OCISvcCtx **, OCIServer **, OCISession **, OCIError **,
OCIEnv **, text *, text *, text *);
/* 必要なテーブルを作成 */
void create_table (OCISvcCtx *, OCIError *, OCIEnv *);
/* サンプルのデータを準備 */
void prepare_data (OCISvcCtx *, OCIError *, OCIEnv *);
/* サンプルで実証するためのプロシージャ/関数を作成 */
void create_stored_procs (OCISvcCtx *, OCIError *, OCIEnv *);
/* resultSet を反復処理してデータを選択および出力 */
void select_print_data (OCISvcCtx *, OCIError *, OCIEnv *);
/* ストアドプロシージャの呼び出しと値の取得を実証 */
/* proc1 は IN OUT を実証 */
void call_stored_proc1 (OCISvcCtx *, OCIError *, OCIEnv *);
/* proc2 は OUT を実証 */
void call_stored_proc2 (OCISvcCtx *, OCIError *, OCIEnv *);
/* 必要なテーブルを削除 */
void drop_table (OCISvcCtx *, OCIError *, OCIEnv *);
/* ストアドプロシージャと関数を削除 */
void drop_stored_procs (OCISvcCtx *, OCIError *, OCIEnv *);
/* 終了前にメインハンドルをクリーンアップ */
void
cleanup (OCISvcCtx **, OCIServer **, OCISession **, OCIError **, OCIEnv **);
/*
* <<<<<<<<<<<<<<<<<<<<<<<<< 関数のプロトタイプの終わり<<<<<<<<<<<<<<<<<<<<<<<<<<
*/
/* <<<<<<<<<< グローバル変数 */
ub4 init_mode = OCI_DEFAULT;
ub4 auth_mode = OCI_CRED_RDBMS;
/* <<<<<<<<<< グローバル変数の終わり */
int
main (void)
{
/*
* ハンドルの宣言。一般的な OCI プログラムでは、少なくとも
* 次のハンドルが必要です:環境ハンドル、エラーハンドル、サービスコンテキスト
* ハンドル、サーバーハンドル、ユーザーセッション (認証ハンドル)
*/
/* 環境 */
OCIEnv *envhp;
/* エラー */
OCIError *errhp;
/* サービスコンテキスト */
OCISvcCtx *svchp;
/* サーバー */
OCIServer *srvhp;
/* セッション (認証) */
OCISession *authp;
/*
* ハンドル宣言の終わり
*/
/*
* ローカル変数の宣言
*/
text *username = (text *) "parallels";
text *passwd = (text *) "";
/*
* Oracle Instant Client 接続文字列
*/
text *server = (text *) "//localhost:5432/postgres";
/*
* ハンドルの初期化と割り当て
*/
initHandles (&svchp, &srvhp, &authp, &errhp, &envhp);
/*
* データベースへのログイン
*/
logon (&svchp, &srvhp, &authp, &errhp, &envhp, username, passwd, server);
/*
* このサンプルに必要なテーブルを作成
*/
create_table (svchp, errhp, envhp);
/*
* テーブルにデータを挿入
*/
prepare_data (svchp, errhp, envhp);
/*
* ストアドプロシージャと関数を作成
*/
create_stored_procs (svchp, errhp, envhp);
/*
* 単純な resultSet を反復処理してデータを選択および出力
*/
select_print_data (svchp, errhp, envhp);
/*
* ストアドプロシージャの呼び出しと値の取得を実証
*/
call_stored_proc1 (svchp, errhp, envhp);
/*
* OUT パラメーターを実証
*/
call_stored_proc2 (svchp, errhp, envhp);
/*
* このサンプルで使用したテーブルを削除
*/
drop_table (svchp, errhp, envhp);
/*
* このサンプルで使用したストアドプロシージャと関数を削除
*/
drop_stored_procs (svchp, errhp, envhp);
/*
* リソースをクリーンアップ
*/
cleanup (&svchp, &srvhp, &authp, &errhp, &envhp);
return 0;
}
/* エラーを処理するカスタムルーチン */
/* OCI でのエラー/例外処理を示します */
void
check_oci_error (dvoid * errhp, sword status)
{
text errbuf[512];
sb4 errcode;
if (status == OCI_SUCCESS)
{
return;
}
switch (status)
{
case OCI_SUCCESS_WITH_INFO:
printf ("OCI_SUCCESS_WITH_INFO:\n");
OCIErrorGet (errhp, (ub4) 1, (text *) 0, &errcode,
errbuf, (ub4) sizeof (errbuf), OCI_HTYPE_ERROR);
printf ("%s", errbuf);
break;
case OCI_NEED_DATA:
printf ("Error - OCI_NEED_DATA\n");
break;
case OCI_NO_DATA:
printf ("Error - OCI_NO_DATA\n");
break;
case OCI_ERROR:
printf ("Error - OCI_ERROR:\n");
OCIErrorGet (errhp, (ub4) 1, (text *) 0, &errcode,
errbuf, (ub4) sizeof (errbuf), OCI_HTYPE_ERROR);
printf ("%s", errbuf);
break;
case OCI_INVALID_HANDLE:
printf ("Error - OCI_INVALID_HANDLE\n");
break;
case OCI_STILL_EXECUTING:
printf ("Error - OCI_STILL_EXECUTING\n");
break;
case OCI_CONTINUE:
printf ("Error - OCI_CONTINUE\n");
break;
default:
break;
}
/*
* アプリケーションを終了
*/
exit((int)status);
}
/* 必要なハンドルを初期化および割り当て */
void
initHandles (OCISvcCtx ** svchp, OCIServer ** srvhp, OCISession ** authp,
OCIError ** errhp, OCIEnv ** envhp)
{
/*
* ここから、基本的なハンドルの初期化と割り当てを行うセクションを開始します。
* これは、データベースにログインして作業を進める前に必要な、必須のセットアップまたは初期化です。
* この初期化と準備には、次の手順が含まれます
*
* 1. OCI の初期化 (OCIInitialize())
* 2. 環境の初期化 (OCIEnvInit())
* 3. エラーハンドルの初期化と割り当て
* 4. サービスコンテキストハンドルの初期化と割り当て
* 5. セッションハンドルの初期化と割り当て
* 6. サーバーハンドルの初期化と割り当て
*
* 新しいバージョンの OCI では、OCIInitialize() と OCIEnvInit() を使用する代わりに、
* OCIEnvCreate() という 1 つの API 呼び出しでこれを行うことができます。
*/
/*
* OCI の初期化
*/
if (OCIInitialize (init_mode, (dvoid *) 0,
(dvoid * (*)(dvoid *, size_t)) 0,
(dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
(void (*)(dvoid *, dvoid *)) 0) != OCI_SUCCESS)
{
printf ("ERROR: failed to initialize OCI\n");
exit (1);
}
/*
* 環境の初期化
*/
HANDLE_ERROR (*envhp,
OCIEnvInit (&(*envhp), OCI_DEFAULT, (size_t) 0,
(dvoid **) 0));
/*
* エラーハンドルの初期化と割り当て
*/
HANDLE_ERROR (*envhp,
OCIHandleAlloc (*envhp, (dvoid **) & (*errhp),
OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0));
/*
* サービスコンテキストハンドルの初期化と割り当て
*/
HANDLE_ERROR (*errhp,
OCIHandleAlloc (*envhp, (dvoid **) & (*svchp),
OCI_HTYPE_SVCCTX, (size_t) 0, (dvoid **) 0));
/*
* セッションハンドルの初期化と割り当て
*/
HANDLE_ERROR (*errhp,
OCIHandleAlloc (*envhp, (dvoid **) & (*authp),
OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0));
/*
* サーバーハンドルの初期化と割り当て
*/
HANDLE_ERROR (*errhp,
OCIHandleAlloc (*envhp, (dvoid **) & (*srvhp),
OCI_HTYPE_SERVER, (size_t) 0, (dvoid **) 0));
}
void
logon (OCISvcCtx ** svchp, OCIServer ** srvhp, OCISession ** authp,
OCIError ** errhp, OCIEnv ** envhp, text * username, text * passwd,
text * server)
{
/*
* ここから、データベースサーバーへのログインを開始します。これには 2 つのステップが含まれます
*
* 1. サーバーへのアタッチ
* 2. セッションの開始
*
* これは複雑なログインです。簡単なログイン方法は、サーバーアタッチとセッション開始を避け、
* 単に OCILogon() または OCILogon2() を使用し、OCILogoff() を使用してログオフすることです。
*/
/*
* サーバーにアタッチ
*/
HANDLE_ERROR (*errhp,
OCIServerAttach (*srvhp, *errhp, server,
(ub4) strlen ((char *) server),
OCI_DEFAULT));
/*
* 次のコードはセッションを開始しますが、セッションを開始する前に、次のことを行う必要があります
* 1. 現在アタッチされているサーバーハンドルをサービスコンテキストハンドルに設定する
* 2. ユーザー名とパスワードをセッションハンドルに設定する
*/
/*
* サーバーハンドルをサービスコンテキストハンドルに設定する
*/
HANDLE_ERROR (*errhp,
OCIAttrSet (*svchp, OCI_HTYPE_SVCCTX,
(dvoid *) (*srvhp), (ub4) 0, OCI_ATTR_SERVER,
*errhp));
/*
* ユーザー名とパスワードをセッションハンドルに設定する
*/
HANDLE_ERROR (*errhp,
OCIAttrSet (*authp, OCI_HTYPE_SESSION,
(dvoid *) username,
(ub4) strlen ((char *) username),
OCI_ATTR_USERNAME, *errhp));
HANDLE_ERROR (*errhp,
OCIAttrSet (*authp, OCI_HTYPE_SESSION, (dvoid *) passwd,
(ub4) strlen ((char *) passwd), OCI_ATTR_PASSWORD,
*errhp));
/*
* そして、最後にセッションを開始します
*/
HANDLE_ERROR ((*errhp),
OCISessionBegin (*svchp, *errhp,
*authp, auth_mode, OCI_DEFAULT));
printf ("********************************************\n");
printf ("Milestone : Logged on as --> '%s'\n", username);
printf ("********************************************\n");
/*
* セッションを開始した後、セッション
*/
/*
* (認証) ハンドルをサービスコンテキストハンドルに設定する必要があります
*/
HANDLE_ERROR (*errhp,
OCIAttrSet (*svchp, OCI_HTYPE_SVCCTX,
(dvoid *) (*authp), (ub4) 0,
OCI_ATTR_SESSION, *errhp));
}
/* このサンプルに必要なテーブルを作成 */
void
create_table (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *stmhp;
text *create_statement =
(text *)"CREATE TABLE OCISPEC \n (ENAME VARCHAR2(20)\n, MGR NUMBER\n, HIREDATE DATE)";
ub4 status = OCI_SUCCESS;
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* CREATE 文を準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp,
create_statement,
strlen ((const char *) create_statement),
OCI_NTV_SYNTAX, OCI_DEFAULT));
/*
* CREATE 文を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN CREATING TABLE(S)\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Table(s) Successfully created\n");
printf ("********************************************\n");
}
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
}
/* サンプルのデータを準備 */
void
prepare_data (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *stmhp;
text *insstmt =
(text *)
"INSERT INTO OCISPEC (ename,mgr, hiredate) VALUES (:ENAME,:MGR, CAST(:HIREDATE AS timestamp))";
OCIBind *bnd1p = (OCIBind *) 0; /* 最初のバインドハンドル */
OCIBind *bnd2p = (OCIBind *) 0; /* 2 番目のバインドハンドル */
OCIBind *bnd3p = (OCIBind *) 0; /* 3 番目のバインドハンドル */
ub4 status = OCI_SUCCESS;
int i = 0;
char *ename[3] = { "SMITH", "ALLEN", "KING" };
sword mgr[] = { 7886, 7110, 7221 };
char *date_buffer[3] = { "02-AUG-07", "02-APR-07", "02-MAR-07" };
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* INSERT 文を準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp, insstmt,
(ub4) strlen ((char *) insstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
/*
* このループでは、配列からデータをバインドしてデータベースに複数の行を挿入します。
* これを行うためのより洗練された良い方法は、配列バインディング (バッチ挿入) を使用することです。
* PolarDB OCI Replacement Library は、ここでは使用されていませんが、配列バインディングをサポートします。
*/
for (i = 0; i < 3; i++)
{
/*
* ENAME の変数をバインド
*/
HANDLE_ERROR (errhp,
OCIBindByName (stmhp, &bnd1p, errhp, (text *) ":ENAME",
-1, (dvoid *) ename[i],
(sb4) strlen (ename[i]) + 1, SQLT_STR,
(dvoid *) 0, 0, (ub2 *) 0, (ub4) 0,
(ub4 *) 0, OCI_DEFAULT));
/*
* MGR の変数をバインド
*/
HANDLE_ERROR (errhp,
OCIBindByName (stmhp, &bnd2p, errhp, (text *) ":MGR",
-1, (dvoid *) & mgr[i], sizeof (mgr[i]),
SQLT_INT, (dvoid *) 0, 0, (ub2 *) 0,
(ub4) 0, (ub4 *) 0, OCI_DEFAULT));
/*
* HIREDATE の変数をバインド
*/
HANDLE_ERROR (errhp,
OCIBindByName (stmhp, &bnd3p, errhp, (text *) ":HIREDATE",
-1, (dvoid *) date_buffer[i],
strlen(date_buffer[i])+1, SQLT_STR, (dvoid *) 0, 0,
(ub2 *) 0, (ub4) 0, (ub4 *) 0,
OCI_DEFAULT));
/*
* 文を実行してデータを挿入
*/
if ((status = OCIStmtExecute (svchp, stmhp, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN INSERTING DATA\n");
HANDLE_ERROR (errhp, status);
return;
}
}
OCITransCommit (svchp, errhp, (ub4) 0);
printf ("********************************************\n");
printf
("MileStone : Data Sucessfully inserted \n & Committed via Transaction\n");
printf ("********************************************\n");
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
}
/* このサンプルで使用するストアドプロシージャと関数を作成 */
void
create_stored_procs (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
/*
* この関数は、2 つのストアドプロシージャと 1 つのストアドファンクションを作成します
* 1. StoredProcedureSample1 - プロシージャを実行し、IN OUT パラメーターから値を受け取ることを示します
* 2. StoredProcedureSample2 - プロシージャを実行し、OUT パラメーターから値を受け取ることを示します
* 3. StoredProcedureSample3 - 関数を実行し、Callable Statement 方式で関数から返される値を受け取ることを示します
*/
OCIStmt *stmhp;
OCIStmt *stmhp2;
OCIStmt *stmhp3;
text *create_statement =
(text *)"CREATE OR REPLACE PROCEDURE StoredProcedureSample1\n (mgr1 int, ename1 IN OUT varchar2)\n is\nbegin\ninsert into ocispec (mgr, ename) values (7990,'STOR1');\nename1 := 'Successful';\n end;\n";
text *create_statement2 =
(text *)"CREATE OR REPLACE PROCEDURE StoredProcedureSample2\n(mgr1 int, ename1 varchar2,eout1 OUT varchar2)\nis\nbegin\ninsert into ocispec(mgr,ename) values (7991, 'STOR2');\neout1 := 'Successful';\n end;";
text *create_statement3 =
(text *)"CREATE OR REPLACE FUNCTION f1\nRETURN VARCHAR2\nis\nv_Sysdate DATE;\nv_charSysdate VARCHAR2(20);\nbegin\nSELECT TO_CHAR(SYSDATE, 'dd-mon-yyyy') into v_charSysdate FROM DUAL;\n return(v_charSysdate);\nend;";
ub4 status = OCI_SUCCESS;
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp2,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp3,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* CREATE 文を準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp,
create_statement,
strlen ((const char *) create_statement),
OCI_NTV_SYNTAX, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp2, errhp, create_statement2,
strlen ((const char *) create_statement2),
OCI_NTV_SYNTAX, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp3, errhp, create_statement3,
strlen ((const char *) create_statement3),
OCI_NTV_SYNTAX, OCI_DEFAULT));
/*
* CREATE 文 SampleProcedure1 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN CREATING PROCEDURE 1\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 1 Successfully created\n");
printf ("********************************************\n");
}
/*
* CREATE 文 Sample Procedure2 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp2, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN CREATING PROCEDURE 2\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 2 Successfully created\n");
printf ("********************************************\n");
}
/*
* CREATE 文 Sample Procedure3 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp3, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN CREATING PROCEDURE 3\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 3 Successfully created\n");
printf ("********************************************\n");
}
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
HANDLE_ERROR (errhp, OCIHandleFree (stmhp2, OCI_HTYPE_STMT));
HANDLE_ERROR (errhp, OCIHandleFree (stmhp3, OCI_HTYPE_STMT));
}
/* resultSet を反復処理してデータを選択および出力 */
void
select_print_data (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
/* 文 */
OCIStmt *stmhp;
/* 定義 */
OCIDefine *define;
/* 従業員名用のバッファー */
char ename_buffer[10] ;
/* mgr 用のバッファー */
sword mgr_buffer;
/*hiredate 用のバッファー */
char hire_date[20];
/*
* 単純な SELECT 文
*/
text * sql_statement =
(text *) "select ename,mgr,hiredate from ocispec";
/*
* 追加のローカル変数
*/
ub4 rows = 1;
ub4 fetched = 1;
ub4 status = OCI_SUCCESS;
sb2 null_ind_ename = 0;
/* ename の NULL インジケーター */
sb2 null_ind_mgr = 0;
/* mgr の NULL インジケーター */
sb2 null_ind_hiredate = 0;
/* hiredate の NULL インジケーター */
/*
* ここから、データベースの単純なクエリと resultSet のループ処理というマイルストーンを開始します。
* これには、次の手順が含まれます
*
* 1. 文ハンドルの初期化と割り当て
* 2. 文の準備
* 3. SELECT 文の出力を受け取るための出力変数の定義
* 4. 文の実行
* 5. 結果セットのフェッチと値の出力
*
*/
memset( ename_buffer, 0, sizeof(ename_buffer) );
memset( hire_date, 0, sizeof(hire_date) );
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* 文の準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp,
sql_statement,
strlen ((const char *) sql_statement),
OCI_NTV_SYNTAX, OCI_DEFAULT));
/*
* 位置 1 に文字列 (OCIString) 変数をバインドします。使用されるデータ型は SQLT_VST です
*/
HANDLE_ERROR (errhp,
OCIDefineByPos (stmhp, &define, errhp,
(ub4) 1, ename_buffer, 10,
(ub2) SQLT_STR, &null_ind_ename, 0, 0,
OCI_DEFAULT));
/*
* 位置 2 に数値 (OCINumber) 変数をバインドします。使用されるデータ型は SQLT_VNU です
*/
HANDLE_ERROR (errhp,
OCIDefineByPos (stmhp, &define, errhp,
(ub4) 2, &mgr_buffer, sizeof (sword),
(ub2) SQLT_INT, &null_ind_mgr, 0, 0,
OCI_DEFAULT));
/*
* 位置 3 に日付 (OCIDate) 変数をバインドします。使用されるデータ型は SQLT_ODT です
*/
HANDLE_ERROR (errhp,
OCIDefineByPos (stmhp, &define, errhp,
(ub4) 3, hire_date, 20,
(ub2) SQLT_STR, &null_ind_hiredate, 0, 0,
OCI_DEFAULT));
/*
* 単純な SQL 文を実行
*/
status = OCIStmtExecute (svchp, stmhp, errhp,
rows, (ub4) 0, NULL, NULL, OCI_DEFAULT);
/*
* 結果セットを出力
*/
if (status == OCI_NO_DATA)
{
/*
* (配列フェッチではないため) 何もフェッチされなかったことを示します
*/
fetched = 0;
}
else
{
HANDLE_ERROR (errhp, status);
}
if (fetched)
{
/*
* 文字列を出力
*/
if (null_ind_ename == -1)
printf ("name -> [NULL]\t");
else
printf ("name -> [%s]\t", ename_buffer);
/*
* int に変換して数値を出力
*/
if (null_ind_mgr == -1)
printf ("mgr -> [NULL]\n");
else
{
printf ("mgr -> [%d]\n", mgr_buffer);
}
if (null_ind_hiredate == -1)
printf ("hiredate -> [NULL]\n");
else
{
printf ("hiredate -> [%s]\n",hire_date );
}
/*
* OCIStmtFetch() を使用して、結果セットを 1 つずつループ処理します
*/
/*
* 何も見つからなくなるまで
*/
while (1)
{
status = OCIStmtFetch (stmhp, errhp,
rows, OCI_FETCH_NEXT, OCI_DEFAULT);
if (status == OCI_NO_DATA)
{
/*
* 何もフェッチできなかったことを示します
*/
break;
}
else
{
HANDLE_ERROR (errhp, status);
}
/*
* 文字列を出力
*/
if (null_ind_ename == -1)
printf ("name -> [NULL]\t");
else
printf ("name -> [%s]\t", ename_buffer);
/*
* int に変換して数値を出力
*/
if (null_ind_mgr == -1)
printf ("mgr -> [NULL]\n");
else
{
printf ("mgr -> [%d]\n", mgr_buffer);
}
/*
* テキストに変換して日付を出力
*/
if (null_ind_hiredate == -1)
printf ("hiredate -> [NULL]\n");
else
{
printf ("hiredate -> [%s]\n", hire_date);
}
}
}
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
}
void
call_stored_proc1 (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *p_sql;
OCIBind *p_Bind1 = (OCIBind *) 0;
OCIBind *p_Bind2 = (OCIBind *) 0;
char field2[20];
/*
* char field3[20];
*/
sword field1 = 3;
text *mySql = (text *) "Begin StoredProcedureSample1(:MGR, :ENAME); END";
memset( field2, 0, sizeof(field2) );
strcpy( field2, "Entry 3" );
printf ("*************************************************\n");
printf ("Example 1 - Using an IN OUT Parameter\n");
printf ("*************************************************\n");
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & p_sql,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIStmtPrepare (p_sql, errhp, mySql,
(ub4) strlen ((char *)mySql), OCI_NTV_SYNTAX,
OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIBindByPos (p_sql, &p_Bind1, errhp, 1,
(dvoid *) & field1, sizeof (sword),
SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIBindByPos (p_sql, &p_Bind2, errhp, 2,
field2, (sizeof (field2)),
SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT));
printf (" Field2 Before:\n");
printf (" size ---> %d\n", sizeof (field2));
printf (" length ---> %d\n", strlen (field2));
printf (" value ---> %s\n", field2);
HANDLE_ERROR (errhp,
OCIStmtExecute (svchp, p_sql, errhp, (ub4) 1, (ub4) 0,
(OCISnapshot *) NULL, (OCISnapshot *) NULL,
(ub4) OCI_COMMIT_ON_SUCCESS));
printf (" Field2 After:\n");
printf (" size ---> %d\n", sizeof (field2));
printf (" length ---> %d\n", strlen (field2));
printf (" value ---> %s\n", field2);
HANDLE_ERROR (errhp, OCIHandleFree (p_sql, OCI_HTYPE_STMT));
}
void
call_stored_proc2 (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *p_sql;
OCIBind *p_Bind1 = (OCIBind *) 0;
OCIBind *p_Bind2 = (OCIBind *) 0;
OCIBind *p_Bind3 = (OCIBind *) 0;
char field2[20] = "Entry 3";
char field3[20];
sword field1 = 3;
text *mySql =
(text *) "Begin StoredProcedureSample2(:MGR, :ENAME, :EOUT); END";
memset( field2, 0, sizeof(field2) );
strcpy( field2, "Entry 3" );
memset( field3, 0, sizeof(field3) );
printf ("*************************************************\n");
printf ("Example 2 - Using an OUT Parameter\n");
printf ("*************************************************\n");
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & p_sql,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIStmtPrepare (p_sql, errhp, mySql,
(ub4) strlen ((char *)mySql), OCI_NTV_SYNTAX,
OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIBindByPos (p_sql, &p_Bind1, errhp, 1,
(dvoid *) & field1, sizeof (sword),
SQLT_INT, 0, 0, 0, 0, 0, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIBindByPos (p_sql, &p_Bind2, errhp, 2,
field2, strlen (field2) + 1,
SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIBindByPos (p_sql, &p_Bind3, errhp, 3,
field3, 20,
SQLT_STR, 0, 0, 0, 0, 0, OCI_DEFAULT));
printf (" Field3 Before:\n");
printf (" size ---> %d\n", sizeof (field3));
printf (" length ---> %d\n", strlen (field3));
printf (" value ---> %s\n", field3);
HANDLE_ERROR (errhp,
OCIStmtExecute (svchp, p_sql, errhp, (ub4) 1, (ub4) 0,
(OCISnapshot *) NULL, (OCISnapshot *) NULL,
(ub4) OCI_COMMIT_ON_SUCCESS));
printf (" Field3 After:\n");
printf (" size ---> %d\n", sizeof (field3));
printf (" length ---> %d\n", strlen (field3));
printf (" value ---> %s\n", field3);
HANDLE_ERROR (errhp, OCIHandleFree (p_sql, OCI_HTYPE_STMT));
}
/* このサンプルに必要なテーブルを削除 */
void
drop_table (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *stmhp;
text *statement = (text *)"DROP TABLE OCISPEC";
ub4 status = OCI_SUCCESS;
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* DROP 文を準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp,
statement, strlen ((const char *) statement),
OCI_NTV_SYNTAX, OCI_DEFAULT));
/*
* DROP 文を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN DROPING TABLE(S)\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Table(s) Successfully Dropped\n");
printf ("********************************************\n");
}
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
}
void
drop_stored_procs (OCISvcCtx * svchp, OCIError * errhp, OCIEnv * envhp)
{
OCIStmt *stmhp;
OCIStmt *stmhp2;
OCIStmt *stmhp3;
text *create_statement = (text *)"DROP PROCEDURE StoredProcedureSample1";
text *create_statement2 = (text *)"DROP PROCEDURE StoredProcedureSample2";
text *create_statement3 = (text *)"DROP FUNCTION f1";
ub4 status = OCI_SUCCESS;
OCITransCommit( svchp, errhp, OCI_DEFAULT );
/*
* 文ハンドルの初期化と割り当て
*/
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp2,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
HANDLE_ERROR (errhp,
OCIHandleAlloc (envhp, (dvoid **) & stmhp3,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
/*
* CREATE 文を準備
*/
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp, errhp,
create_statement,
strlen ((const char *) create_statement),
OCI_NTV_SYNTAX, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp2, errhp, create_statement2,
strlen ((const char *) create_statement2),
OCI_NTV_SYNTAX, OCI_DEFAULT));
HANDLE_ERROR (errhp,
OCIStmtPrepare (stmhp3, errhp, create_statement3,
strlen ((const char *) create_statement3),
OCI_NTV_SYNTAX, OCI_DEFAULT));
/*
* CREATE 文 SampleProcedure1 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN DROPPING PROCEDURE 1\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 1 Successfully dropped\n");
printf ("********************************************\n");
}
/*
* CREATE 文 Sample Procedure2 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp2, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN DROPPING PROCEDURE 2\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 2 Successfully dropped\n");
printf ("********************************************\n");
}
/*
* CREATE 文 Sample Procedure3 を実行
*/
if ((status = OCIStmtExecute (svchp, stmhp3, errhp,
(ub4) 1, (ub4) 0, NULL, NULL, OCI_DEFAULT)) < OCI_SUCCESS)
{
printf ("FAILURE IN DROPPING PROCEDURE 3\n");
HANDLE_ERROR (errhp, status);
return;
}
else
{
printf ("********************************************\n");
printf ("MileStone : Sample Procedure 3 Successfully dropped\n");
printf ("********************************************\n");
}
HANDLE_ERROR (errhp, OCIHandleFree (stmhp, OCI_HTYPE_STMT));
HANDLE_ERROR (errhp, OCIHandleFree (stmhp2, OCI_HTYPE_STMT));
HANDLE_ERROR (errhp, OCIHandleFree (stmhp3, OCI_HTYPE_STMT));
}
/* 後片付け */
void
cleanup (OCISvcCtx ** svchp, OCIServer ** srvhp, OCISession ** authp,
OCIError ** errhp, OCIEnv ** envhp)
{
/*
* ログオフ
*/
HANDLE_ERROR (*errhp, OCISessionEnd (*svchp, *errhp, *authp, OCI_DEFAULT));
printf ("logged off\n");
/*
* サーバーからデタッチ
*/
HANDLE_ERROR (*errhp, OCIServerDetach (*srvhp, *errhp, OCI_DEFAULT));
printf ("detached form server\n");
/*
* ハンドルを解放
*/
HANDLE_ERROR (*errhp, OCIHandleFree (*authp, OCI_HTYPE_SESSION));
/* セッションハンドルを解放 */
*authp = 0;
HANDLE_ERROR (*errhp, OCIHandleFree (*srvhp, OCI_HTYPE_SERVER));
/* サーバーハンドルを解放 */
*srvhp = 0;
HANDLE_ERROR (*errhp, OCIHandleFree (*svchp, OCI_HTYPE_SVCCTX));
/* サービスコンテキストを解放 */
*svchp = 0;
HANDLE_ERROR (*errhp, OCIHandleFree (*errhp, OCI_HTYPE_ERROR));
/* エラーハンドルを解放 */
*errhp = 0;
OCIHandleFree (*envhp, OCI_HTYPE_ENV);
/* 環境ハンドルを解放 */
*envhp = 0;
printf ("free'd all handles\n");
}main() 関数内の接続パラメーターを、ご利用のクラスターの情報に置き換えてください (上記の「接続パラメーター」セクションをご参照ください)。
Oracle ネイティブ OCI ドライバーの詳細については、「OCI: はじめに」をご参照ください。
コードのコンパイル
Linux
ドライバーパッケージ内の Makefile は、コンパイラを Oracle OCI ヘッダーと PolarDB OCI ライブラリにリンクします。
# ============================================================================
# Copyright (c) 2004-2012 PolarDB Corporation. All Rights Reserved.
# ===========================================================================
# Makefile to build C testcases for OCILib
#
CC=gcc
CFLAGS=-Wall -g -I$(ORACLE_HOME)/ -L $(POLARDBOCI_LIB) -lpolaroci -lpq -liconv
SAMPLES = polardb_demo
all: $(SAMPLES)
%:%.o
$(CC) $(CFLAGS) -o $@
clean:
rm -rf $(SAMPLES)make を実行する前に、2 つの Makefile 変数をシステム上の正しいパスに設定してください。
| 変数 | 指す対象 | パスの例 |
|---|---|---|
ORACLE_HOME | Oracle OCI ヘッダーファイルディレクトリ | instantclient_12_1/sdk/include |
POLARDBOCI_LIB | libpolaroci.so、libpq.so、および libiconv.so | /usr/lib |
デモをコンパイルします。
makeWindows
このセクションでは、Visual Studio を例として使用します。
ドライバーディレクトリから Oracle OCI 開発パッケージのパスを [C/C++] > [全般] > [追加のインクルード ディレクトリ] に追加します。
ドライバーディレクトリから
polardboci.dllとpolardboci.libのパスを [リンカー] > [全般] > [追加のライブラリ ディレクトリ] に追加します。[リンカー] > [入力] > [追加の依存ファイル] に
polardboci.libを入力します。
接続の確認
polardb_demo をコンパイルして実行すると、期待される出力は次のとおりです。
********************************************
Milestone : Logged on as --> 'parallels'
********************************************
********************************************
MileStone : Table(s) Successfully created
********************************************
********************************************
MileStone : Data Sucessfully inserted
& Committed via Transaction
********************************************
********************************************
MileStone : Sample Procedure 1 Successfully created
********************************************
********************************************
MileStone : Sample Procedure 2 Successfully created
********************************************
********************************************
MileStone : Sample Procedure 3 Successfully created
********************************************
name -> [SMITH] mgr -> [7886]
hiredate -> [2007-08-02 00:00:00]
name -> [ALLEN] mgr -> [7110]
hiredate -> [2007-04-02 00:00:00]
name -> [KING] mgr -> [7221]
hiredate -> [2007-03-02 00:00:00]
*************************************************
Example 1 - Using an IN OUT Parameter
*************************************************
Field2 Before:
size ---> 20
length ---> 7
value ---> Entry 3
Field2 After:
size ---> 20
length ---> 10
value ---> Successful
*************************************************
Example 2 - Using an OUT Parameter
*************************************************
Field3 Before:
size ---> 20
length ---> 0
value --->
Field3 After:
size ---> 20
length ---> 10
value ---> Successful
********************************************
MileStone : Table(s) Successfully Dropped
********************************************
********************************************
MileStone : Sample Procedure 1 Successfully dropped
********************************************
********************************************
MileStone : Sample Procedure 2 Successfully dropped
********************************************
********************************************
MileStone : Sample Procedure 3 Successfully dropped
********************************************
logged off
detached form server
free'd all handles出力が一致する場合、PolarDB OCI ドライバーは正しくインストールされ、接続されています。
次のステップ
OCI ドライバーで接続した後、その上に高レベルのインターフェイスを構築できます。
PolarDB JDBC — Java アプリケーション
PolarDB ODBC — ODBC 互換ドライバーを使用するアプリケーション
PolarDB .NET — .NET アプリケーション