TimesTenデータベース接続の管理

TimesTenデータベース接続を管理する方法について説明します。

TimesTen接続の概要

ODBCアプリケーションは、属性(ホストやポート番号など)またはデータソース名(DSN)のいずれかを参照してデータベースに接続できます。TimesTen Classicでは、ユーザーはDSNを直接作成できます。TimesTen Scaleoutでは、グリッドに定義する接続可能オブジェクトごとにDSNが作成されます。

この項では、TimesTen接続に関する基本事項をいくつか説明し、詳細の参照先を示します。

TimesTen Scaleoutの場合の、データベース作成方法、および直接接続またはクライアント/サーバー接続の使用によるデータベースへの接続方法の詳細は、Oracle TimesTen In-Memory Database Scaleoutユーザーズ・ガイドを参照してください。データベースの作成およびデータベースへの接続を参照してください。

TimesTen Classicの場合の、データベースのDSNの作成方法の詳細は、Oracle TimesTen In-Memory Databaseオペレーション・ガイドを参照してください。作成するDSNのタイプは、アプリケーションがデータベースに直接接続するか、クライアント接続するかによって異なります。

  • データベースに直接接続する予定の場合は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』TimesTenデータベースの管理を参照してください。LinuxまたはUNIXから、あるいはWindowsから、直接接続するためのDSNの作成方法に関する説明があります。

  • データベースへのクライアント接続を作成する予定の場合は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』TimesTenクライアントおよびサーバーの使用を参照してください。LinuxまたはUNIXから、あるいはWindowsから、クライアント/サーバー接続を行うためのDSNの作成方法に関する説明があります。

ノート:

  • TimesTenでは、ユーザー名およびパスワードは、データベースに接続するためのCREATE SESSION権限を付与されている有効なユーザーのものである必要があります。

  • TimesTen接続は、親プロセスから継承することはできません。プロセスが子プロセスを作成(分岐)する前にデータベース接続をオープンした場合、子プロセスではそのデータベース接続を使用しないでください。

SQLConnect関数、SQLDriverConnect関数、SQLAllocConnect関数、SQLDisconnect関数

データベースへの接続、接続のメモリーの割当て、データベースからの切断に使用できるODBC関数を示します。

  • SQLConnect: ドライバをロードしてデータベースに接続します。接続ハンドルは、ステータス、トランザクションの状態、結果およびエラー情報などの接続情報が格納される場所を指します。

    次に、SQLConnectコール・シーケンスを示します。

    SQLRETURN SQLConnect( 
              SQLHDBC        ConnectionHandle, 
              SQLCHAR *      ServerName, 
              SQLSMALLINT    NameLength1, 
              SQLCHAR *      UserName, 
              SQLSMALLINT    NameLength2, 
              SQLCHAR *      Authentication, 
              SQLSMALLINT    NameLength3); 
  • SQLDriverConnect: SQLConnectでサポートされている情報(データソース(データベース)、ユーザー名およびパスワード)よりも詳細な情報が必要な場合に、SQLConnectのかわりに使用します。

    次に、SQLDriverConnectコール・シーケンスを示します。

    SQLRETURN SQLDriverConnect( 
              SQLHDBC         ConnectionHandle, 
              SQLHWND         WindowHandle, 
              SQLCHAR *       InConnectionString, 
              SQLSMALLINT     StringLength1, 
              SQLCHAR *       OutConnectionString, 
              SQLSMALLINT     BufferLength, 
              SQLSMALLINT *   StringLength2Ptr, 
              SQLUSMALLINT    DriverCompletion); 
  • SQLAllocConnect: 指定した環境内の接続ハンドルにメモリーを割り当てます。

    次に、SQLAllocConnectコール・シーケンスを示します。

    SQLRETURN SQLAllocConnect(
               SQLHENV        EnvironmentHandle,
               SQLHDBC        PointerToConnectionHandle);
  • SQLDisconnect: データベースから切断します。既存の接続ハンドルを唯一の引数として使用します。

    次に、SQLDisconnectコール・シーケンスを示します。

    SQLRETURN SQLDisconnect(
              SQLHDBC        ConnectionHandle);

これらの関数の詳細は、ODBC APIのリファレンス・マニュアルを参照してください。

デフォルトDSNの使用

次に、デフォルトのDSNが使用される状況を示します。

TimesTen Classicでは、defaultという名前が付けられているデフォルトDSNは、odbc.iniファイルまたはsys.odbc.iniファイルで定義できます。『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』TimesTen ClassicでのデフォルトDSNの設定を参照してください。

SQLConnectでは、デフォルトのDSNが定義されている場合は、次の状況でそれが使用されます。

  • ServerNameで、見つからないデータソースが指定されている場合。

  • ServerNameがNULLポインタの場合。

  • defaultがサーバー名として指定されている場合。ユーザー名と認証値はそのまま使用します。

