3 SODA for Cの使用

SODA for Cにアクセスする方法、およびこれを使用してコレクションに対する作成、読取り(取得)および削除(CRUD)操作を実行する方法について説明します。CRUD操作は、このドキュメントでは読取りおよび書込み操作とも呼ばれています。

3.1 SODA for Cスタート・ガイド

SODA for Cにアクセスする方法、およびこれを使用してデータベース・コレクションを作成し、ドキュメントをコレクションに挿入し、コレクションからドキュメントを取得する方法について説明します。

注意:

最初に読んだときに、このトピック内のすべてが理解できなくても気にしないでください。必要な概念は、他のトピックで詳細に理解が進みます。このトピックは、SODAを使用する上で全体的に何が関与しているかをとらえるためのものです。

SODA for Cの使用を開始するには、次のステップを実行します。

  1. SODA for Cを使用するための前提条件がすべて満たされていることを確認します。SODA for Cの前提条件を参照してください。

  2. SODAコレクションを格納するデータベース・スキーマ(ユーザー・アカウント)にデータベース・ロールSODA_APPを付与します。(ここでプレースホルダuserを実際のアカウント名で置き換えます。)

    GRANT SODA_APP TO user;
    
  3. 例3-1でCコードを含むプログラム・ファイルを作成しますが、変数usrpasswdおよびconnstrを、データベース・アカウントおよびインスタンスに適切な文字値に設定します。

  4. OCIプログラムの場合と同様に、ファイルをコンパイルして実行可能プログラムをビルドします。

  5. プログラムを実行します。

    コマンド行にプログラム名を入力するのみでこれを実行できます。たとえば、名前がsoda-get-startedの場合、コマンド行プロンプトにそれを入力します。

    > soda-get-started

    プログラムの終了時にコレクションをドロップする場合は、コマンド行で引数dropを渡します。

    > soda-get-started drop

注意:

SQLを使用して、コレクションの基礎となるデータベースをドロップしないでください。コレクションのドロップには、単なるデータベース表のドロップよりも多くのことが含まれます。表に格納されるドキュメントに加えて、コレクションにはOracle Databaseにも残っているメタデータが含まれています。コレクションの基礎となる表をドロップしても、同様にコレクション・メタデータがドロップされることはありません

注意:

  • SODA for Cの機能を使用する手持ちのCコードはすべて、最初にOCIオブジェクト・モードで環境を初期化し、ここでモード・パラメータとしてOCI_OBJECTを関数OCIEnvNlsCreate()に渡す必要があります

  • SODAハンドル(ドキュメント、コレクション、およびその他)はすべて、プログラムで不要になったときに、関数OCIHandleFree()を使用して明示的に解放する必要があります。(特に、大規模なコンテンツのドキュメントのハンドルは、大量のメモリーと関連付けられている可能性があります。)

関連項目:

例3-1 スタート・ガイド概要

このコード例では次の事項を実行します。

  1. オブジェクト・モードでOracle Call Interface(OCI)環境を作成し、エラー・ハンドルを割り当て、OCISessionGet()関数を使用してセッションを取得します。

  2. デフォルトのコレクション構成(メタデータ)を使用して、SODAドキュメント・コレクションを作成して開きます。

  3. 一部のJSONコンテンツを使用してSODAドキュメントを作成します。

  4. ドキュメントをコレクションに挿入します。

  5. 挿入されたドキュメントを戻します。他のコンポーネントは、コンテンツ以外は自動的に生成されます。

  6. 自動的に生成されたコンポーネントの1つである一意のドキュメント・キーを出力します。

  7. キーを指定して、コレクション内のドキュメントを検索します。

  8. ドキュメント・コンポーネントの一部(キー、バージョン、最終変更のタイムスタンプ、作成時のタイムスタンプ、メディア・タイプ、およびコンテンツ)を出力します。

  9. 必要に応じて、コレクションをドロップして、コレクションとそのメタデータの格納に使用されるデータベース表をクリーン・アップします。

  10. 割り当てられたすべてのハンドルを解放します。

コレクションがドロップされているかどうかは、実行時に決定されます。コレクションをドロップするには、実行可能プログラムへのコマンド行引数として、dropを指定します。

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

static sword status;

int main(int argc, char *argv[])
{
  sword        rc = OCI_SUCCESS;
  OCIEnv      *envhp = NULL;
  OCIError    *errhp = NULL;
  OCISvcCtx   *svchp = NULL;
  OCIAuthInfo *authhp = NULL;
  OCISodaColl *collhp = NULL;
  OCISodaDoc  *dochp = NULL;
  boolean      isDropped = FALSE;
  ub4          docFlags = OCI_DEFAULT;
  OraText     *collectionName = (oratext *)"MyJSONCollection";
  OCISodaDoc  *foundDochp = NULL;
  OCISodaDoc  *origDochp = NULL;

  // Document content: JSON data
  char         documentContent[30] = "{\"name\":\"Alexander\"}";
 
  // Set these variables to strings with the appropriate user name and password.
  // (Be sure to replace the placeholders user and password used here.)
  OraText      usr[30] = user;
  OraText      passwd[30] = password;

  // Set variable connstr to a string value composed of the host name, port number, and service name
  // of your database instance.
  // (Be sure to replace placeholders host, port, and service used here.)
  OraText      connstr[50] = "host:port/service";

  OraText     *key = NULL;
  ub4          keyLen = 0;
  OraText     *content = NULL;
  ub4          contentLen = 0;
  OraText     *version = NULL;
  ub4          versionLen = 0;
  OraText     *lastModified = NULL;
  ub4          lastModifiedLen = 0;
  OraText     *mediaType = NULL;
  ub4          mediaTypeLen = 0;
  OraText     *createdOn = NULL;
  ub4          createdOnLen = 0;

  // Set up environment. OCI_OBJECT is required for all SODA C code.
  rc = OCIEnvNlsCreate(&envhp,
                       OCI_OBJECT,
                       NULL,
                       NULL,
                       NULL,
                       NULL,
                       0,
                       NULL,
                       0,
                       0);

  if (rc != OCI_SUCCESS)
  {
    printf ("OCIEnvNlsCreate failed\n");
    goto finally;
  }

  // Allocate error handle
  rc = OCIHandleAlloc((dvoid *) envhp,
                      (dvoid **) &errhp,
                      OCI_HTYPE_ERROR,
                      (size_t) 0,
                      (dvoid **) 0);

  if (rc != OCI_SUCCESS)
  {
    printf ("OCIHandleAlloc: OCI_HTYPE_ERROR creation failed\n");
    goto finally;
  }

  // Allocate authentication-information handle
  rc = OCIHandleAlloc ((dvoid *)envhp,
                       (dvoid **)&authhp,
                       (ub4)OCI_HTYPE_AUTHINFO,
                       (size_t)0,
                       (dvoid **)0);

  if (rc != OCI_SUCCESS)
  {
    printf ("OCIHandleAlloc: OCI_HTYPE_AUTHINFO creation failed\n");
    goto finally;
  }
  
  // Set variable usr to the user name
  rc = OCIAttrSet ((dvoid *)authhp,
                   (ub4)OCI_HTYPE_AUTHINFO,
                   (dvoid *)usr,
                   (ub4)strlen((char *)usr),
                   (ub4)OCI_ATTR_USERNAME,
                   (OCIError *)errhp);
  if (rc != OCI_SUCCESS)
  {
    printf ("OCIAttrSet: OCI_ATTR_USERNAME failed\n");
    goto finally;
  }

  // Set variable passwd to the password
  rc = OCIAttrSet ((dvoid *)authhp,
                   (ub4)OCI_HTYPE_AUTHINFO,
                   (dvoid *)passwd,
                   (ub4)strlen((char *)passwd),
                   (ub4)OCI_ATTR_PASSWORD,
                   (OCIError *)errhp);
  if (rc != OCI_SUCCESS)
  {
    printf ("OCIAttrSet: OCI_ATTR_PASSWORD failed\n");
    goto finally;
  }

  // Get service handle
  // This provides service and error handles we can use for service calls
  rc = OCISessionGet ((OCIEnv *)envhp,
                      (OCIError *)errhp,
                      (OCISvcCtx **)&svchp,
                      (OCIAuthInfo *)authhp,
                      (OraText *)connstr,
                      (ub4)strlen((char *)connstr),
                      (OraText *)NULL,
                      (ub4)0,
                      (OraText **)0,
                      (ub4 *)0,
                      (boolean *)0,
                      (ub4)OCI_DEFAULT);

  if (rc != OCI_SUCCESS)
  {
    printf("OCISessionGet failed\n");
    goto finally;
  }

  // Create collection named by the value of variable collectionName, with default metadata
  rc = OCISodaCollCreate(svchp,
                         collectionName,
                         (ub4) strlen(collectionName),
                         &collhp,
                         errhp,
                         OCI_DEFAULT);

  if (rc != OCI_SUCCESS)
  {
    printf("OCISodaCollCreate failed\n");
    goto finally;
  }

  // Create a document with content provided by variable documentContent
  rc = OCISodaDocCreate(envhp,
                        documentContent,
                        (ub4) strlen(documentContent),
                        docFlags,
                        &dochp,
                        errhp,
                        OCI_DEFAULT);

  if (rc != OCI_SUCCESS)
  {
    printf("OCISodaDocCreate failed\n");
    goto finally;
  }

  // Because OCISodaInsertAndGet returns the result document as dochp, we first
  // save the pointer to the original input document handle, which was returned
  // by OCISodaDocCreate, as origDochp. This lets us free the original
  // document handle later.
  origDochp = dochp;

  // Insert the document into the collection
  rc = OCISodaInsertAndGet(svchp,
                           collhp,
                           &dochp,
                           errhp,
                           OCI_SODA_ATOMIC_COMMIT);

  if (rc != OCI_SUCCESS)
  {
    printf("OCISodaInsertAndGet failed\n");
    goto finally;
  }

  // Get the auto-generated key of the inserted document
  rc = OCIAttrGet((dvoid *) dochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_KEY failed\n");
    goto finally;
  }

  // Find the document using its key
  printf("Find the document by its auto-generated key %.*s\n", keyLen, key);
  rc = OCISodaFindOneWithKey(svchp,
                             collhp,
                             key,
                             keyLen,
                             OCI_DEFAULT,
                             &foundDochp,
                             errhp,
                             OCI_DEFAULT);

  if (rc != OCI_SUCCESS)
  {
    printf("OCISodaFindOneWithKey failed\n");
    goto finally;
  }

  // Get and print components of found document
  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_KEY failed\n");
    goto finally;
  }
  printf("Key: %.*s\n", keyLen, key);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &version,
                  &versionLen,
                  OCI_ATTR_SODA_VERSION,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_VERSION failed\n");
    goto finally;
  }
  printf("Version: %.*s\n", versionLen, version);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &lastModified,
                  &lastModifiedLen,
                  OCI_ATTR_SODA_LASTMOD_TIMESTAMP,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_LASTMOD_TIMESTAMP failed\n");
    goto finally;
  }
  printf("Last-modified: %.*s\n", lastModifiedLen, lastModified);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &createdOn,
                  &createdOnLen,
                  OCI_ATTR_SODA_CREATE_TIMESTAMP,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_CREATE_TIMESTAMP failed\n");
    goto finally;
  }
  printf("Created: %.*s\n", createdOnLen, createdOn);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &mediaType,
                  &mediaTypeLen,
                  OCI_ATTR_SODA_MEDIA_TYPE,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_MEDIA_TYPE failed\n");
    goto finally;
  }
  printf("Media Type: %.*s\n", mediaTypeLen, mediaType);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &content,
                  &contentLen,
                  OCI_ATTR_SODA_CONTENT,
                  errhp);

  if (rc != OCI_SUCCESS)
  {
    printf("OCIAttrGet for OCI_ATTR_SODA_CONTENT failed\n");
    goto finally;
  }
  printf("Content: %.*s \n", contentLen, content);

  // Drop the collection if argument "drop" was provided
  if ((argc > 1) && (strcmp(argv[1], "drop") == 0))
  {
    rc = OCISodaCollDrop(svchp,
                         collhp,
                         &isDropped,
                         errhp,
                         OCI_DEFAULT);
    if (rc != OCI_SUCCESS)
    {
      printf("OCISodaCollDrop failed\n");
      goto finally;
    }
    else 
    {
      printf("Collection dropped\n");
    }
  }

 finally:

  // Release the session and free all handles
  if (collhp) 
    (void ) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
  
  if (dochp) 
    (void ) OCIHandleFree((dvoid *) dochp, OCI_HTYPE_SODA_DOCUMENT);

  if (origDochp)
    (void ) OCIHandleFree((dvoid *) origDochp, OCI_HTYPE_SODA_DOCUMENT);

  if (foundDochp) 
    (void ) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);

  (void ) OCISessionRelease(svchp, errhp, (oratext *)0, 0, OCI_DEFAULT);

  if (authhp)
    (void ) OCIHandleFree ((dvoid *)authhp, (ub4)OCI_HTYPE_AUTHINFO);
  
  if (errhp) 
    (void ) OCIHandleFree((dvoid *) errhp, OCI_HTYPE_ERROR);
  
  if (svchp) 
    (void ) OCIHandleFree((dvoid *) svchp, OCI_HTYPE_SVCCTX);

  if (envhp) 
    (void ) OCIHandleFree((dvoid *) envhp, OCI_HTYPE_ENV);
  return rc;
}

