3 SODA for Cの使用
SODA for Cにアクセスする方法、およびこれを使用してコレクションに対する作成、読取り(取得)および削除(CRUD)操作を実行する方法について説明します。CRUD操作は、このドキュメントでは読取りおよび書込み操作とも呼ばれています。
- SODA for Cスタート・ガイド
SODA for Cにアクセスする方法、およびこれを使用してデータベース・コレクションを作成し、ドキュメントをコレクションに挿入し、コレクションからドキュメントを取得する方法について説明します。 - SODA for Cを使用したドキュメント・コレクションの作成
構成の詳細を気にしない場合は、OCI関数OCISodaCollCreate()
を使用してコレクションを作成します。これにより、デフォルトのメタデータを持つコレクションが作成されます。デフォルト以外の方法で構成されたコレクションを作成するには、かわりに関数OCISodaCollCreateWithMetadata()
を使用して、JSONで表されたカスタム・メタデータを渡します。 - SODA for Cを使用した既存のドキュメント・コレクションのオープン
既存のドキュメント・コレクションを開くには、OCI関数OCISodaCollOpen()
を使用します。 - SODA for Cを使用した指定されたコレクションが存在するかどうかの確認
指定された名前のコレクションの存在を確認するには、OCI関数OCISodaCollOpen()
を使用します。この関数は、コレクションが正常に開かれた場合にOCI_SUCCESS
を返します。これは、それが存在することを意味します。そのようなコレクションが存在しない場合、コレクション・ハンドルのポインタはNULL
です。 - SODA for Cを使用した既存のコレクションの検出
既存のコレクションを検出するには、OCI関数OCISodaCollList()
およびOCISodaCollGetNext()
を使用します。 - SODA for Cを使用したドキュメント・コレクションのドロップ
ドキュメント・コレクションをドロップするには、OCI関数OCISodaCollDrop()
を使用します。 - SODA for Cを使用したドキュメントの作成
SODAドキュメントを作成する様々な方法が、ドキュメントのコンポーネントとともに説明されています。 - SODA for Cを使用したコレクションへのドキュメントの挿入
ドキュメントをSODAコレクションに挿入する様々な方法が説明されています。 - SODA for Cを使用したコレクションへのドキュメントの保存
OCI関数OCISodaSave()
、OCISodaSaveWithCtnt()
、OCISodaSaveAndGet()
、OCISodaSaveAndGetWithCtnt()
およびOCISodaSaveAndGetWithOpts()
を使用して、ドキュメントをコレクションに保存できます。つまり、ドキュメントが新規の場合は挿入し、コレクションにすでに属している場合は更新します。(このような操作は「アップサート」と呼ばれることがあります。) - SODA for Cの読取りおよび書込み操作
すべての読取り操作、およびコレクションへの挿入および保存以外のすべての書込み操作では、(1)操作オプション・ハンドルを割り当て、(2)特定の操作を指定するために一部の属性を設定し、(3)操作を実行する汎用関数にハンドルを渡します。 - SODA for Cを使用したコレクション内のドキュメントの検索
コレクション内のドキュメントを検索するには、OCISodaFind()
関数を使用し、特定の検索操作を指定する操作オプション・ハンドルを渡します。特定のキーを持つ一意のドキュメントを検索するには、操作オプション・ハンドルを必要としないOCIの簡易関数OCISodaFindOneWithKey()
を使用することもできます。 - SODA検索操作のプリフェッチ・サイズの設定
OCISodaFind()
関数のコールでは、OCISodaDocGetNext()
で必要なクライアント・データベースのラウンドトリップ回数を減らすために、複数のドキュメントがプリフェッチされます。操作ハンドルでOCI_ATTR_SODA_FETCH_ARRAY_SIZE
属性を設定することによって、プリフェッチ・バッチに使用するドキュメント数を変更できます。 - SODA for Cを使用したコレクション内のドキュメントの置換
コレクション内のドキュメントを置換するには、OCISodaReplOneAndGet()
関数を使用し、置換するドキュメントのキーと新しい代替ドキュメントを指定する操作オプション・ハンドルを渡します。結果ドキュメントとしてその代替ドキュメントが返されます(メタデータがすべて入力された状態)。 - SODA for Cを使用したコレクションからのドキュメントの削除
関数OCISodaRemove()
およびOCISodaRemoveOneWithKey()
を使用して、コレクションからドキュメントを削除できます。 - SODA for Cを使用したコレクションの切捨て(すべてのドキュメントの削除)
コレクションは空にすることも、切り捨てることもできます。つまり、関数OCISodaCollTruncate()
を使用して、そのすべてのドキュメントを削除できます。 - SODA for Cを使用したコレクション内のドキュメントの索引付け
索引付けすると、QBEのパフォーマンスを向上させることができます。SODAコレクション内のドキュメントを索引付けするには、OCISodaIndexCreate()
関数を使用して、テキストのJSON索引指定を渡します。これにより、Bツリー、空間、全文および非定型の索引付けのサポートを指定し、JSONデータ・ガイドのサポートを指定できます。 - SODA for Cを使用したコレクションのデータ・ガイドの取得
コレクションのデータ・ガイドを取得するには、OCISodaDataGuideGet()
またはOCISodaDataGuideGetWithOpts()
関数を使用します。データ・ガイドは、コレクション内のJSONドキュメントの構造およびタイプ情報をまとめたJSONドキュメントです。これらの文書内で使用されているフィールドに関するメタデータを記録します。 - SODA for Cを使用したトランザクションの処理
個々の読取りおよび書込み操作、またはそのグループを、データベース・トランザクションとして処理できます。
3.1 SODA for Cスタート・ガイド
SODA for Cにアクセスする方法、およびこれを使用してデータベース・コレクションを作成し、ドキュメントをコレクションに挿入し、コレクションからドキュメントを取得する方法について説明します。
ノート:
最初に読んだときに、このトピック内のすべてが理解できなくても気にしないでください。必要な概念は、他のトピックで詳細に理解が進みます。このトピックは、SODAを使用する上で全体的に何が関与しているかをとらえるためのものです。
SODA for Cの使用を開始するには、次のステップを実行します。
-
SODA for Cを使用するための前提条件がすべて満たされていることを確認します。SODA for Cの前提条件を参照してください。
-
SODAコレクションを格納するデータベース・スキーマ(ユーザー・アカウント)にデータベース・ロール
SODA_APP
を付与します。(ここでプレースホルダuser
を実際のアカウント名で置き換えます。)GRANT SODA_APP TO user;
-
例3-1でCコードを含むプログラム・ファイルを作成しますが、変数
usr
、passwd
およびconnstr
を、データベース・アカウントおよびインスタンスに適切な文字値に設定します。 -
OCIプログラムの場合と同様に、ファイルをコンパイルして実行可能プログラムをビルドします。
-
プログラムを実行します。
コマンド行にプログラム名を入力するのみでこれを実行できます。たとえば、名前が
soda-get-started
の場合、コマンド行プロンプトにそれを入力します。> soda-get-started
プログラムの終了時にコレクションをドロップする場合は、コマンド行で引数
drop
を渡します。> soda-get-started drop
注意:
SQLを使用して、コレクションの基礎となるデータベース表をドロップしないでください。コレクションのドロップには、単なるデータベース表のドロップよりも多くのことが含まれます。表に格納されるドキュメントに加えて、コレクションにはOracle Databaseにも残っているメタデータが含まれています。コレクションの基礎となる表をドロップしても、同様にコレクション・メタデータがドロップされることはありません。
ノート:
-
SODA for Cの機能を使用する手持ちのCコードはすべて、最初にOCIオブジェクト・モードで環境を初期化し、ここでモード・パラメータとして
OCI_OBJECT
を関数OCIEnvNlsCreate()
に渡す必要があります。 -
SODAハンドル(ドキュメント、コレクション、およびその他)はすべて、プログラムで不要になったときに、関数
OCIHandleFree()
を使用して明示的に解放する必要があります。(特に、大規模なコンテンツのドキュメントのハンドルは、大量のメモリーと関連付けられている可能性があります。)
関連項目:
-
OCIアプリケーションの構築については、Oracle Call Interfaceプログラマーズ・ガイドを参照
-
OCIプログラミングの基本については、Oracle Call Interfaceプログラミング・ガイドを参照
例3-1 スタート・ガイド概要
このコード例では次の事項を実行します。
-
オブジェクト・モードでOracle Call Interface(OCI)環境を作成し、エラー・ハンドルを割り当て、
OCISessionGet()
関数を使用してセッションを取得します。 -
デフォルトのコレクション構成(メタデータ)を使用して、SODAドキュメント・コレクションを作成して開きます。
-
一部のJSONコンテンツを使用してSODAドキュメントを作成します。
-
ドキュメントをコレクションに挿入します。
-
挿入されたドキュメントを戻します。他のコンポーネントは、コンテンツ以外は自動的に生成されます。
-
自動的に生成されたコンポーネントの1つである一意のドキュメント・キーを出力します。
-
キーを指定して、コレクション内のドキュメントを検索します。
-
ドキュメント・コンポーネントの一部(キー、バージョン、最終変更のタイムスタンプ、作成時のタイムスタンプ、メディア・タイプ、およびコンテンツ)を出力します。
-
必要に応じて、コレクションをドロップして、コレクションとそのメタデータの格納に使用されるデータベース表をクリーン・アップします。
-
割り当てられたすべてのハンドルを解放します。
コレクションがドロップされているかどうかは、実行時に決定されます。コレクションをドロップするには、実行可能プログラムへのコマンド行引数として、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 variables usr and passwd to strings for user name and password.
// (Be sure to replace placeholders user and password used here.)
OraText usr[30] = user;
OraText passwd[30] = password;
// Set variable connstr to a string 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 variable collectionName, using
// default metadata.
rc = OCISodaCollCreate(svchp,
collectionName,
(ub4) strlen(collectionName),
&collhp,
errhp,
OCI_DEFAULT);
if (rc != OCI_SUCCESS)
{
printf("OCISodaCollCreate failed\n");
goto finally;
}
// Create 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 autogenerated 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;
}
親トピック: SODA for Cの使用
3.2 SODA for Cを使用したドキュメント・コレクションの作成
構成の詳細を気にしない場合は、OCI関数OCISodaCollCreate()
を使用してコレクションを作成します。これにより、デフォルトのメタデータを持つコレクションが作成されます。デフォルト以外の方法で構成されたコレクションを作成するには、かわりに関数OCISodaCollCreateWithMetadata()
を使用して、JSONで表されたカスタム・メタデータを渡します。
これらの関数のそれぞれについて、同じ名前のコレクションがすでに存在する場合は、コレクションが単に開かれてそのハンドルが返されます。関数OCISodaCollCreateWithMetadata()
の場合、渡されたメタデータが既存のコレクションのメタデータと一致しない場合、コレクションは開かれず、エラーが発生します。(一致するには、すべてのメタデータ・フィールドが同じ値である必要があります。)
例3-2では、関数OCISodaCollCreate()
を使用して、デフォルト構成(デフォルトのメタデータ)を含むコレクションを作成します。これは、コレクションをOCISodaColl
ハンドルとして返します。
デフォルトのコレクション・メタデータを持つコレクションには、次の特性があります。
-
JSONドキュメントのみを格納できます。
-
そのドキュメントのそれぞれに、キー、作成時のタイムスタンプ、最終変更のタイムスタンプの各コンポーネントがあります。
-
キーは、コレクションに追加したドキュメントに自動的に生成されます。
ほとんどの場合、デフォルトのコレクション構成をお薦めしますが、コレクションは高度な構成が可能です。コレクションを作成する場合、次のような項目を指定できます。
-
コレクションがJSONドキュメントのみを格納できるかどうか。
-
ドキュメント作成時のタイムスタンプ、最終変更のタイムスタンプおよびバージョン用の列の有無。
-
ドキュメント・キーの生成方式、およびキーをクライアントで割り当てるかまたは自動的に生成するか。
-
バージョンの生成方式。
-
記憶域の詳細。たとえば、コレクションを格納する表の名前、列の名前とデータ型など。
このように構成可能であるため、新規コレクションを既存のデータベース表にマップすることもできます。
ノート:
特に記載のないかぎり、このドキュメントでは、コレクションはデフォルト構成を使用していると想定しています。
関連項目:
-
コレクション表のデフォルトのネーミング規則については、Oracle Database Simple Oracle Document Access (SODA)の概要を参照
-
コレクション・メタデータ・コンポーネントの参照情報は、Oracle Database Simple Oracle Document Access (SODA)の概要を参照
-
OCI関数
OCISodaCollCreate()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaCollCreateWithMetadata()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例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);
親トピック: SODA for Cの使用
3.4 SODA for Cを使用した指定されたコレクションが存在するかどうかの確認
指定された名前のコレクションが存在するかどうかを確認するには、OCI関数OCISodaCollOpen()
を使用します。この関数は、コレクションが正常に開かれた場合にOCI_SUCCESS
を返します。これは、それが存在することを意味します。そのようなコレクションが存在しない場合、コレクション・ハンドルのポインタはNULL
です。
例3-3に、これを示します。MyCollection
が既存のコレクションの名前を指定している場合、そのコレクションが開かれて、コレクション・ハンドルcollhp
がそのコレクションを指します。MyCollection
が既存のコレクションの名前を指定していない場合は、関数OCISodaCollOpen()
を呼び出した後のコレクション・ハンドルcollhp
の値は引き続きNULL
です。
親トピック: SODA for Cの使用
3.5 SODA for Cを使用した既存のコレクションの検出
既存のコレクションを検出するには、OCI関数OCISodaCollList()
およびOCISodaCollGetNext()
を使用します。
関連項目:
-
OCI関数
OCISodaCollList()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaGetNext()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例3-4 すべての既存のコレクションの名前の出力
この例では、OCI関数OCISodaCollList()
を使用して、コレクションのカーソル(collectionCursor
)を取得します。さらに、このカーソルを反復処理して、各コレクションの名前を出力します。
OCISodaCollCursor *collectionCursor;
OCISodaColl *collhp;
OraText *startName = NULL;
ub4 startNameLen = 0;
OraText *collectionName = NULL;
ub4 collectionNameLen = 0;
sword rc;
rc = OCISodaCollList(svchp,
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_COLL_CURSOR);
この例では、startName
がNULL
で、startNameLen
が0
です。その結果、カーソルはデータベース内のすべてのコレクションを反復処理します。
または、既存のコレクションのサブセットのみを反復処理できます。その場合、startName
を"myCollectionB"
などの既存のコレクションの名前に設定し、startNameLen
をその文字列の長さに設定できます。カーソルは、そのコレクションとそのコレクション名の後ろに名前がアルファベット順に並んでいるコレクションのみを反復処理します。コレクションは、名前のアルファベット順に反復処理されます。
たとえば、既存のコレクションが"myCollectionA"
、"myCollectionB"
および"myCollectionC"
であり、startName
が"myCollectionB"
であると、カーソルは"myCollectionB"
および"myCollectionC"
をこの順序で反復処理します。
親トピック: SODA for Cの使用
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()
の呼出し後はdropStatus
はFALSE
になります。
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 ドキュメント・ハンドル属性(ドキュメント・コンポーネント)
属性 | 説明 |
---|---|
|
ドキュメントの一意のキー。 |
|
ドキュメントの作成時のタイムスタンプ。 |
|
ドキュメントの最終変更のタイムスタンプ。 |
|
ドキュメントのメディア・タイプ。 |
|
ドキュメントのバージョン。 |
|
ドキュメントのコンテンツ。 |
ドキュメントを作成した直後に、OCIAttrGet()
はコンポーネントの次の値を返します。
-
ドキュメント作成関数に明示的に提供された値
-
作成関数にメディア・タイプが提供されていなかった場合は、
OCI_ATTR_SODA_MEDIA_TYPE
に対して"application/json"
-
他のコンポーネントの場合は
NULL
関連項目:
-
SODAドキュメントの概要については、Oracle Database Simple Oracle Document Access (SODA)の概要を参照
-
SODAドキュメントに適用される制限については、Oracle Database Simple Oracle Document Access (SODA)の概要を参照
-
OCI関数
OCISodaDocCreate()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaDocCreateWithKey()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaDocCreateWithKeyAndMType()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCIHandleAlloc()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCIAttrSet()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例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()
関数は、ドキュメントを挿入するだけでなく、結果ドキュメントを返します。結果ドキュメントには、キー、バージョン、作成タイムスタンプ、最終更新タイムスタンプなどの生成されたドキュメント・コンポーネントが含まれています。挿入されたドキュメントのコンテンツは含まれていません。
関数OCISodaInsertAndGetWithOpts()
はOCISodaInsertAndGet()
に似ていますが、OCISodaOperationOptions
ハンドルのオプションに従ってドキュメントを挿入します。特に、これを使用して、SODAの基礎となるSQLコードに監視ヒントを渡すことができます。
操作オプション・ハンドルに属性OCI_ATTR_SODA_HINT
を設定して、SQLヒント構文のテキスト(つまり、SQLコメント構文/*+
...*/
で囲まれていないヒント・テキスト)を指定できます。ヒントMONITOR
(監視をオンにする)またはNO_MONITOR
(監視をオフにする)のみを使用します。
(これを使用してSQLヒントを渡すことができますが、MONITOR
とNO_MONITOR
はSODAに有用なヒントであり、適切でないヒントによってオプティマイザが最適でない問合せプランを生成する可能性があります。)
ノート:
コレクションがクライアントで割り当てられたドキュメント・キーで構成されていて(デフォルトの場合と異なるケース)、入力ドキュメントがコレクション内の既存のドキュメントを識別するキーを提供している場合、これらのメソッドはエラーを返します。
関連項目:
-
OCI関数
OCISodaInsert()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaInsertAndGet()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaInsertWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaInsertAndGetWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaBulkInsert()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaBulkInsertAndGet()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaBulkInsertWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaBulkInsertAndGetWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例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_TIMESTAMP
、OCI_ATTR_SODA_LASTMOD_TIMESTAMP
OCI_ATTR_SODA_MEDIA_TYPE
、OCI_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を使用したコレクションへのドキュメントの保存
OCI関数OCISodaSave()
、OCISodaSaveWithCtnt()
、OCISodaSaveAndGet()
、OCISodaSaveAndGetWithCtnt()
およびOCISodaSaveAndGetWithOpts()
を使用して、ドキュメントをコレクションに保存できます。つまり、ドキュメントが新規の場合は挿入し、コレクションにすでに属している場合は更新します。(このような操作は「アップサート」と呼ばれることがあります。)
ドキュメントの挿入または置換のみを行う同様の名前が付いた関数の場合と同様に、保存関数の名前はそれぞれ異なる動作を示します。
-
WithCtnt
が名前に含まれている保存関数は、ドキュメント・ハンドルではなくコンテンツを指定したドキュメントを挿入または置換します。コレクションのキーがクライアントによって割り当てられている場合は、ドキュメント・キーも指定します。 -
AndGet
が名前に含まれている保存関数は、結果ドキュメントを返します。これには、キー、バージョン、作成タイムスタンプ、最終更新タイムスタンプなどの生成されたドキュメント・コンポーネントが含まれています。挿入されたドキュメントのコンテンツは含まれていません。(ドキュメントのコンテンツは含まれていません。)これらの関数では、引数としてドキュメント・ハンドルが必要です。 -
関数
OCISodaSaveAndGetWithOpts()
はOCISodaSaveAndGet()
に似ていますが、OCISodaOperationOptions
ハンドルのオプションに従ってドキュメントを保存します。特に、これを使用して、SODAの基礎となるSQLコードに監視ヒントを渡すことができます。操作オプション・ハンドルに属性
OCI_ATTR_SODA_HINT
を設定して、SQLヒント構文のテキスト(つまり、SQLコメント構文/*+
...*/
で囲まれていないヒント・テキスト)を指定できます。ヒントMONITOR
(監視をオンにする)またはNO_MONITOR
(監視をオフにする)のみを使用します。(これを使用してSQLヒントを渡すことができますが、
MONITOR
とNO_MONITOR
はSODAに有用なヒントであり、適切でないヒントによってオプティマイザが最適でない問合せプランを生成する可能性があります。)
関連項目:
-
データベース操作の監視の詳細は、Oracle Database SQLチューニング・ガイドのデータベース操作の監視を参照
-
SQLヒント
MONITOR
およびNO_MONITOR
の構文と動作の詳細は、Oracle Database SQLチューニング・ガイドのMONITORおよびNO_MONITORヒントを参照
例3-12 SODA for Cを使用したコレクションへのドキュメントの保存
この例では、クライアントで割り当てられたキーを持つドキュメントを作成し、OCI関数OCISodaSaveAndGet()
を使用して、ハンドルcollhp
を持つコレクションにドキュメントを保存します。これにより、ドキュメントが挿入されてから取得されます。例では次に、ドキュメント・コンポーネントの一部を出力します。
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". dochp is the document handle.
rc = OCISodaDocCreateWithKey(envhp,
documentContent,
(ub4) strlen(documentContent),
key,
(ub4) strlen(key),
docFlags,
&dochp,
errhp,
OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;
// Save value of document pointer returned by OCISodaDocCreateWithKey()
// as origDochp, in order to free it later.
origDochp = dochp;
// Save the document to a collection (handle collhp).
// OCISodaSaveAndGet() returns the result document as dochp.
// This example assumes the collection uses client-assigned keys.
rc = OCISodaSaveAndGet(svchp,
collhp,
&dochp,
errhp,
OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;
// Print some components of the inserted document.
// (For brevity we omit checking for return value OCI_SUCCESS.)
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);
親トピック: SODA for Cの使用
3.10 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番目の関数によってオーバーライドされます。
関連項目:
- 操作オプション・ハンドルで設定可能なSODA属性の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
- OCI関数
OCISodaOperKeySet()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
親トピック: SODA for Cの使用
3.11 SODA for Cを使用したコレクションでのドキュメントの検索
コレクション内のドキュメントを検索するには、OCISodaFind()
関数を使用し、特定の検索操作を指定する操作オプション・ハンドルを渡します。特定のキーを持つ一意のドキュメントを検索するには、操作オプション・ハンドルを必要としないOCIの簡易関数OCISodaFindOneWithKey()
を使用することもできます。
関連項目:
-
OCI関数
OCISodaFind()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaFindOneWithKey()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例3-13 コレクション内のすべてのドキュメントの検索
この例は、コレクション内の各ドキュメントを含む問合せ結果リストのカーソルを最初に取得します。次に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-14 ドキュメント・キーを付与した一意のドキュメントの検索
この例では、指定した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 key of document we want to find, on 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-15 ドキュメント・キーを指定した複数のドキュメントの検索
この例では、キーを使用して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.
//
// Use function OCISodaOperKeysSet(). (You cannot set keys
// and their lengths using standard function OCIAttrSet().)
rc = OCISodaOperKeysSet(opthp,
keys,
keyLengths,
3,
errhp,
OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;
// Find documents 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-16 フィルタ仕様によるドキュメントの検索
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 (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 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-17 フィルタ指定およびページ区切りを使用したドキュメントの検索
この例では、ページ区切り問合せでOCISodaFind()
関数を使用しています。これは、OCI_ATTR_SODA_FILTER
属性(QBEとして)、OCI_ATTR_SODA_SKIP
属性(スキップするドキュメントの数)およびOCI_ATTR_SODA_LIMIT
属性(返されるドキュメントの最大数)を指定する操作オプション・ハンドルを渡します。この例は、ページ区切り(スキップおよび限定)を指定することを除き、例3-16と同じです。
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 (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 the filter set in the
// 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-18 特定バージョンのドキュメントの検索
この例では、検索するドキュメントのバージョンおよびキーを指定する操作オプション・ハンドルとともに、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-19 見つかったドキュメントの数のカウント
この例では、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 (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-20 全文検索によるSODA for Cを使用した異機種間コレクション内のドキュメントの検索
この例では、QBE演算子$textContains
を使用して、メディア・タイプ列を持つ異機種間コレクションの全文検索を実行します。たとえば、Microsoft Word、Portable Document Format (PDF)およびプレーン・テキスト・ドキュメントはすべて、$textContains
を使用して検索できます。
(JSONドキュメントのコレクションの全文検索を実行するには、$textContains
ではなくQBE演算子$contains
を使用します。)
この例の検索パターンはRogers
です。これは、コレクションcollhp
のドキュメント内の任意の場所のリテラル・テキストを検索することを意味します。
OCISodaDocCursor *cursor = NULL;
OCISodaOperationOptions *opthp = NULL;
oratext *filter;
// 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 QBE filter attribute on the operation handle
filter = (oratext *) "{ \"$textContains\" : \"Rogers\" }";
rc = OCIAttrSet(opthp, OCI_HTYPE_SODA_OPER_OPTIONS, filter, (ub4) strlen(filter),
OCI_ATTR_SODA_FILTER, errhp);
if (rc != OCI_SUCCESS) goto finally;
// Get document cursor using operation options handle
rc = OCISodaFind(svchp, collhp, opthp, OCI_DEFAULY, &cursor,
errhp, OCI_SODA_ATOMIC_COMMIT);
if (rc != OCI_SUCCESS) goto finally;
finally:
// Free all handles.
if (cursor)
(void) OCIHandleFree((dvoid *) cursorhp, OCI_HTYPE_SODA_DOC_CURSOR);
if (opthp)
(void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
$textContains
の検索パターン値の構文は、SQL関数contains
と同じであり、その結果の動作は同じです。たとえば、これは、他のテキスト付近にあるテキストを問い合せたり、問合せであいまいパターン一致を使用できるということです。(検索パターン引数に、Oracle Textの検索で予約されている文字または単語が含まれる場合は、その文字または単語をエスケープする必要があります。)
演算子$textContains
を使用してコレクションを検索するには、SQLを使用してコレクションのコンテンツ列にOracle Text検索索引を定義しておく必要があります。次のSQLコードによってそれが行われます。コレクションmyTextCollection
のコンテンツ列myContentColumn
に索引mySearchIndex
が作成されます。
CREATE SEARCH INDEX mySearchIndex ON
myTextCollection(myContentColumn)
関連トピック
親トピック: SODA for Cの使用
3.12 SODA検索操作のプリフェッチ・サイズの設定
OCISodaFind()
関数のコールでは、OCISodaDocGetNext()
で必要なクライアント・データベースのラウンドトリップ回数を減らすために、複数のドキュメントがプリフェッチされます。操作ハンドルでOCI_ATTR_SODA_FETCH_ARRAY_SIZE
属性を設定することによって、プリフェッチ・バッチに使用するドキュメント数を変更できます。
OCI_HTYPE_SODA_OPER_OPTIONS
属性のデフォルト値は100です。つまり、OCISodaDocGetNext()
のコールで、内部プリフェッチ・バッファに100個のドキュメントが保持されるまで、ラウンドトリップは行われません。この属性の値が大きいほど、ラウンドトリップの回数が少なくなります。
例3-21プリフェッチ配列サイズの設定
この例では、各ラウンドトリップで最大125のドキュメントをフェッチできるように、プリフェッチ配列サイズを125に設定します。
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;
ub4 pfchsz;
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 array prefetch size to 125, overriding the default value of 100.
pfchsz = 125;
OCIAttrSet(opthp, OCI_HTYPE_SODA_OPER_OPTIONS, &pfchsz, 0,
OCI_ATTR_SODA_FETCH_ARRAY_SIZE, errhp)
// Find all documents in the collection.
//
// 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 the components of the 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);
親トピック: SODA for Cの使用
3.13 SODA for Cを使用したコレクション内のドキュメントの置換
コレクション内のドキュメントを置換するには、OCISodaReplOneAndGet()
関数を使用し、置換するドキュメントのキーと新しい代替ドキュメントを指定する操作オプション・ハンドルを渡します。結果ドキュメントとしてその代替ドキュメントが返されます(メタデータがすべて入力された状態)。
OCISodaReplOne()
関数は、結果ドキュメントが完全なメタデータとともに返されないことを除き、OCISodaReplOneAndGet()
と同じです。
これらは最も汎用的なドキュメント置換関数です。より固有のユースケースのためには他の簡易関数もあります。
ドキュメントのコンテンツのみを置換する場合は、これらの簡易関数を使用できます。代替ドキュメントを渡すかわりに、新しい(JSON)コンテンツのみをテキスト引数として渡します。
-
OCISodaReplOneAndGetWithCtnt()
-
OCISodaReplOneWithCtnt()
ドキュメントのキーのみを指定する場合は、これらの簡易関数を使用できます。操作オプション・ハンドルを渡すかわりに、代替ドキュメントと置換するドキュメントのキーのみを渡します。つまり、フィルタ、ドキュメント・バージョンなどは指定できません。
-
OCISodaReplOneAndGetWithKey()
-
OCISodaReplOneWithKey()
名前にAndGet
が含まれている関数は、入力ドキュメントに使用されたパラメータと同じパラメータの値として新しい(結果)ドキュメントを返すため、そのコンポーネントを取得できます。
どちらの置換関数を使用した場合も、置換操作が成功したかどうかを示すブール値が出力パラメータisReplaced
として返されます。
ドキュメントの取得時に操作オプション・ハンドルのロック属性をTRUE
に設定することで、ペシミスティック・ロックを使用してドキュメントを更新できます。これを例3-24に示します。
関連項目:
-
OCI関数
OCISodaReplOne()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaReplOneAndGet()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaReplOneWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaReplOneAndGetWithCtnt()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaReplOneWithKey()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaReplOneAndGetWithKey()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例3-22 SODA For Cを使用した、キーが指定された場合のドキュメントの置換および結果ドキュメントの取得
この例では、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-23 SODA for Cを使用した特定バージョンのドキュメントの置換
ドキュメントを置き換える場合にオプティミスティック・ロックを実装するには、この例のようにキーおよびバージョンの両方を指定できます。
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-24 SODA for Cを使用した更新(置換)用のドキュメントのロック
この例は例3-22に似ていますが、永続ロックを使用しています。置換操作が終了するまでドキュメントがロックされます。操作オプション・ハンドルのロック属性をTRUE
に設定して、ドキュメントのロックを取得します。
OCISodaDoc *dochp = NULL;
OCISodaDoc *tempDochp = NULL;
OCISodaDoc *foundDochp = NULL;
char documentContent[30] = "{\"name\":\"LiLing\"}";
ub4 docFlags = OCI_DEFAULT;
boolean doLock;
boolean isReplaced = FALSE;
OCISodaOperationOptions *opthp;
OraText *inKey = "3C03C00FA3904FC2BF5182C424A2C6C1";
// 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 lock attribute to TRUE on the operation-options handle to obtain
// the document with lock.
doLock = TRUE;
rc = OCIAttrSet(opthp, OCI_HTYPE_SODA_OPER_OPTIONS, &doLock, 0,
OCI_ATTR_SODA_LOCK, errhp);
if (rc != OCI_SUCCESS) goto finally;
// Find the document with the key, by way of the operation-options handle
// that has key and lock attributes set.
// 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;
// The document is now locked for update - other users cannot update it
// until it is released.
// Create a temporary replacement document, with 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;
}
// OCISodaReplOneAndGet returns the result document as dochp, so
// before calling it we save a pointer, tempDochp, to the handle that
// was returned by OCISodaDocCreate.
tempDochp = dochp;
// Replace the document that has the key set in the operation-options
// handle with the replacement document, dochp, and get back 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");
// OCI_SODA_ATOMIC_COMMIT commits the transaction, thereby releasing the lock
// obtained on the document.
finally:
// Free all handles.
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);
if (foundDochp)
(void) OCIHandleFree((dvoid *) foundDochp, OCI_HTYPE_SODA_DOCUMENT);
3.14 SODA for Cを使用したコレクションからのドキュメントの削除
関数OCISodaRemove()
およびOCISodaRemoveOneWithKey()
を使用して、コレクションからドキュメントを削除できます。
1つ以上のドキュメントを削除するには、OCISodaRemove()
関数を使用し、操作オプション・ハンドルを渡します。キーで指定した1つのドキュメントを削除する場合は、簡易関数OCISodaRemoveOneWithKey()
を使用することもできます。操作オプション・ハンドルは必要ありません。キーを直接渡します。
どちらのドキュメント削除関数を使用した場合も、削除されたドキュメントの数がOUTパラメータとして返されます。
関連項目:
-
OCI関数
OCISodaRemove()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCISodaRemoveOneWithKey()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
例3-25 ドキュメント・キーによるコレクションからのドキュメントの削除
この例では、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-26 特定バージョンのドキュメントの削除
この例では、削除するドキュメントのバージョンおよびキーを指定する操作オプション・ハンドルとともに、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-27 ドキュメント・キーによるコレクションからのドキュメントの削除
この例では、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-28 フィルタによるコレクションからの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.15 SODA for Cを使用したコレクションの切捨て(すべてのドキュメントの削除)
コレクションは空にすることも、切り捨てることもできます。つまり、関数OCISodaCollTruncate()
を使用して、そのすべてのドキュメントを削除できます。
この関数は、成功するとOCI_SUCCESS
を返します。
例3-29 コレクションの切捨て(すべてのドキュメントの削除)
OCISvcCtx *svchp;
OCIError *errhp;
OCISodaColl *collhp;
sword rc;
rc = OCISodaCollTruncate(svchp,
collhp,
errhp,
OCI_SODA_ATOMIC_COMMIT);
if (rc == OCI_SUCCESS)
printf("Successfully truncated the collection.\n");
親トピック: SODA for Cの使用
3.16 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()
関数を使用し、索引名を渡します。
関数OCISodaIndexGet()
またはOCISodaIndexList()
をそれぞれ使用して、コレクションの1つの索引指定またはすべての索引指定を取得できます。
関数OCISodaIndexGet()
では、索引、およびオプションで関連するデータベース・スキーマ名を引数として指定します。(スキーマおよび索引名に使用される値は、データ・ディクショナリ内の識別子です。特に、大文字と小文字が同じである必要があるため、二重引用符を使用せずにSQLで作成した場合は大文字にする必要があります。)
関連項目:
-
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaIndexCreate()を参照
-
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaIndexDrop()を参照
-
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaIndexGet()を参照
-
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaIndexList()を参照
-
Oracle Database Simple Oracle Document Access (SODA)の概要のSODA索引付けの概要を参照
-
Oracle Database Simple Oracle Document Access (SODA)の概要のSODA索引仕様(参考)を参照
-
Oracle Database JSON開発者ガイドのJSON検索索引: 非定型の問合せおよび全文検索を参照
-
Oracle Database JSON開発者ガイドの永続的なデータ・ガイド情報: JSON検索索引の一部を参照
-
Oracle Database JSON開発者ガイドのGeoJSON地理データの使用を参照
例3-30 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-31 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-32 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-33 SODA for Cを使用した索引仕様の取得
この例では、関数OCISodaIndexGet()
を使用して、SODAコレクションcollhp
のドキュメントについて、現在接続されているデータベース・スキーマで索引idx
の定義に使用される仕様を取得します。
static void printIndex(OCISvcCtx *svchp, OCIEnv *envhp, OCISodaColl *collhp,
oratext *idx, ub4 idxlen, ub4 flags, OCIError *err
{
OCIString *spec = NULL;
sword rc;
printf("Describing index: %.*s\n", idxlen, idx);
rc = OCISodaIndexGet(svchp, collhp, idx, idxlen, NULL, 0,
flags, &spec, errhp, mode);
if (rc != OCI_SUCCESS) return;
if (spec)
{
oratext *str = OCIStringPtr(envhp, spec);
ub4 slen = OCIStringSize(envhp, spec);
printf("Index specification: %.*s\n", slen, str);
}
}
例3-34 SODA for Cを使用したコレクションのすべての索引仕様の取得
この例では、関数OCISodaIndexList()
を使用して、変数specs
で、コレクションcollhp
のドキュメントに定義されているすべての索引仕様を取得します。次に、その数(関数OCICollSize()
を使用して取得)とともに出力します。
static
void printIndexes(OCISvcCtx *svchp, OCIEnv *envhp, OCISodaColl *collhp,
ub4 flags, OCIError *errhp, ub4 mode)
{
OCIColl *specs = NULL;
sb4 ndocs;
sword rc;
printf("Listing indexes\n");
rc = OCISodaIndexList(svchp, collhp, OCI_SODA_AS_AL32UTF8, &specs, errhp, 0);
if (rc != OCI_SUCCESS) return;
rc = OCICollSize(envhp, errhp, specs, &ndocs);
if (rc != OCI_SUCCESS) return;
printf("No. of indexes: %d\n", ndocs);
for (int i = 0 ; i < ndocs ; i++)
{
void *specstr;
boolean exists = FALSE;
rc = OCICollGetElem(envhp, errhp, (const OCIColl *)specs, i, &exists,
(void **) &specstr, (void **) NULL);
if (rc != OCI_SUCCESS) return;
if (exists)
{
OCIString *item = *(OCIString **)specstr;
oratext *spec = NULL;
ub4 specLen = 0;
spec = OCIStringPtr(envhp, item);
specLen = OCIStringSize(envhp, item);
printf("Index %d:\n%.*s\n", i, specLen, spec);
}
}
}
親トピック: SODA for Cの使用
3.17 SODA for Cを使用したコレクションのデータ・ガイドの取得
コレクションのデータ・ガイドを取得するには、OCISodaDataGuideGet()
またはOCISodaDataGuideGetWithOpts()
関数を使用します。データ・ガイドは、コレクション内のJSONドキュメントの構造およびタイプ情報をまとめたJSONドキュメントです。これらの文書内で使用されているフィールドに関するメタデータを記録します。
ノート:
JSONデータ・ガイドに対するSODA for Cのサポートは、Oracle Database 18.3で追加されました。このSODA機能を使用するには、そのデータベース・リリース以降が必要となります。
コレクションのデータ・ガイドを作成するには、次の2つの方法があります。
-
関数
OCISodaDataGuideGetWithOpts()
を、操作オプション・ハンドル属性OCI_ATTR_SODA_SAMPLE_PCT
または例による問合せ(QBE)フィルタリング操作とともに使用します。これにより、問合せによって選択されたドキュメントのみのデータ・ガイドが最初から動的に作成されます。このように、データ・ガイドのベースとなるドキュメントのセットを制限できます。例3-35に、これを示します。(この方法は、SQL関数
json_dataguide
の使用に対応しています。) -
関数
OCISodaDataGuideGet()
を使用します。これにより常に、コレクション内のすべてのドキュメントに基づいてデータ・ガイドが作成されます。例3-36に、これを示します。この方法では、JSON検索索引の一部として格納されている永続データ・ガイド情報を使用するため、この方法を使用する前に、まずコレクションにデータ・ガイド対応のJSON検索索引を作成する必要があります。この方法を例3-31に示します。索引内のデータ・ガイド情報は永続的であり、新しいJSONコンテンツが追加されると自動的に更新されます。
(この方法は、PL/SQL関数
get_index_dataguide
の使用に対応しています。)
索引ベースの関数OCISodaDataGuideGet()
では、索引更新を伴うドキュメント書込み(作成および更新)など、関連データの更新にかかる継続的なコストが永続的に発生します。ただし、データ・ガイド情報は索引ですぐに使用できるため、データ・ガイド・ドキュメントを生成するときに最初から収集する必要はありません。
関数OCISodaDataGuideGetWithOpts()
は毎回最初から開始されるため、これを一般的に使用するのは、メソッドをドキュメントのランダム・サンプルにのみ適用したり、一部のフィルタ(QBE)を満たすドキュメントにのみ適用する場合などです。例3-35に、ドキュメントのランダム・サンプルの使用を示します。
例3-35 SODA for Cを使用したデータ・ガイドの動的な作成
この例では、関数OCISodaDataGuideGetWithOpts()
を、操作オプション・ハンドル属性OCI_ATTR_SODA_SAMPLE_PCT
脚注2とともに使用して、コレクションcollhp
内のドキュメントのランダム・サンプルのデータ・ガイドを取得します。特定のドキュメントがサンプルに含まれる確率は40%です(引数値40
)。
この例では、フラット形式でデータ・ガイド・ドキュメントの内容をプリティプリントします。最後に、データ・ガイド・ドキュメントに使用されている一時LOBが解放されます。
属性OCI_ATTR_SODA_SAMPLE_PCT
は、読取り操作にのみ使用します。これは書込み操作では無視されます。動的データ・ガイドの作成は、OCI_ATTR_SODA_SAMPLE_PCT
の一般的なユースケースです。これを使用してカーソルを取得することもできます。
ランダム・サンプルを使用する以外に、動的に作成されたデータ・ガイドによって表されるドキュメントを制限するもう1つの一般的な方法は、OCI_ATTR_SODA_SAMPLE_PCT
のかわりに例による問合せ(QBE)フィルタリング操作を使用することです。
OCISodaDoc *dgdochp = NULL;
OCISodaOperationOptions *opthp = NULL;
oratext *content;
ub4 contentLen;
double sample_pct = 40.0;
rc = OCIHandleAlloc((void *) envhp, (void **)&opt,
OCI_HTYPE_SODA_OPER_OPTIONS, (size_t) 0,
(dvoid **) 0
if (rc != OCI_SUCCESS) goto finally;
// Set the sample size (40%) on the operation-options handle.
rc = OCIAttrSet(opr, OCI_HTYPE_SODA_OPER_OPTIONS, &sample_pct, 0,
OCI_ATTR_SODA_SAMPLE_PCT, errhp)
if (rc != OCI_SUCCESS) goto finally;
// Create a data guide dynamically, from scratch.
// dgdochp is the handle for the data-guide document.
rc = OCISodaDataGuideGetWithOpts(svchp, collhp, opthp,
OCI_SODA_DG_FMT_HIERARCHICAL,
OCI_SODA_DATAGUIDE_PRETTY,
OCI_SODA_AS_AL32UTF8,
&dgdochp, errhp, OCI_DEFAULT));
if (rc != OCI_SUCCESS) goto finally;
rc = OCIAttrGet((dvoid *)dgdochp, OCI_HTYPE_SODA_DOCUMENT,
(dvoid *)&content, &contentLen,
OCI_ATTR_SODA_CONTENT, errhp)
if (rc != OCI_SUCCESS) goto finally;
printf("Dataguide: %.*s\n", contentLen, content);
finally:
// Free all handles.
if (dgdochp)
(void) OCIHandleFree((dvoid *) dgdochp, OCI_HTYPE_SODA_DOCUMENT);
if (opthp)
(void) OCIHandleFree((dvoid *) opthp, OCI_HTYPE_SODA_OPER_OPTIONS);
関連項目:
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaDataGuideGetWithOpts()を参照
例3-36 SODA for Cを使用したJSON検索索引によるデータ・ガイドの作成
この例では、OCISodaDataGuideGet()
関数を使用して、コレクション・ハンドルcollhp
を持つコレクションのデータ・ガイドを取得します。その後、データガイド・ドキュメントのコンテンツを出力します。
OCISodaDoc *dgdochp = NULL;
OraText *content = NULL;
ub4 contentLen = 0;
// Create a data guide based on a JSON search index defined on the
// collection. dgdochp is the handle for the data-guide document.
rc = OCISodaDataGuideGet(svchp,
collhp,
OCI_DEFAULT,
&dgdochp,
errhp,
OCI_DEFAULT);
if (rc != OCI_SUCCESS) goto finally;
rc = OCIAttrGet((dvoid *) dgdochp,
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 (dgdochp)
(void) OCIHandleFree((dvoid *) dgdochp, OCI_HTYPE_SODA_OPER_OPTIONS);
関連項目:
Oracle Call Interfaceプログラマーズ・ガイドのOCISodaDataGuideGet()を参照
親トピック: SODA for Cの使用
3.18 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
文の構成とは異なります。
関連トピック
関連項目:
-
実行モード・パラメータ
OCI_SODA_ATOMIC_COMMIT
の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照 -
トランザクションのOracle Call Interface (OCI)のサポートの詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
-
OCI関数
OCITransCommit()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照 -
OCI関数
OCITransRollback()
の詳細は、Oracle Call Interfaceプログラマーズ・ガイドを参照
親トピック: SODA for Cの使用
脚注の凡例
脚注1: ハンドルの使用が完了したときに解放するためのリマインダとして、ハンドルはここですぐに解放されます(他のハンドルと同じです)。実際には、ハンドルを解放する前になんらかの方法でハンドルを使用します。脚注2: ここでの構文は、SQL SELECT文のsample_clauseの構文に対応します。