SQLDriverConnectでは、デフォルトのDSNが定義されている場合は、次の状況でそれが使用されます。

  • 接続文字列にDSNキーワードが含まれていない場合。

  • データ・ソースが見つからない場合。

  • defaultがDSNキーワードとして指定されている場合。ユーザー名とパスワードはそのまま使用します。

直接モードまたは汎用ドライバ・マネージャを備えたクライアント/サーバー・モードの場合、次の使用上のノートに注意してください。

  • 汎用ドライバ・マネージャを使用していない場合、TimesTenがこの機能を管理します。デフォルトDSNは、TimesTenデータベースである必要があります。

  • 汎用ドライバ・マネージャを使用している場合、ドライバ・マネージャがこの機能を管理します。デフォルトDSNは、TimesTenデータベースである必要はありません。

データベースに対する接続および切断

データベースに対する接続および切断の方法について説明します。

このコード部分では、SQLConnectおよびSQLDisconnectを起動して、FixedDsというデータベースに対する接続および切断を行います。アプリケーションで初めてSQLConnectを起動すると、データベースFixedDsが作成されます。その後のSQLConnectの起動では、既存のデータベースに接続されます。

#include <timesten.h>
SQLRETURN retcode;
SQLHDBC hdbc;

...
retcode = SQLConnect(hdbc,
                     (SQLCHAR*)"FixedDs", SQL_NTS,
                     (SQLCHAR*)"johndoe", SQL_NTS,
                     (SQLCHAR*)"opensesame", SQL_NTS);
...
retcode = SQLDisconnect(hdbc);
...

次に、データベースを作成し、データベースに接続し、その接続を切断する完成されたプログラムを示します。この例では、SQLConnectではなくSQLDriverConnectを使用して接続を設定し、SQLAllocConnectを使用してメモリーを割り当てます。また、エラー・メッセージの取得方法についても示します。(「エラー処理」も参考になる可能性があります。)

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

static void chkReturnCode(SQLRETURN rc, SQLHENV henv,
                          SQLHDBC hdbc, SQLHSTMT hstmt,
                          char* msg, char* filename,
                          int lineno, BOOL err_is_fatal);
#define DEFAULT_CONNSTR "DSN=sampledb;PermSize=32"

int
main(int ac, char** av)
{
   SQLRETURN rc = SQL_SUCCESS;
                  /* General return code for the API */
   SQLHENV henv = SQL_NULL_HENV;
                  /* Environment handle */
   SQLHDBC hdbc = SQL_NULL_HDBC;
                  /* Connection handle */
   SQLHSTMT hstmt = SQL_NULL_HSTMT;
                  /* Statement handle */
   SQLCHAR connOut[255];
                  /* Buffer for completed connection string */
   SQLSMALLINT connOutLen;
                  /* Number of bytes returned in ConnOut */
   SQLCHAR *connStr = (SQLCHAR*)DEFAULT_CONNSTR;
                  /* Connection string */
   rc = SQLAllocEnv(&henv);
   if (rc != SQL_SUCCESS) {
      fprintf(stderr, "Unable to allocate an "
             "environment handle\n");
    exit(1);
   }
   rc = SQLAllocConnect(henv, &hdbc);
   chkReturnCode(rc, henv, SQL_NULL_HDBC,
              SQL_NULL_HSTMT,
              "Unable to allocate a "
              "connection handle\n",
              __FILE__, __LINE__, 1);

   rc = SQLDriverConnect(hdbc, NULL,
                         connStr, SQL_NTS,
                         connOut, sizeof(connOut),
                         &connOutLen,
                         SQL_DRIVER_NOPROMPT);
   chkReturnCode(rc, henv, hdbc, SQL_NULL_HSTMT,
                 "Error in connecting to the"
                 " database\n",
                 __FILE__, __LINE__, 1);
   rc = SQLAllocStmt(hdbc, &hstmt);
   chkReturnCode(rc, henv, hdbc, SQL_NULL_HSTMT,
                 "Unable to allocate a "
                 "statement handle\n",
                 __FILE__, __LINE__, 1);

   /* Your application code here */

   if (hstmt != SQL_NULL_HSTMT) {
     rc = SQLFreeStmt(hstmt, SQL_DROP);
     chkReturnCode(rc, henv, hdbc, hstmt,
                   "Unable to free the "
                   "statement handle\n",
                    __FILE__, __LINE__, 0);
   }

   rc = SQLDisconnect(hdbc);
   chkReturnCode(rc, henv, hdbc,
                 SQL_NULL_HSTMT,
                 "Unable to close the "
                 "connection\n",
                 __FILE__, __LINE__, 0);

   rc = SQLFreeConnect(hdbc);
   chkReturnCode(rc, henv, hdbc,
                 SQL_NULL_HSTMT,
                 "Unable to free the "
                 "connection handle\n",
                 __FILE__, __LINE__, 0);

   rc = SQLFreeEnv(henv);
   chkReturnCode(rc, henv, SQL_NULL_HDBC,
                 SQL_NULL_HSTMT,
                 "Unable to free the "
                 "environment handle\n",
                 __FILE__, __LINE__, 0);
     return 0;
   }
}