3.2 SODA for Cを使用したドキュメント・コレクションの作成

構成の詳細を気にしない場合は、OCI関数OCISodaCollCreate()を使用してコレクションを作成します。これにより、デフォルトのメタデータを持つコレクションが作成されます。デフォルト以外の方法で構成されたコレクションを作成するには、かわりに関数OCISodaCollCreateWithMetadata()を使用して、JSONで表されたカスタム・メタデータを渡します。

これらの関数のそれぞれについて、同じ名前のコレクションがすでに存在する場合は、コレクションが単に開かれてそのハンドルが返されます。関数OCISodaCollCreateWithMetadata()の場合、渡されたメタデータが既存のコレクションのメタデータと一致しない場合、コレクションは開かれず、エラーが発生します。(一致するには、すべてのメタデータ・フィールドが同じ値である必要があります。)

例3-2では、関数OCISodaCollCreate()を使用して、デフォルト構成(デフォルトのメタデータ)を含むコレクションを作成します。これは、コレクションをOCISodaCollハンドルとして返します。

デフォルトのコレクション・メタデータを持つコレクションには、次の特性があります。

  • JSONドキュメントのみを格納できます。

  • そのドキュメントのそれぞれに、キー、作成時のタイムスタンプ、最終変更のタイムスタンプの各コンポーネントがあります。

  • キーは、コレクションに追加したドキュメントに自動的に生成されます。

ほとんどの場合、デフォルトのコレクション構成をお薦めしますが、コレクションは高度な構成が可能です。コレクションを作成する場合、次のような項目を指定できます。

  • コレクションがJSONドキュメントのみを格納できるかどうか。

  • ドキュメント作成時のタイムスタンプ、最終変更のタイムスタンプおよびバージョン用の列の有無。

  • ドキュメント・キーの生成方式、およびキーをクライアントで割り当てるかまたは自動的に生成するか。

  • バージョンの生成方式。

  • 記憶域の詳細。たとえば、コレクションを格納する表の名前、列の名前とデータ型など。

このように構成可能であるため、新規コレクションを既存のデータベース表にマップすることもできます。

注意:

特に記載のないかぎり、このドキュメントでは、コレクションはデフォルト構成を使用していると想定しています。

関連項目:

例3-2 デフォルトのメタデータが含まれるコレクションの作成

この例では、デフォルトのメタデータでコレクションMyCollectionが作成されます。関数OCISodaCollCreate()自体は、データベース・コミット操作を実行しないことに注意してください。

OCISodaColl *collhp = NULL;
OraText     *collectionName = (OraText *)"MyCollection";
rc = OCISodaCollCreate(svchp,
                       (const OraText *)collectionName,
                       (ub4)strlen(collectionName),
                       &collhp,
                       errhp,
                       OCI_DEFAULT);

3.3 SODA for Cを使用した既存のドキュメント・コレクションのオープン

既存のドキュメント・コレクションを開くには、OCI関数OCISodaCollOpen()を使用します。

関連項目:

OCI関数OCISodaCollOpen()の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照

例3-3 既存のドキュメント・コレクションのオープン

この例では、OCI関数OCISodaCollOpen()を使用して、MyCollectionという名前のコレクションを開きます。このコレクションを4番目のパラメータ(この例ではcollhp)の値として表すOCISodaCollハンドルが返されます。関数の戻り値は、成功の場合はOCI_SUCCESS、失敗の場合はOCI_ERRORです。返された値がOCI_ERRORの場合、MyCollectionという名前のコレクションは存在しません。

OCISodaColl *collhp = NULL;
OraText     *collectionName = "MyCollection";
rc = OCISodaCollOpen(svchp, 
                     collectionName,
                     (ub4) strlen(collectionName),
                     &collhp,
                     errhp,
                     OCI_DEFAULT);
if (!collhp) printf("Collection %s does not exist\n", collectionName);

3.4 SODA for Cを使用した指定されたコレクションが存在するかどうかの確認

指定された名前のコレクションが存在するかどうかを確認するには、OCI関数OCISodaCollOpen()を使用します。この関数は、コレクションが正常に開かれた場合にOCI_SUCCESSを返します。これは、それが存在することを意味します。そのようなコレクションが存在しない場合、コレクション・ハンドルのポインタはNULLです。

例3-3に、これを示します。MyCollectionが既存のコレクションの名前を指定している場合、そのコレクションが開かれて、コレクション・ハンドルcollhpがそのコレクションを指します。MyCollectionが既存のコレクションの名前を指定していない場合は、関数OCISodaCollOpen()を呼び出した後のコレクション・ハンドルcollhpの値は引き続きNULLです。

3.5 SODA for Cを使用した既存のコレクションの検出

既存のコレクションを検出するには、OCI関数OCISodaCollList()およびOCISodaCollGetNext()を使用します。

関連項目:

例3-4 すべての既存のコレクションの名前の出力

この例では、OCI関数OCISodaCollList()を使用して、コレクションのカーソル(collectionCursor)を取得します。さらに、このカーソルを反復処理して、各コレクションの名前を出力します。

OCISodaCollCursor *collectionCursor;
OCISodaColl       *collhp;
OraText           *startName = NULL;
ub4                startNameLen = 0;
OraText           *collectionName = NULL;
ub4                collectionNameLen = 0;

rc = OCISodaCollList(svchp,
                     startName,
                     (ub4) strlen(startName),
                     startNameLen,
                     &collectionCursor,
                     errhp,
                     OCI_DEFAULT);

if (rc != OCI_SUCCESS) goto finally;

do
{
  rc = OCISodaCollGetNext(svchp,
                          collectionCursor,
                          &collhp,
                          errhp,
                          OCI_DEFAULT);
  if (rc == OCI_NO_DATA || rc == OCI_INVALID_HANDLE || rc == OCI_ERROR) goto finally;

  rc = OCIAttrGet((dvoid *) collhp,
                  OCI_HTYPE_SODA_COLLECTION,
                  (dvoid *) &collectionName,
                  &collectionNameLen,
                  OCI_ATTR_SODA_COLL_NAME,
                  errhp);

  if (rc != OCI_SUCCESS) goto finally;
  printf("%s\n", collectionName);
  if (collhp) OCIHandleFree((dvoid *) collhp, (ub4) OCI_HTYPE_SODA_COLLECTION));
}
while(1);

finally:
if (collectionCursor) OCIHandleFree((dvoid *) collectionCursor, (ub4)OCI_HTYPE_SODA_CURSOR);

この例では、startNameNULLで、startNameLen0です。その結果、カーソルはデータベース内のすべてのコレクションを反復処理します。

または、既存のコレクションのサブセットのみを反復処理できます。その場合、startName"myCollectionB"などの既存のコレクションの名前に設定し、startNameLenをその文字列の長さに設定できます。カーソルは、そのコレクションとそのコレクション名の後ろに名前がアルファベット順に並んでいるコレクションのみを反復処理します。コレクションは、名前のアルファベット順に反復処理されます。

たとえば、既存のコレクションが"myCollectionA""myCollectionB"および"myCollectionC"であり、startName"myCollectionB"であると、カーソルは"myCollectionB"および"myCollectionC"をこの順序で反復処理します。

3.6 SODA for Cを使用したドキュメント・コレクションのドロップ

ドキュメント・コレクションをドロップするには、OCI関数OCISodaCollDrop()を使用します。

Oracle SQL文DROP TABLEとは異なり、関数OCISodaCollDrop()はコレクションをドロップする前後にコミット操作を暗黙的に実行しません。コレクションの削除を完了するには、OCISodaCollDrop()を呼び出す前に、コミットされていないすべての書込みをコレクションに明示的にコミットする必要があります。

コレクション・ハンドルを使用してコレクションをドロップしても、ハンドルは解放されません。ハンドルを解放するには、OCI関数OCIHandleFree()を使用します。

注意:

SQLを使用して、コレクションの基礎となるデータベースをドロップしないでください。コレクションのドロップには、単なるデータベース表のドロップよりも多くのことが含まれます。表に格納されるドキュメントに加えて、コレクションにはOracle Databaseにも残っているメタデータが含まれています。コレクションの基礎となる表をドロップしても、同様にコレクション・メタデータがドロップされることはありません

注意:

SODAを使用する通常のアプリケーションを日常的に使用する場合、コレクションをドロップして再作成する必要はありません。しかし、なんらかの理由でこれを行う必要がある場合は、このガイドラインが適用されます。

多少なりともコレクションを使用しているアプリケーションがある場合は、コレクションをドロップした後に異なるメタデータで再作成しないでください。すべてのライブSODAハンドルが解放されるように、コレクションを再作成する前にこのようなアプリケーションをすべて停止します。

コレクションのドロップだけでは、問題は発生しません。ドロップされたコレクションの読取りまたは書込み操作でエラーが発生します。コレクションをドロップして同じメタデータを持つコレクションを再作成しても、問題はありません。ただし、異なるメタデータでコレクションを再作成して、SODAハンドルを使用するライブ・アプリケーションが存在する場合、古いコレクションがアクセスされるというリスクがあり、この場合、エラーは発生しません

関連項目:

OCI関数OCISodaCollDrop()の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照

例3-5 ドキュメント・コレクションのドロップ

この例では、OCI関数OCISodaCollDrop()を使用してコレクションをドロップします。(変数collhpは、既存のコレクション(OCISodaCollインスタンス)を指すものとみなされます)。

コミットされていない書込み操作のためにコレクションをドロップできない場合、エラーが返されます。コレクションが正常にドロップされた場合、outパラメータdropStatusの値はTRUEで、それ以外の場合はFALSEです。

コレクション・ハンドル引数(この例ではcollhp)が既存のコレクションを参照しなくなった場合、エラーは返されませんが、OCISodaCollDrop()の呼出し後はdropStatusFALSEになります。

boolean dropStatus = FALSE;
rc = OCISodaCollDrop(svchp, collhp, &dropStatus, errhp, OCI_DEFAULT);

3.7 SODA for Cを使用したドキュメントの作成

SODAドキュメントを作成する様々な方法が、ドキュメントのコンポーネントとともに説明されています。

SODA for Cは、OCISodaDocハンドルを使用してドキュメントを表します。これは、ドキュメント・コンテンツおよびドキュメント・キーなどの他のドキュメント・コンポーネントのキャリヤです。ドキュメント・コンポーネントはハンドル属性です。

JSONドキュメントのコンテンツの例を次に示します。

{ "name" :    "Alexander",
  "address" : "1234 Main Street",
  "city" :    "Anytown",
  "state" :   "CA",
  "zip" :     "12345"
}

ドキュメントには次のコンポーネントがあります。

  • キー

  • コンテンツ

  • 作成時のタイムスタンプ

  • 最終変更のタイムスタンプ

  • バージョン

  • メディア・タイプ(JSONドキュメントの場合、"application/json")

次の方法でドキュメントを作成できます。

  • OCISodaDocCreate()OCISodaDocCreateWithKey()またはOCISodaDocCreateWithKeyAndMType()など、ドキュメントを作成するために特別に設計されたOCI関数を呼び出します。

    例3-6および例3-7に、これを示します。これらは、どちらもモジュール・ハンドルを作成します。どちらの場合も、作成されたドキュメントのメディア・タイプは"application/json"にデフォルト設定され、他のドキュメント・コンポーネントはNULLにデフォルト設定されます。

  • ハンドルの型がOCI_HTYPE_SODA_DOCUMENTの関数OCIHandleAlloc()を呼び出すことにより、空のドキュメント(ハンドル)を作成します。

    例3-8に、これを示します。

すでに値があるかどうかにかかわらず、関数OCIAttrSet()を使用してドキュメント・コンポーネント(ドキュメント・ハンドル属性)を定義(設定)できます。

2番目の方法(OCIHandleAlloc())を使用してドキュメントを作成する場合は、関数OCIAttrSet()を呼び出してコンテンツ・コンポーネントを設定する必要があります。クライアントによって割り当てられたキーを持つコレクションにドキュメントを書き込む場合は、キーを設定するためにも呼び出す必要があります。ドキュメントにJSON以外のコンテンツを含める場合は、メディア・タイプを設定するためにも呼び出す必要があります。

ただし、ドキュメントを作成すると、複数のドキュメント操作のハンドルを再利用できます。たとえば、コンテンツまたはその他のコンポーネントを変更して、同じハンドルを別の書込み操作に渡せます。

コレクションでは、各ドキュメントにキーが必要です。ドキュメントを作成する場合で、ドキュメントをコレクションに挿入する必要があり、挿入されるドキュメントに対してコレクションで自動的にキーを生成しない場合にのみ、キーを指定する必要があります。デフォルトでは、コレクションは自動的にドキュメント・キーを生成するように構成されます。キーを自動的に生成する必要がある場合は関数OCISodaDocCreate()を使用し、それ以外の場合はキー(パラメータkey)をOCISodaDocCreateWithKey()またはOCISodaDocCreateWithKeyAndMType()に指定します。

ドキュメントのメディア・タイプを指定する場合は(指定しない場合のデフォルトは"application/json")、関数OCISodaDocCreateWithKeyAndMType()を使用します。これは、JSONドキュメントを("application/json"以外のメディア・タイプを使用して)作成するために役立つことがあります。

どちらのドキュメント作成関数を使用する場合でも、それを呼び出すと、指定したドキュメント・コンポーネント(コンテンツ、場合によってはキーおよびメディア・タイプ)が指定した値に設定されます。また、作成時タイムスタンプ、最終変更のタイムスタンプおよびバージョンをnullに設定します。

OCI関数OCIAttrGet()を使用してドキュメント・コンポーネントを取得します。これは、ハンドル属性の値を取得するのと同じ方法です。取得するコンポーネントのタイプを5番目の引数としてOCIAttrGet()に渡します。

表3-1 ドキュメント・ハンドル属性(ドキュメント・コンポーネント)

属性 説明

OCI_ATTR_SODA_KEY

ドキュメントの一意のキー

OCI_ATTR_SODA_CREATE_TIMESTAMP

ドキュメントの作成時のタイムスタンプ

OCI_ATTR_SODA_LASTMOD_TIMESTAMP

ドキュメントの最終変更のタイムスタンプ

OCI_ATTR_SODA_MEDIA_TYPE

ドキュメントのメディア・タイプ

OCI_ATTR_SODA_VERSION

ドキュメントのバージョン

OCI_ATTR_SODA_CONTENT

ドキュメントのコンテンツ

ドキュメントを作成した直後に、OCIAttrGet()はコンポーネントの次の値を返します。

  • ドキュメント作成関数に明示的に提供された値

  • 作成関数にメディア・タイプが提供されていなかった場合は、OCI_ATTR_SODA_MEDIA_TYPEに対して"application/json"

  • 他のコンポーネントの場合はNULL

関連項目:

例3-6 JSONコンテンツを含むドキュメントの作成

この例では、OCISodaDocCreate()を使用してドキュメント・ハンドルを作成し、ドキュメントにコンテンツを埋め込みます。その後、ドキュメント・ハンドルが解放されます。脚注1

OCISodaDoc *dochp =  NULL;
OraText    *documentContent = "{\"name\":\"Alexander\"}";
ub4         docFlags = OCI_DEFAULT;

rc = OCISodaDocCreate(envhp,
                      documentContent,
                      (ub4) strlen(documentContent),
                      docFlags,
                      &dochp,
                      errhp,
                      OCI_DEFAULT)
// Make further use of handle dochp...
if (dochp) OCIHandleFree((dvoid *) dochp, (ub4) OCI_HTYPE_SODA_DOCUMENT);

例3-7 ドキュメント・キーおよびJSONコンテンツを含むドキュメントの作成

この例は、例3-6に似ていますが、OCISodaDocCreateWithKey()を使用して、ドキュメント・キー(myKey)とドキュメント・コンテンツを提供します。次に、OCISodaDocCreateWithKey()によって設定されたnull以外のドキュメント・コンポーネント(キー、コンテンツおよびメディア・タイプ)を取得して出力します。その後、ドキュメント・ハンドルを解放します。