static void
chkReturnCode(SQLRETURN rc, SQLHENV henv,
              SQLHDBC hdbc, SQLHSTMT hstmt,
              char* msg, char* filename,
              int lineno, BOOL err_is_fatal)
{
   #define MSG_LNG 512
   SQLCHAR sqlState[MSG_LNG];
   /* SQL state string */
   SQLINTEGER nativeErr;
   /* Native error code */
   SQLCHAR errMsg[MSG_LNG];
   /* Error msg text buffer pointer */
   SQLSMALLINT errMsgLen;
   /* Error msg text Available bytes */
   SQLRETURN ret = SQL_SUCCESS;
   if (rc != SQL_SUCCESS &&
       rc != SQL_NO_DATA_FOUND ) {
      if (rc != SQL_SUCCESS_WITH_INFO) {
       /*
        * It's not just a warning
        */
      fprintf(stderr, "*** ERROR in %s, line %d:"
               " %s\n",
               filename, lineno, msg);
  }
  /*
   * Now see why the error/warning occurred
   */
  while (ret == SQL_SUCCESS ||
         ret == SQL_SUCCESS_WITH_INFO) {
    ret = SQLError(henv, hdbc, hstmt,
                   sqlState, &nativeErr,
                   errMsg, MSG_LNG,
                   &errMsgLen);
    switch (ret) {
      case SQL_SUCCESS:
        fprintf(stderr, "*** %s\n"
                 "*** ODBC Error/Warning = %s, "
                 "TimesTen Error/Warning "
                 " = %d\n",
                 errMsg, sqlState,
                 nativeErr);
      break;
    case SQL_SUCCESS_WITH_INFO:
      fprintf(stderr, "*** Call to SQLError"
              " failed with return code of "
              "SQL_SUCCESS_WITH_INFO.\n "
              "*** Need to increase size of"
              " message buffer.\n");
      break;
    case SQL_INVALID_HANDLE:
      fprintf(stderr, "*** Call to SQLError"
              " failed with return code of "
              "SQL_INVALID_HANDLE.\n");
      break;
    case SQL_ERROR:
      fprintf(stderr, "*** Call to SQLError"
              " failed with return code of "
              "SQL_ERROR.\n");
      break;
    case SQL_NO_DATA_FOUND:
      break;
     } /* switch */
   } /* while */
   if (rc != SQL_SUCCESS_WITH_INFO && err_is_fatal) {
     fprintf(stderr, "Exiting.\n");
     exit(-1);
   }
}

プログラムでの接続属性の設定

次に、データベースへの接続時に接続文字列を指定することで、プログラムで接続属性を設定または上書きする方法を示します。

このコード部分では、mydsnというデータベースに接続して、SQLDriverConnectコールで、アプリケーションがパススルー設定の3を使用することを示します。PassThroughは一般接続属性であることに注意してください。

SQLHDBC hdbc;
SQLCHAR ConnStrOut[512];
SQLSMALLINT cbConnStrOut;
SQLRETURN rc;

rc = SQLDriverConnect(hdbc, NULL,
    "DSN=mydsn;PassThrough=3", SQL_NTS,
    ConnStrOut, sizeof (ConnStrOut),
    &cbConnStrOut, SQL_DRIVER_NOPROMPT);

ノート:

  • データベースへの直接接続ごとに、いくつかのファイルがオープンします。多数のスレッドを使用し、スレッドごとに別々の接続を使用するアプリケーションでは、各スレッドに対して複数のファイルがオープンします。このようなアプリケーションでは、オペレーティング・システムで同時にオープンできるファイル記述子の許可された最大数(構成されている最大値)を超える可能性があります。この場合は、多数のオープン・ファイルを許可するようシステムを設定します。『Oracle TimesTen In-Memory Databaseリファレンス』オープン・ファイルの数の制限を参照してください。

  • 接続属性に関する一般情報は、『Oracle TimesTen In-Memory Databaseオペレーション・ガイド』TimesTenデータベースの管理を参照してください。一般接続属性には、特に権限は必要ありません。データベースが初めてロードされたときに最初の接続属性が設定され、すべての接続に持続的に使用されます。最初の接続属性の設定を変更してデータベースをロードできるのは、インスタンス管理者のみです。『Oracle TimesTen In-Memory Databaseリファレンス』接続属性を参照してください。