OCISodaDoc *dochp =  NULL;
OraText    *documentContent = "{\"name\":\"Alexander\"}";
OraText    *key = "myKey";
ub4         docFlags = OCI_DEFAULT;
sword       rc = OCI_SUCCESS;
OraText    *finalKey;
ub4         finalKeyLen = 0;
OraText    *finalContent;
ub4         finalContentLen = 0;
OraText    *media;
ub4         mediaLen = 0;

rc = OCISodaDocCreateWithKey(envhp,
                             documentContent,
                             (ub4) strlen(documentContent),
                             key,
                             (ub4) strlen(key),
                             docFlags,
                             &dochp,
                             errhp,
                             OCI_DEFAULT)
  
if (rc != OCI_SUCCESS) goto finally;

// Get and print the key, content and media type, which were set by OCISodaDocCreateWithKey().
OCIAttrGet((dvoid *) dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *) &finalKey,
           &finalKeyLen,
           OCI_ATTR_SODA_KEY,
           errhp);
printf ("Key: %.*s\n", finalKeyLen, finalKey);
  
OCIAttrGet((dvoid *) dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *) &finalContent,
           &finalContentLen,
           OCI_ATTR_SODA_CONTENT,
           errhp);
printf ("Content: %.*s\n", finalContentLen, finalContent);

OCIAttrGet((dvoid *)dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *) &media,
           &mediaLen,
           OCI_ATTR_SODA_MEDIA_TYPE,
           errhp);
printf ("Media type: %.*s\n", mediaLen, media);

finally:
if (dochp) OCIHandleFree((dvoid *) dochp, (ub4) OCI_HTYPE_SODA_DOCUMENT);

印刷出力は次のとおりです。

Key: myKey
Content: {"name" : "Alexander"}
Media type: application/json 

例3-8 空のドキュメントの作成とそれに続くコンポーネントの定義

sword       rc = OCI_SUCCESS;
OCISodaDoc *dochp = NULL;
OraText    *documentContent= "{\"name\":\"Alexander\"}";

rc = OCIHandleAlloc((void *) envhp,
                    (void **) &dochp,
                    OCI_HTYPE_SODA_DOCUMENT,
                    (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

rc = OCIAttrSet(dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                documentContent,
                (ub4) strlen(documentContent),
                OCI_ATTR_SODA_CONTENT,
                errhp);
finally: ...

3.8 SODA for Cを使用したドキュメントのコレクションへの挿入

ドキュメントをSODAコレクションに挿入する様々な方法が説明されています。

ドキュメント・ハンドルを作成した場合は、関数OCISodaInsert()またはOCISodaInsertAndGet()を使用して、ドキュメントをコレクションに挿入できます。コレクションがクライアントで割り当てられたキーで構成されておらず、入力ドキュメントがキーを指定していない場合、これらの関数では、ドキュメント・キーが自動的に作成されます。これらの関数は、引数の1つとしてドキュメント・ハンドルが必要です。

便宜上、関数OCISodaInsertWithCtnt()またはOCISodaInsertAndGetWithCtnt()を使用して、ドキュメント・ハンドルを作成せずにドキュメントを挿入することもできます。コンテンツと(必要に応じて)ドキュメントのキーのみを提供します。(キーは、クライアントで割り当てられたキーを持つコレクションに挿入するときにのみ必要になります。)

ターゲット・コレクションが、作成時のタイムスタンプおよび最終変更のタイムスタンプのコンポーネントを持つドキュメント用に構成されている場合、ドキュメントの挿入関数はすべて、これらのコンポーネントを自動的に設定します。コレクションが、ドキュメント・バージョンを自動的に生成するように構成されている場合、挿入関数はバージョン・コンポーネントも設定します。(デフォルトのコレクション構成では、タイムスタンプ・コンポーネントおよびバージョン・コンポーネントの両方が提供されています。)

OCISodaInsertAndGet()関数およびOCISodaInsertAndGetWithCtnt()関数は、ドキュメントを挿入するだけでなく、結果ドキュメントを返します。結果ドキュメントには、キー、バージョン、作成タイムスタンプ、最終更新タイムスタンプなどの生成されたドキュメント・コンポーネントが含まれています。挿入されたドキュメントのコンテンツは含まれていません

注意:

コレクションがクライアントで割り当てられたドキュメント・キーで構成されていて(デフォルトの場合と異なるケース)、入力ドキュメントがコレクション内の既存のドキュメントを識別するキーを提供している場合、これらのメソッドはエラーを返します。

関連項目:

例3-9 コレクションへのドキュメントの挿入

この例では、ドキュメントを作成し、関数OCISodaInsert()を使用してこれをコレクションに挿入します。モード・パラメータOCI_SODA_ATOMIC_COMMITの使用により、挿入およびその他の未処理の操作がコミットされます。

OCISodaDoc *dochp = NULL;
OraText    *documentContent = "{\"name\":\"Alexander\"}";

rc = OCISodaDocCreate(envhp,
                      documentContent,
                      (ub4) strlen(documentContent),
                      OCI_DEFAULT,
                      &dochp,
                      errhp,
                      OCI_DEFAULT);

if (rc != OCI_SUCCESS) goto finally:

rc = OCISodaInsert(svchp,
                   collhp,
                   dochp,
                   errhp,
                   OCI_SODA_ATOMIC_COMMIT);

finally: ...

例3-10 コレクションへのドキュメントの挿入および結果ドキュメントの取得

この例では、ドキュメントを作成し、関数OCISodaInsertAndGet()を使用してこれをコレクションに挿入して、挿入後に結果ドキュメントも返します。この例では次に、その結果ドキュメント(生成されたコンポーネントを含む)から生成済コンポーネント(作成時のタイムスタンプ、最終変更のタイムスタンプ、メディア・タイプおよびバージョン)をそれぞれ取得(および印刷)します。これらの各コンポーネントを取得するには、関数OCIAttrGet()を使用して、コンポーネントのタイプ(OCI_ATTR_SODA_CREATE_TIMESTAMPOCI_ATTR_SODA_LASTMOD_TIMESTAMP OCI_ATTR_SODA_MEDIA_TYPEOCI_ATTR_SODA_VERSION)を渡します。

sword rc = OCI_SUCCESS;

OraText    *key = "myKey1";
OraText    *documentContent = "{\"name\":\"Alexander\"}";
ub4         docFlags = OCI_DEFAULT;
OCISodaDoc *dochp = NULL;
OCISodaDoc *origDochp = NULL;
OraText    *resultKey;
ub4         resultKeyLen = 0;
OraText    *resultCreatedOn;
ub4         resultCreatedOnLen = 0;
OraText    *resultLastModified;
ub4         resultLastModifiedLen = 0;
OraText    *resultVersion;
ub4         resultVersionLen = 0;
OraText    *resultMedia;
ub4         resultMediaLen = 0;

// Create a document with key "myKey1"
rc = OCISodaDocCreateWithKey(envhp,
                             documentContent,
                             (ub4) strlen(documentContent),
                             key,
                             (ub4) strlen(key),
                             docFlags,
                             &dochp,
                             errhp,
                             OCI_DEFAULT);

if (rc != OCI_SUCCESS) goto finally;

// Insert the document into a collection.

// collhp is a collection-handle pointer.  We assume the collection it
// points to was configured to use client-assigned keys.

// Because OCISodaInsertAndGet returns the result document as dochp, we first
// save the pointer to the original input document handle, which is returned by
// OCISodaDocCreateWithKey, as origDochp.  This lets us free the original
// document handle later.
 
origDochp = dochp;

rc = OCISodaInsertAndGet(svchp,
                         collhp,
                         &dochp,
                         errhp,
                         OCI_SODA_ATOMIC_COMMIT);

if (rc != OCI_SUCCESS) goto finally;

// Print some components of the result document.  (For brevity we omit checking
// for a return value of OCI_SUCCESS in all OCIAttrGet() calls here.)

OCIAttrGet((dvoid *)dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *)&resultCreatedOn,
           &resultCreatedOnLen,
           OCI_ATTR_SODA_CREATE_TIMESTAMP,
           errhp);
printf ("Created-on time stamp: %.*s\n", resultCreatedOnLen, resultCreatedOn);

OCIAttrGet((dvoid *)dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *)&resultLastModified,
           &resultLastModifiedLen,
           OCI_ATTR_SODA_LASTMOD_TIMESTAMP,
           errhp);
printf ("Last-modified time stamp: %.*s\n", resultLastModifiedLen, resultLastModified);

OCIAttrGet((dvoid *)dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *)&resultVersion,
           &resultVersionLen,
           OCI_ATTR_SODA_VERSION,
           errhp);
printf ("Version: %.*s\n", resultVersionLen, resultVersion);

OCIAttrGet((dvoid *)dochp,
           OCI_HTYPE_SODA_DOCUMENT,
           (dvoid *)&resultMedia,
           &resultMediaLen,
           OCI_ATTR_SODA_MEDIA_TYPE,
           errhp);
printf ("Media type: %.*s\n", resultMediaLen, resultMedia);

finally:
    
// Free the document handles
if (origDochp) OCIHandleFree((dvoid *) origDochp, (ub4) OCI_HTYPE_SODA_DOCUMENT);

if (dochp) OCIHandleFree((dvoid *) dochp, (ub4) OCI_HTYPE_SODA_DOCUMENT);

例3-11 ハンドルを指定しないコレクションへのドキュメントの挿入

この例では、関数OCISodaInsertWithCtnt()を使用して、ドキュメント・ハンドルを指定せずにコレクションにドキュメントを挿入します。ドキュメント・キーおよびコンテンツのみが引数として提供されます。

ここでは、クライアントで割り当てられたキーで構成されたコレクションにドキュメントを挿入していると仮定します。かわりに、自動生成キー用に構成されたコレクションにドキュメントを挿入する場合は、キー引数としてNULLを渡し、(キー引数の直後の)キー長さ引数として0を渡します。

OraText *documentContent = "{\"name\":\"Hannibal\"}";
OraText *key = "myKey2";

rc = OCISodaInsertWithCtnt(svchp,
                           collhp,
                           key,
                           (ub4) strlen(key),
                           (void *)documentContent,
                           (ub4) strlen(documentContent),
                           errhp,
                           OCI_SODA_ATOMIC_COMMIT);

3.9 SODA for Cの読取りおよび書込み操作

すべての読取り操作、および挿入操作以外の書込み操作では、(1)操作オプション・ハンドルを割り当て、(2)特定の操作を指定するために一部の属性を設定し、(3)操作を実行する汎用関数にハンドルを渡します。

読取り操作関数は次のとおりです。

  • OCISodaFindOne() — ドキュメントを検索して、1つのドキュメントのみを返します。

  • OCISodaFind() — 複数のドキュメントを検索し、それらへのカーソルを返します。

  • OCISodaDocCount() — 複数のドキュメントを検索し、見つかったドキュメントの数を返します。

書込み操作関数は次のとおりです。

  • OCISodaReplOne() — 1つのドキュメントを置換します。

  • OCISodaReplOneAndGet() — 1つのドキュメントを置換して、結果ドキュメントを返します。

  • OCISodaRemove() — 複数のドキュメントを削除します。

空の操作オプション・ハンドルを割り当てるには、OCIHandleAlloc()関数を使用します。

OCISodaOperationOptions *opthp;
// Create an empty operation options handle
rc = OCIHandleAlloc((void *) envhp,
                    (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS,
                    (size_t) 0,
                    (dvoid **) 0);

操作オプション・ハンドルの単一の属性を設定するには、OCIAttrSet()関数を使用します。たとえば、次の例はfilter属性に値{"name:"Ruth"}を設定しています。

OraText * filter = "{\"name\" : \"Ruth\"}";
// Set the filter on the operation options handle
rc = OCIAttrSet(opthp, 
                OCI_HTYPE_SODA_OPER_OPTIONS, 
                filter,
                strlen(filter),
                OCI_ATTR_SODA_FILTER,
                errhp);

複数のドキュメント・キーを表す属性はありません。複数のキーに関連する操作の場合は、OCISodaOperKeysSet()関数を使用してキーを設定します。

注意:

関数OCIAttrSet()を使用して操作オプション・ハンドルに属性OCI_ATTR_SODA_KEYを設定し、関数OCISodaOperKeysSet()を使用して同じハンドルに複数のキーを設定する場合、2つの設定のうち新しい方のみが有効になります。最初に呼び出された関数の有効性は、2番目の関数によってオーバーライドされます。

関連項目:

3.10 SODA for Cを使用したコレクションでのドキュメントの検索

コレクション内のドキュメントを検索するには、OCISodaFind()関数を使用し、特定の検索操作を指定する操作オプション・ハンドルを渡します。特定のキーを持つ一意のドキュメントを検索するには、操作オプション・ハンドルを必要としないOCIの簡易関数OCISodaFindOneWithKey()を使用することもできます。

関連項目:

例3-12 コレクション内のすべてのドキュメントの検索

この例は、コレクション内の各ドキュメントを含む問合せ結果リストのカーソルを最初に取得します。次にwhile文のカーソルを使用し、各ドキュメントのコンポーネントを文字列として取得して出力します。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
OraText                 *version = NULL;
ub4                      versionLen = 0;
OraText                 *lastModified = NULL;
ub4                      lastModifiedLen = 0;
OraText                 *mediaType = NULL;
ub4                      mediaTypeLen = 0;
OraText                 *createdOn = NULL;
ub4                      createdOnLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OCISodaDocCursor        *cursorhp = NULL;
OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Find all documents in the collection.
//
// Because the operation-options handle (opthp) is empty, no conditions
// are set on the find operation, so all documents are returned.
//
// collhp is an OCISodaColl pointer, representing an open collection.
//
// cursorhp is a OCISodaDocCursor pointer to a returned cursor over the
// resulting document set.
rc = OCISodaFind(svchp,
                 collhp,
                 opthp,
                 findFlags,
                 &cursorhp,
                 errhp,
                 OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Fetch each document from the cursor, and print all of its components.
while (OCISodaDocGetNext(svchp,
                         cursorhp,
                         &foundDochp,
                         errhp,
                         OCI_DEFAULT)
        == OCI_SUCCESS)
{
  // Get and print components of found document.
  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Key: %.*s\n", keyLen, key);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &version,
                  &versionLen,
                  OCI_ATTR_SODA_VERSION,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Version: %.*s\n", versionLen, version);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &lastModified,
                  &lastModifiedLen,
                  OCI_ATTR_SODA_LASTMOD_TIMESTAMP,
  if (rc != OCI_SUCCESS) goto finally;
  printf("Last-modified: %.*s\n", lastModifiedLen, lastModified);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &createdOn,
                  &createdOnLen,
                  OCI_ATTR_SODA_CREATE_TIMESTAMP,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Created: %.*s\n", createdOnLen, createdOn);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &mediaType,
                  &mediaTypeLen,
                  OCI_ATTR_SODA_MEDIA_TYPE,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Media Type: %.*s\n", mediaTypeLen, mediaType);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &content,
                  &contentLen,
                  OCI_ATTR_SODA_CONTENT,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Content: %.*s \n", contentLen, content);

  // Important: free document handle before fetching next document.
  // This releases memory associated with the current document.
  if (foundDochp)
    (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
}

finally:

// Free all handles.
if (cursorhp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_DOC_CURSOR);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);

例3-13 ドキュメント・キーを付与した一意のドキュメントの検索

この例では、指定したUUIDキー(E914016C41174F6CBF7C877C7F9EB4C2)を持つ操作オプション・ハンドルを設定し、これをOCISodaFindOne()関数に渡して、そのキーを持つドキュメントを検索します。

ドキュメントの検索後、OCIAttrGet()関数を使用し、ドキュメントのキーとコンテンツを取得して出力します。最後に、コレクション、ドキュメントおよび操作オプションに割り当てられたドキュメント・ハンドルが解放されます。

操作オプション・ハンドルにキー属性を設定してOCISodaFindOne()を使用するかわりに、簡易関数OCISodaFindOneWithKeyを使用することもできます。これは操作オプション・ハンドルのかわりにキー引数を直接受け取ります。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OraText                 *inKey = "E914016C41174F6CBF7C877C7F9EB4C2";

OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the key of the document we want to find, on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey,
                strlen(inKey),
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Find the document with the key, by way of the operation-options handle.
//
// collhp is an OCISodaColl pointer, representing an open collection.
rc = OCISodaFindOne(svchp,
                    collhp, 
                    opthp,
                    findFlags, 
                    &foundDochp,
                    errhp,
                    OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Get and print components of found document.
rc = OCIAttrGet((dvoid *) foundDochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &key,
                &keyLen,
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Key: %.*s\n", keyLen, key);

rc = OCIAttrGet((dvoid *) foundDochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &content,
                &contentLen,
                OCI_ATTR_SODA_CONTENT,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Content: %.*s \n", contentLen, content);

finally:

// Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
if (opthp)     
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);

例3-14 ドキュメント・キーを指定した複数のドキュメントの検索

この例では、キーを使用して3つのドキュメントを検索します。キーとその文字列の長さ(配列)、およびキーの数(3)がOCISodaOperKeysSet()関数に渡され、操作オプション・ハンドルが適切に設定されます。(標準の関数OCIAttrSet()を使用して複数のキーとその長さを設定することはできません。)この例では、OCISodaFind()関数を呼び出してハンドルを渡します。

この例では、OCISodaFind関数を使用し、3つのドキュメントをそのキーを使用して検索しています。キーとその文字列の長さ(配列)、およびキーの数(3)がOCISodaOperKeysSet()関数に渡され、この情報を使用して操作オプション・ハンドルが設定されます。(標準の関数OCIAttrSet()を使用して複数のキーとその長さを設定することはできません。)

注意:

関数OCIAttrSet()を使用して操作オプション・ハンドルに属性OCI_ATTR_SODA_KEYを設定し、関数OCISodaOperKeysSet()を使用して同じハンドルに複数のキーを設定する場合、2つの設定のうち新しい方のみが有効になります。最初に呼び出された関数の有効性は、2番目の関数によってオーバーライドされます。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OraText                 *keys[3] = {"6B67A10BC6EB4FB7BFA1ECE7E697C507",
                                    "9195598AA9FB4F1CBFA376F35BF78588",
                                    "7FD55EED38BE4F70BF327F8132394E8B"};
ub4                      keyLengths[3];
int                      i = 0;

OCISodaDocCursor        *cursorhp = NULL;
OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Fill array of key lengths.
for(i=0; i<3; i++)
  keyLengths[i] = strlen(keys[i]);

// Set keys and their lengths on the operation-options handle.
//
// You cannot set keys and their lengths using standard function OCIAttrSet().
// Use function OCISodaOperKeysSet().
rc = OCISodaOperKeysSet(opthp,
                        keys,
                        keyLengths,
                        3,
                        errhp,
                        OCI_DEFAULT);

if (rc != OCI_SUCCESS) goto finally;

// Find documents in collection that match the keys set in operation-options handle.
//
// collhp is an OCISodaColl pointer, representing an open collection.
//
// cursorhp is a OCISodaDocCursor pointer to a returned cursor over the
// resulting document set.
rc = OCISodaFind(svchp,
                 collhp,
                 opthp,
                 findFlags,
                 &cursorhp,
                 errhp,
                 OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Fetch each document from the cursor, and its key and content.
while (OCISodaDocGetNext(svchp,
                         cursorhp,
                         &foundDochp,
                         errhp,
                         OCI_DEFAULT)
       == OCI_SUCCESS)
{
  // Get and print components of found document.
  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Key: %.*s\n", keyLen, key);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &content,
                  &contentLen,
                  OCI_ATTR_SODA_CONTENT,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Content: %.*s \n\n", contentLen, content);

  // Important: Free the document handle before fetching the next document.
  // This releases memory associated with the current document.
  if (foundDochp)
    (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
}

finally: 

// Free all handles
if (cursorhp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_DOC_CURSOR );
if (opthp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_OPER_OPTIONS );
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);

例3-15 フィルタ仕様によるドキュメントの検索

OCISodaFind()関数は、コレクション内のJSONドキュメントをフィルタするための強力な方法を提供します。これを使用するには、OCI_ATTR_SODA_FILTER属性をJSONの例による問合せ(QBEとも呼ばれる)として指定する操作オプション・ハンドルを渡します。

フィルタ指定の構文には、表現力があるJSONドキュメントのパターン・マッチング言語を使用します。この例では、SODA for CでQBEを使用する方法を示すためだけの非常に簡単なQBEのみを使用します。

この例では、操作オプション・ハンドルのOCI_ATTR_SODA_FILTER属性にnameフィールドの値が"Alexander"であるJSONドキュメントを指定するフィルタを設定しています。その後、この操作オプション・ハンドルを使用して、そのフィルタに一致するドキュメントを検索します。最後に、見つかった各ドキュメントのキーおよびコンテンツを出力します。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OraText                 *filter = "{ \"name\" : \"Alexander\"}";

OCISodaDocCursor        *cursorhp = NULL;
OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the filter (query-by-example, or QBE) on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                filter,
                strlen(filter),
                OCI_ATTR_SODA_FILTER,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Find all documents in collection that match filter set in operation-options handle.
//
// collhp is an OCISodaColl pointer, representing an open collection.
//
// cursorhp is a OCISodaDocCursor pointer to a returned cursor over the
// resulting document set.
rc = OCISodaFind(svchp,
                       collhp,
                       opthp,
                       findFlags,
                       &cursorhp,
                       errhp,
                       OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Fetch each document from the cursor, and print its key and content.
while (OCISodaDocGetNext(svchp,
                         cursorhp,
                         &foundDochp,
                         errhp,
                         OCI_DEFAULT)
       == OCI_SUCCESS)
{
  // Get and print key and content of found document.
  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Key: %.*s\n", keyLen, key);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &content,
                  &contentLen,
                  OCI_ATTR_SODA_CONTENT,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Content: %.*s \n\n", contentLen, content);

  // Important: Free the document handle before fetching next document.
  // This releases memory associated with the current document.
  if (foundDochp)
    (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
}

finally:

// Free all handles
if (cursorhp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_DOC_CURSOR );
if (opthp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_OPER_OPTIONS );
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);

例3-16 フィルタ指定およびページ区切りを使用したドキュメントの検索

この例では、ページ区切り問合せでOCISodaFind()関数を使用しています。これは、OCI_ATTR_SODA_FILTER属性(QBEとして)、OCI_ATTR_SODA_SKIP属性(スキップするドキュメントの数)およびOCI_ATTR_SODA_LIMIT属性(返されるドキュメントの最大数)を指定する操作オプション・ハンドルを渡します。この例は、ページ区切り(スキップおよび限定)を指定することを除き、例3-15と同じです。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OraText                 *filter = "{ \"name\" : \"Alexander\"}";
ub4                      skip = 1000;
ub4                      limit = 100;

OCISodaDocCursor        *cursorhp = NULL;
OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the filter (query-by-example, or QBE) on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                filter,
                strlen(filter),
                OCI_ATTR_SODA_FILTER,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Set the number of documents to skip on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                &skip,
                0,
                OCI_ATTR_SODA_SKIP,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Set the limit of the number of documents to return on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                &limit,
                0,
                OCI_ATTR_SODA_LIMIT,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Find all documents in collection that match filter set in operation-options handle.
// Honor  skip and limit values set in the handle.
//
// collhp is an OCISodaColl pointer, representing an open collection.
//
// cursorhp is a OCISodaDocCursor pointer to a returned cursor over the
// resulting document set.
rc = OCISodaFind(svchp,
                 collhp,
                 opthp,
                 findFlags,
                 &cursorhp,
                 errhp,
                 OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Fetch each document from the cursor, and print its key and content.
while (OCISodaDocGetNext(svchp,
                         cursorhp,
                         &foundDochp,
                         errhp,
                         OCI_DEFAULT)
       == OCI_SUCCESS)
{
  // Get and print components of found document.
  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &key,
                  &keyLen,
                  OCI_ATTR_SODA_KEY,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Key: %.*s\n", keyLen, key);

  rc = OCIAttrGet((dvoid *) foundDochp,
                  OCI_HTYPE_SODA_DOCUMENT,
                  (dvoid *) &content,
                  &contentLen,
                  OCI_ATTR_SODA_CONTENT,
                  errhp);
  if (rc != OCI_SUCCESS) goto finally;
  printf("Content: %.*s \n\n", contentLen, content);

  // Important: Free the document handle before fetching the next document.
  // This releases memory associated with the current document.
  if (foundDochp)
    (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
}

finally:

// Free all handles
if (cursorhp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_DOC_CURSOR );
if (opthp)
  (void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_OPER_OPTIONS );
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);

例3-17 特定バージョンのドキュメントの検索

この例では、検索するドキュメントのバージョンおよびキーを指定する操作オプション・ハンドルとともに、OCISodaFindOne()関数を使用しています。

通常、ドキュメントのバージョンを指定する場合はキーも指定します。ただし、フィルタによってコレクション内のドキュメントが1つのみ指定される場合は、フィルタと一緒にバージョンを指定できます。

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
OraText                 *version = NULL;
ub4                      versionLen = 0;
ub4                      findFlags = OCI_DEFAULT;

OraText                 *inKey = "E914016C41174F6CBF7C877C7F9EB4C2";
OraText                 *inVersion =
  "7CCEF2F54035DE9A9D64653645DBEF7E61B92142F2E41B3F6144262A5F7BC054";

OCISodaDocCursor        *cursorhp = NULL;
OCISodaDoc              *foundDochp = NULL;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the key on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey,
                strlen(inKey),
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Set the version on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inVersion,
                strlen(inVersion),
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Find document that matches key and version set on operation-options handle.
rc = OCISodaFindOne(svchp,
                          collhp,
                          opthp,
                          findFlags,
                          &foundDochp,
                          errhp,
                          OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Get the found document and print its key, version, and content.
rc = OCIAttrGet((dvoid *) foundDochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &key,
                &keyLen,
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Key: %.*s\n", keyLen, key);

rc = OCIAttrGet((dvoid *) foundDochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &version,
                &versionLen,
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Version: %.*s\n", versionLen, version);

rc = OCIAttrGet((dvoid *) foundDochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &content,
                &contentLen,
                OCI_ATTR_SODA_CONTENT,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Content: %.*s \n", contentLen, content);

finally:

// Free all handles
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (foundDochp)
  (void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);

例3-18 見つかったドキュメントの数のカウント

この例では、OCISodaDocCount()関数を使用して、特定のフィルタ指定を満たすコレクション内のすべてのドキュメントの数を取得しています。

OraText                 *filter = "{ \"name\" : \"Alexander\"}";
ub8                      count = 0;
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the filter (query-by-example, or QBE) on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                filter,
                strlen(filter),
                OCI_ATTR_SODA_FILTER,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Number of documents that match filter set on  operation-options handle is returned as count.
rc = OCISodaDocCount(svchp,
                     collhp,
                     opthp ,
                     &count,
                     errhp,
                     OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;
printf ("Number of matching documents: %d\n", count);

finally:

// Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION );
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS );

3.11 SODA for Cを使用したコレクション内のドキュメントの置換

コレクション内のドキュメントを置換するには、OCISodaReplOneAndGet()関数を使用し、置換するドキュメントのキーと新しい代替ドキュメントを指定する操作オプション・ハンドルを渡します。結果ドキュメントとしてその代替ドキュメントが返されます(メタデータがすべて入力された状態)。

OCISodaReplOne()関数は、結果ドキュメントが完全なメタデータとともに返されないことを除き、OCISodaReplOneAndGet()と同じです。

これらは最も汎用的なドキュメント置換関数です。より固有のユースケースのためには他の簡易関数もあります。

ドキュメントのコンテンツのみを置換する場合は、これらの簡易関数を使用できます。代替ドキュメントを渡すかわりに、新しい(JSON)コンテンツのみをテキスト引数として渡します。

  • OCISodaReplOneAndGetWithCtnt()

  • OCISodaReplOneWithCtnt()

ドキュメントのキーのみを指定する場合は、これらの簡易関数を使用できます。操作オプション・ハンドルを渡すかわりに、代替ドキュメントと置換するドキュメントのキーのみを渡します。つまり、フィルタ、ドキュメント・バージョンなどは指定できません。

  • OCISodaReplOneAndGetWithKey()

  • OCISodaReplOneWithKey()

名前にAndGetが含まれている関数は、入力ドキュメントに使用されたパラメータと同じパラメータの値として新しい(結果)ドキュメントを返すため、そのコンポーネントを取得できます。

どちらの置換関数を使用した場合も、置換操作が成功したかどうかを示すブール値が出力パラメータisReplacedとして返されます。

関連項目:

例3-19 キーが指定された場合のコレクション内のドキュメントの置換えおよび結果ドキュメントの取得

この例では、UUIDキー"3C03C00FA3904FC2BF5182C424A2C6C1"を持つドキュメントの代替として新しいドキュメントを作成します。OCI関数OCISodaReplOneAndGet()を使用し、そのキーを持つドキュメントを置換して結果ドキュメントを取得します。

これは、関数OCIAttrGet()を使用し、結果のドキュメントから様々なコンポーネントを取得して出力します。モード・パラメータOCI_SODA_ATOMIC_COMMITの使用により、置換およびその他の未処理の操作がコミットされます。

OCISodaDoc              *dochp = NULL;
OCISodaDoc              *tempDochp = NULL;

// Document content: JSON data
char                     documentContent[30] = "{\"name\":\"LiLing\"}";
ub4                      docFlags = OCI_DEFAULT;

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
OraText                 *version = NULL;
ub4                      versionLen = 0;
OraText                 *lastModified = NULL;
ub4                      lastModifiedLen = 0;
OraText                 *mediaType = NULL;
ub4                      mediaTypeLen = 0;
OraText                 *createdOn = NULL;
ub4                      createdOnLen = 0;
boolean                  isReplaced = FALSE;

OCISodaOperationOptions *opthp;
OraText                 *inKey = "3C03C00FA3904FC2BF5182C424A2C6C1";

// Create a temporary replacement document, which has documentContent as its content.
rc = OCISodaDocCreate(envhp,
                      documentContent,
                      (ub4) strlen(documentContent),
                      docFlags,
                      &dochp,
                      errhp,
                      OCI_DEFAULT);
if (rc != OCI_SUCCESS)
{
  printf("OCISodaDocCreate failed\n");
  goto finally;
}

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the document-key attribute on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey,
                strlen(inKey),
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// OCISodaReplOneAndGet returns the result document as dochp, so
// before calling it we save a pointer, tempDochp, to the handle that
// was returned by OCISodaDocCreate.  Later we free tempDochp.
tempDochp = dochp;

// Replace the document that has the key set in the operation-options
// handle with the new, replacement document pointed to by dochp, and
// get back the result document.
//
// The result document has the content of the replacement
// document, but it also has all of the other document components,
// automatically populated by SODA when the replacement document was inserted.
rc = OCISodaReplOneAndGet(svchp,
                          collhp,
                          opthp,
                          &dochp,
                          &isReplaced,
                          errhp,
                          OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (isReplaced) printf ("Document was replaced.\n");

// Get and print the components of the document after replacement.
rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &key,
                &keyLen,
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Key: %.*s\n", keyLen, key);

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &version,
                &versionLen,
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Version: %.*s\n", versionLen, version);

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &lastModified,
                &lastModifiedLen,
                OCI_ATTR_SODA_LASTMOD_TIMESTAMP,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Last-modified: %.*s\n", lastModifiedLen, lastModified);

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &createdOn,
                &createdOnLen,
                OCI_ATTR_SODA_CREATE_TIMESTAMP,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Created: %.*s\n", createdOnLen, createdOn);

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &mediaType,
                &mediaTypeLen,
                OCI_ATTR_SODA_MEDIA_TYPE,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Media Type: %.*s\n", mediaTypeLen, mediaType);

finally:

// Release the session and free all handles, including the handle of the temporary document.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (dochp)
  (void) OCIHandleFree((dvoid *) dochp, OCI_HTYPE_SODA_DOCUMENT);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
if (tempDochp)
  (void) OCIHandleFree((dvoid *) tempDochp, OCI_HTYPE_SODA_DOCUMENT);

例3-20 特定バージョンのドキュメントの置換

ドキュメントを置き換える場合にオプティミスティック・ロックを実装するには、この例のようにキーおよびバージョンの両方を指定できます。

OCISodaDoc              *dochp = NULL;
OCISodaDoc              *tempDochp = NULL;

// Document content: JSON data
char                     documentContent[30] = "{\"name\":\"Esmeralda\"}";
ub4                      docFlags = OCI_DEFAULT;

OraText                 *key = NULL;
ub4                      keyLen = 0;
OraText                 *content = NULL;
ub4                      contentLen = 0;
OraText                 *version = NULL;
ub4                      versionLen = 0;
boolean                  isReplaced = FALSE;

OCISodaOperationOptions *opthp;

OraText                 *inKey = "3C03C00FA3904FC2BF5182C424A2C6C1";
OraText                 *inVersion =
  "BD0A8E86428FFD68A00FAE7833B41404637EE0A31791B36EC4C78A5782272448";

// Create a temporary replacement document, which has documentContent as its content.
rc = OCISodaDocCreate(envhp,
                      documentContent,
                      (ub4) strlen(documentContent),
                      docFlags,
                      &dochp,
                      errhp,
                      OCI_DEFAULT);
if (rc != OCI_SUCCESS)
{
  printf("OCISodaDocCreate failed\n");
  goto finally;
}

// Allocate an empty operation options handle
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the key of the document we want to replace on the operation options handle
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey, 
                strlen(inKey),
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Set the version of the document we want to replace on the operation options handle
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inVersion,
                strlen(inVersion),
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// OCISodaReplOneAndGet returns the result document as dochp, so
// before calling it we save a pointer, tempDochp, to the handle that
// was returned by OCISodaDocCreate.  Later we free tempDochp.
tempDochp = dochp;

// Replace the document that has the key and version set in the
// operation-options handle with the new, replacement document pointed
// to by dochp, and get back the result document.
//
// The result document has the content of the replacement
// document, but it also has all of the other document components,
// automatically populated by SODA when the replacement document was inserted.
rc = OCISodaReplOneAndGet(svchp,
                          collhp,
                          opthp,
                          &dochp,
                          &isReplaced,
                          errhp,
                          OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (isReplaced) printf ("Document was replaced.\n");

// Get and print the components of found document after replacement.
rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &key,
                &keyLen,
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Key: %.*s\n", keyLen, key);

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &version,
                &versionLen,
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;
printf("Version: %.*s\n", versionLen, version);

finally:

// Release the session and free all handles, including handle of the temporary document.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (dochp)
  (void) OCIHandleFree((dvoid *) dochp, OCI_HTYPE_SODA_DOCUMENT);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
if (tempDochp)
  (void) OCIHandleFree((dvoid *) tempDochp, OCI_HTYPE_SODA_DOCUMENT);

3.12 SODA for Cを使用したコレクションからのドキュメントの削除

コレクションからドキュメントを削除するには、OCISodaRemove()関数を使用し、操作オプション・ハンドルを渡します。キーで指定した1つのドキュメントのみを削除する場合は、簡易関数OCISodaRemoveOneWithKey()を使用することもできます。操作オプション・ハンドルは必要ありません。キーを直接渡します。

どちらのドキュメント削除関数を使用した場合も、削除されたドキュメントの数がOUTパラメータとして返されます。

関連項目:

例3-21 ドキュメント・キーによるコレクションからのドキュメントの削除

この例では、UUIDキー"E914016C41174F6CBF7C877C7F9EB4C2"のドキュメントを削除します。モード・パラメータOCI_SODA_ATOMIC_COMMITの使用により、削除およびその他の未処理の操作がコミットされます。

OraText                 *inKey = "E914016C41174F6CBF7C877C7F9EB4C2";
ub8                      removeCount = 0;

OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the document-key attribute on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey,
                strlen(inKey),
                OCI_ATTR_SODA_KEY,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Remove the document that has the key set in the operation-options handle.
rc = =OCISodaRemove(svchp,
                    collhp,
                    opthp,
                    &removeCount,
                    errhp,
                    OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (removeCount > 0)
  printf("Successfully removed document.\n");
else
  printf("Document with specified key was not found.\n");

finally:

// Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);

例3-22 特定バージョンのドキュメントの削除

この例では、削除するドキュメントのバージョンおよびキーを指定する操作オプション・ハンドルとともに、OCISodaRemove()関数を使用しています。これは書込み操作のためにオプティミスティック・ロックを実装する場合に役立ちます。

通常、ドキュメントのバージョンを指定する場合はキーも指定します。ただし、フィルタによってコレクション内のドキュメントが1つのみ指定される場合は、フィルタと一緒にバージョンを指定できます。

ub8                      removeCount = 0;

OraText                 *inKey = "0C6132FC780D4F16BF9561FC9E2B4F98";
OraText                 *inVersion =
  "7CCEF2F54035DE9A9D64653645DBEF7E61B92142F2E41B3F6144262A5F7BC054";

OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle,
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the document-key attribute on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inKey,
                strlen(inKey),
                OCI_ATTR_SODA_KEY, 
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Set the document-version attribute on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                inVersion,
                strlen(inVersion),
                OCI_ATTR_SODA_VERSION,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Remove document that has the key and version set in the operation-options handle.
rc = OCISodaRemove(svchp,
                   collhp,
                   opthp,
                   &removeCount,
                   errhp,
                   OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (removeCount > 0)
  printf("Successfully removed document.\n");
else
  printf("Document with specified key was not found.\n");

finally:

// Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);

例3-23 ドキュメント・キーによるコレクションからのドキュメントの削除

この例では、OCISodaOperKeysSet()関数を使用して、操作オプション・ハンドルに2つのドキュメントのキーとキーの長さの属性を設定します。その後、OCISodaRemove()関数を呼び出し、それらのキーを持つドキュメントを削除します。OCISodaOperKeysSet()関数は、引数としてキーの配列、対応するキー長の配列、およびキーの数を受け入れます。(標準の関数OCIAttrSet()を使用して複数のキーとその長さを設定することはできません。)

注意:

関数OCIAttrSet()を使用して操作オプション・ハンドルに属性OCI_ATTR_SODA_KEYを設定し、関数OCISodaOperKeysSet()を使用して同じハンドルに複数のキーを設定する場合、2つの設定のうち新しい方のみが有効になります。最初に呼び出された関数の有効性は、2番目の関数によってオーバーライドされます。

OraText                 *keys[2] = {"ACF8C4BDA3E44F4CBF802C9708D00C10",
                                    "787B22133B254F0CBF2DB9975E277913"};

ub4                      keyLengths[2];
ub8                      removeCount = 0;
int                      i = 0;

OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Fill array of key lengths.
for(i=0; i<2; i++)
  keyLengths[i] = strlen(keys[i]);

// Set keys and key lengths on operation-options handle.
rc = OCISodaOperKeysSet(opthp,
                        keys,
                        keyLengths,
                        2,
                        errhp,
                        OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

// Remove documents matching the keys in the operation options handle.
rc = OCISodaRemove(svchp,
                   collhp,
                   opthp,
                   &removeCount,
                   errhp,
                   OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (removeCount > 0)
  printf("Successfully removed %d documents.\n", removeCount);
else
  printf("Document with specified keys were not found.\n");

finally:

// Free all handles.
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);

例3-24 フィルタによるコレクションからのJSONドキュメントの削除

この例では、フィルタを使用してgreetingフィールドの値が"hello"であるJSONドキュメントを削除します。その後、削除されたドキュメントの数を出力します。

ub8                      removeCount = 0;
OraText                 *filter = "{\"greeting\" : \"hello\"}";
OCISodaOperationOptions *opthp;

// Allocate an empty operation-options handle.
rc = OCIHandleAlloc((void *) envhp, (void **)&opthp,
                    OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
                    (dvoid **) 0);
if (rc != OCI_SUCCESS) goto finally;

// Set the filter (query-by-example, or QBE) on the operation-options handle.
rc = OCIAttrSet(opthp,
                OCI_HTYPE_SODA_OPER_OPTIONS,
                filter,
                strlen(filter),
                OCI_ATTR_SODA_FILTER,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Remove documents matching the filter (QBE) set in operation-options handle.
rc = OCISodaRemove(svchp,
                   collhp,
                   opthp,
                   &removeCount,
                   errhp,
                   OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;

if (removeCount > 0)
  printf("Successfully removed %d documents.\n", removeCount);
else
  printf("No documents matching the filter were found.\n");

finally:

//Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (opthp)
  (void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);

3.13 SODA for Cを使用したコレクション内のドキュメントの索引付け

索引付けを行うと、QBEのパフォーマンスを向上させることができます。SODAコレクション内のドキュメントを索引付けするには、OCISodaIndexCreate()関数を使用して、テキストのJSON索引指定を渡します。これにより、Bツリー、空間、全文および非定型の索引付けのサポートを指定し、JSONデータ・ガイドのサポートを指定できます。

  • Bツリー索引は、特定のスカラーJSONフィールドの索引付けに使用されます。

  • Oracle Spatial and Graph索引は、GeoJSON (空間)データを索引付けするために使用されます。

  • JSON検索索引を使用すると、次のパフォーマンスを向上させることができます。

    • 予期しないQBE、または定期的に使用しないQBE (汎用用途の索引)。

    • 演算子$containsを使用するQBE (全文検索)。

  • JSON検索索引では、JSONデータ・ガイド情報の永続的な記録および自動更新を行うこともできます。

JSON検索索引が定義されている場合、およびBツリー索引または空間索引が特定のQBEに適用されている場合、そのBツリーまたは空間索引は(より汎用的な)検索索引よりも優先してそのQBEに使用されます。

OCISodaIndexCreate()関数の呼出しは、作成する索引の種類にかかわらず同じです。唯一の違いは、関数に引数として渡される索引の指定です。

SODAコレクションに対する索引を削除するには、OCISodaIndexDrop()関数を使用し、索引名を渡します。

関連項目:

例3-25 SODA for Cを使用したJSONフィールドに対するBツリー索引の作成

この例では、ハンドルcollhpを持つコレクション内のJSONドキュメントの数値フィールドaddress.zipに対して、一意ではないBツリー索引を作成します。Bツリー索引の指定は、fieldsフィールドが存在することによって認識できます。

// Index specification for B-tree index on field address.zip.
OraText *indexSpec = "{\"name\" : \"ZIPCODE_IDX\", \
                       \"fields\" : [{\"path\" : \"address.zip\", \
                                      \"datatype\" : \"number\", \
                                      \"order\" : \"asc\"}]}";

// Create the index.
rc = OCISodaIndexCreate(svchp, collhp, indexSpec, strlen(indexSpec), errhp, OCI_DEFAULT);

例3-26 SODA for Cを使用したJSON検索索引の作成

この例では、非定型問合せおよび全文検索(演算子$containsを使用するQBE)のために、ハンドルcollhpを持つコレクション内のドキュメントを索引付けして、JSONドキュメントに関するデータ・ガイド情報を自動的に累計および更新します(構造およびタイプ情報を集計します)。索引指定のフィールドはnameのみです(fieldsフィールドは指定しません)。

// Index specification for JSON search index.
OraText *indexSpec = "{\"name\" : \"SEARCH_AND_DATA_GUIDE_IDX\"}";

// Create the index.
rc = OCISodaIndexCreate(svchp, collhp, indexSpec, strlen(indexSpec), errhp, OCI_DEFAULT);

ここで使用されている単純な索引指定は、デフォルト値を明示的に使用した次の指定と同じです。

{"name" : "SEARCH_AND_DATA_GUIDE_IDX",
 "dataguide" : "on",
 "search_on" : "text_value"}

かわりに非定型のみの索引付けを行う場合は、dataguideフィールドに値"off"を明示的に指定します。かわりにデータ・ガイドのみをサポートする場合は、search_onフィールドに値"none"を明示的に指定します。

注意:

データ・ガイド対応JSON検索索引を作成する、または既存のJSON検索索引をデータ・ガイド対応にするには、データベース権限CTXAPPおよびOracle Databaseリリース12c (12.2.0.1)以降が必要です。

例3-27 SODA for Cを使用した索引の削除

SODAコレクションに対する索引を削除するには、OCISodaIndexDrop()関数に索引名を渡します。この例では、索引ZIPCODE_IDXを削除します。

boolean isDropped = FALSE;

// Drop the index named ZIPCODE_IDX.
rc = OCISodaIndexDrop(svchp,
                      "ZIPCODE_IDX",
                      strlen("ZIPCODE_IDX"),
                      &isDropped,
                      errhp,
                      OCI_DEFAULT);

printf ("isDropped %d\n", isDropped);

3.14 SODA for Cを使用したコレクションのデータ・ガイドの取得

コレクションのデータ・ガイドを取得するには、OCISodaDataGuideGet()関数を使用します。データ・ガイドは、コレクション内のJSONドキュメントの構造およびタイプ情報をまとめたJSONドキュメントです。これらの文書内で使用されているフィールドに関するメタデータを記録します。

コレクションのデータ・ガイドを取得する前に、データ・ガイド対応のJSON検索索引を作成する必要があります。例3-26にその作成方法が示されています。

関連項目:

OCI関数CISodaDataGuideGet()の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照

例3-28 JavaのためのSODAによるデータ・ガイドの取得

この例では、OCISodaDataGuideGet()関数を使用して、コレクション・ハンドルcollhpを持つコレクションのデータ・ガイドを取得します。その後、データガイド・ドキュメントのコンテンツを出力します。

OCISodaDoc  *dochp = NULL;
OraText     *content = NULL;
ub4          contentLen = 0;

// Get the data guide based on the JSON search index defined on the collection.
// dochp is the handle for the data-guide document.
rc = OCISodaDataGuideGet(svchp,
                         collhp,
                         OCI_DEFAULT,
                         &dochp,
                         errhp,
                         OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;

rc = OCIAttrGet((dvoid *) dochp,
                OCI_HTYPE_SODA_DOCUMENT,
                (dvoid *) &content,
                &contentLen,
                OCI_ATTR_SODA_CONTENT,
                errhp);
if (rc != OCI_SUCCESS) goto finally;

// Print the content of the data-guide document.
printf("Data guide: %.*s \n", contentLen, content);

finally:

//Free all handles.
if (collhp)
  (void) OCIHandleFree((dvoid *) collhp, OCI_HTYPE_SODA_COLLECTION);
if (dochp)
  (void) OCIHandleFree((dvoid *) dochp, OCI_HTYPE_SODA_OPER_OPTIONS);

3.15 SODA for Cを使用したトランザクションの処理

個々の読取りおよび書込み操作、またはそのグループを、データベース・トランザクションとして処理できます。

次のいずれかの方法でこれを実行します。

  • SODA操作を呼び出すときに、実行モード・パラメータOCI_SODA_ATOMIC_COMMITを使用します。操作がこのモードで実行され、それが正常に完了した場合、現行のトランザクションは完了後にコミットされます。

    通常のコミットのように、これはSODA操作による変更のみでなく、すべての顕著な変更をコミットします。ただし、操作が失敗した場合、SODA操作による変更のみがロールバックされます。SODA操作の呼出し前に行われたコミットされていない変更はロールバックされません。

  • 関数OCITransCommit()またはOCITransRollback()は、現在のトランザクションをそれぞれコミットまたはロールバックする場合に使用されます。これらは標準のOracle Call Interface (OCI)関数であり、SODA固有ではありません。

コレクションの作成およびドロップのSODA操作は、アクションの実行前または実行後に自動的にコミットされません。(これは、アクションを実行する前後にコミットするSQL DDL文の動作とは異なります。)

この結果、SODAコレクションをドロップするには、その前に、未処理の書込み操作をコミットまたはロールバックする必要があります。これは、関数OCISodaCollDrop()自体、そのアクションを実行する前にコミットしないためです。 この場合、その動作はSQL DROP TABLE文の構成とは異なります。

関連項目:



脚注の凡例

脚注1: ハンドルの使用が完了したときに解放するためのリマインダとして、ハンドルはここですぐに解放されます(他のハンドルと同じです)。実際には、ハンドルを解放する前になんらかの方法でハンドルを使用します。