PSQL Programmer's Guide (v11)

レコードへのアクセス (トランザクショナル インターフェイス)

Btrieve は、データへの物理アクセスと論理アクセスの両方を行います。物理アクセスでは、Btrieve はファイル内の物理レコード アドレスに基づいてレコードを取得します。論理アクセスでは、Btrieve はレコードに含まれているキー値に基づいてレコードを取得します。また、Btrieve ではレコード内のデータの「チャンク」にアクセスできます。

物理位置によるレコードへのアクセス

物理位置によるレコード アクセスは、以下の理由で高速になります。

物理カレンシー

物理カレンシーは、物理位置でレコードにアクセスする際のポジショニングに影響を与えます。レコードを挿入する場合、レコードに含まれているキー値とは無関係に、MicroKernel はファイル内の最初の空きスペースにそのレコードを書き込みます。この場所はレコードの物理位置、つまり、アドレスと呼びます。レコードは、ファイルから削除するまでこの位置に残ります。Btrieve Step オペレーションは、物理位置を使用してレコードにアクセスします。

最後にアクセスされたレコードが、現在の物理レコードです。次の物理レコードは、現在の物理レコードに対してすぐ上位のアドレスを持つレコードです。直前の物理レコードは、すぐ下位のアドレスを持つレコードです。最初の物理レコードの直前の物理レコードはありません。同様に、最後の物理レコードの次の物理レコードはありません。

まとめると、現在の物理位置、次の物理位置、直前の物理位置がファイル内の物理カレンシーを構成します。

Step オペレーション

アプリケーションは、Step オペレーションを使用して、ファイル内の物理位置に基づいてレコードにアクセスできます。たとえば、Step First オペレーション(33)は、ファイル内の最初、つまり、最下位の物理位置に格納されているレコードを取得します。


メモ

キーオンリー ファイルでは Step オペレーションを実行できません。


Step Next オペレーション(24)は、次に上位の物理位置に格納されているレコードを取得します。Step Previous オペレーション(35)は、ファイル内の次に下位の物理位置に格納されているレコードを取得します。Step Last オペレーション(34)は、ファイル内の最後、つまり、最上位の物理位置に格納されているレコードを取得します。

Step Next Extended(38)オペレーションと Step Previous Extended(39)オペレーションは、現在のレコードの後または前の物理位置から 1 つまたは複数のレコードを取得します。


メモ

各 Step オペレーションは物理カレンシーを再確立しますが、論理カレンシーについては、先に存在していたとしても破壊します。


キー値によるレコードへのアクセス

キー値でレコードにアクセスすると、指定されたキーに対するレコードの値に基づいてレコードを取得できます。

論理カレンシー

論理カレンシーは、キー値でレコードにアクセスする際のポジショニングに影響を与えます。ファイルにレコードを挿入すると、MicroKernel はレコード内の対応するキーに非ヌル値が存在する各 B ツリーを更新します。ファイルの各キーは、レコードの論理順序を決定します。この順序は、キーの定義済みのソート順序または ACS で決定されます。

最後にアクセスされたレコードが、現在の論理レコードです。このレコードは、必ずしも、最後に取得されたレコードではありません。最後のレコードは Get Direct/Chunk オペレーション(23)で取得されている可能性があり、このオペレーションは論理カレンシーを変更しません。次の論理レコードは、定められた論理順序ですぐ次にあるレコードです。直前の論理レコードは、定められた論理順序ですぐ直前にあるレコードです。最初の論理レコードの直前の論理レコードはありません。同様に、最後の論理レコードの次の論理レコードはありません。

まとめると、現在の論理レコード、次の論理レコード、直前の論理レコードがファイル内の論理カレンシーを構成します。

no-currency-change(NCC)オプションを使用するオペレーションを実行する場合や、ヌル キー値を持つレコードを処理する場合を除き、現在の論理レコードは現在の物理レコードでもあります。たとえば、NCC Insert オペレーション(2)を実行し、挿入以前にあったものと同じ論理位置をファイル内に持つことができます。物理カレンシーが更新されます。

NCC オペレーションは、別のオペレーションを実行するために論理カレンシーを保存しなければならない場合に有効です。たとえば、レコードの挿入または更新を行い、オリジナルの論理カレンシーに基づいて Get Next オペレーション(6)を使用しなければならない場合があります。

NCC Insert オペレーション

status = BTRV( B_GET_FIRST, posBlock, dataBuf, 
&dataLen, keyBuf, keyNum); /* キー パスの最初のレコード
を取得 */ 
 
for (i = 0; i < numRecords; i++) 
{ status = BTRV( B_INSERT, posBlock, dataBuf, 
&dataLen, keyBuf, -1); /* キー番号 -1 はカレンシー変更な
しを示す */ 
} /* 複数レコードを挿入 */ 
 
status = BTRV( B_GET_FIRST, posBlock, dataBuf, 
&dataLen, keyBuf, keyNum); /* キー パスの最初のレコード
の次のレコードを取得 */ 


メモ

NCC オペレーションを使用する場合、MicroKernel はキー バッファー パラメーターに情報を返しません。論理カレンシーを保持する場合、NCC オペレーションの後にキー バッファー内の値を変更しないでください。それ以外は、次の Get オペレーションで予測できない結果が発生するおそれがあります。


Get オペレーション

アプリケーションは、Get オペレーションを使用して、指定されたキーの値に基づいてレコードを取得できます。対応する Get オペレーションは、ファイルから特定のレコードを取得したり、ある順序でレコードを取得できます。

たとえば、Get First オペレーション(12)はキー番号パラメーターで指定されたキーで最初のレコードを取得します。同様に、Get Last オペレーション(13)は、指定されたキーに基づいて論理順序に従って最後のレコードを取得します。Get Equal(5)や Get Less Than(10)などの Get オペレーションの中には、アプリケーションがキー バッファー パラメーターで指定するキー値に基づいてレコードを返すものがあります。

Get オペレーションは論理カレンシーを確立します。アプリケーションは、以下の手順を実行することによってあるキーから別のキーへ変更できます。

  1. Get オペレーションのうちの 1 つを発行することによってレコードを取得します。
  2. レコードの 4 バイト物理アドレスを取得するために、Get Position オペレーション(22)を発行します。
  3. Get Direct/Record オペレーション(23)を発行し、4 バイトの物理アドレスと変更するキー番号を MicroKernel に渡します。

Get Position(22)以外の Get オペレーションは、論理カレンシーを確立するほか、物理カレンシーも確立します。したがって、Step Next(24)オペレーションまたは Step Previous(35)オペレーションを続けることができます。ただし、Step オペレーションを使用すると論理カレンシーが破壊されます。

Step オペレーションを使用した後に論理カレンシーを再確立するには、以下の手順で行います。

  1. Step オペレーションを使用した直後に、Get Position オペレーション(22)を発行して取得されたレコードの 4 バイトの物理アドレスを取得します。
  2. Get Direct/Record オペレーション(23)を発行し、4 バイトの位置と論理カレンシーを確立するキー番号を MicroKernel に渡します。

可変長レコードの読み取り

可変長の読み取りは、データ バッファー長パラメーターを使用してレコードを返すためのスペース量を MicroKernel に指示するという点で、固定長レコードの読み取りと同じです。このパラメーターをデータ バッファーのサイズに設定すれば、データ バッファーは最大のデータ量を収容できます。


メモ

データ バッファー長を、データ バッファーに割り当てられたバイト数より大きい値に設定しないでください。設定すると、アプリケーションの実行時にメモリが上書きされるおそれがあります。


読み取りオペレーションが成功した後、返されたレコードのサイズ、つまり固定長部分のサイズに可変長部分の実際のデータ量を足したサイズ(レコードの最大サイズではない)を反映して、データ バッファー長パラメータは変更されます。アプリケーションはこの値を使用して、データ バッファー内のデータ量を決定する必要があります。

たとえば、データ ファイル内に以下のレコードがあるとしましょう。

キー 0:Owner
30 バイト ZSTRING
キー 1:Account
8 バイト INTEGER
Balance
(キーではない)
8 バイト
Comments
(キーではない)
1000 バイト
John Q. Smith
263512477
1024.38
解説
Matthew Wilson
815728990
644.29
解説
Eleanor Public
234817031
3259.78
解説

以下に、Get Equal オペレーションの例を示します。


メモ

アプリケーションの開発とデバッグを行う間、このオペレーションは読み取りオペレーションの直前と直後にデータ バッファー長を表示して、それが各時点で正しく設定されているかどうかを確認するのに役立ちます。


C での Get Equal オペレーション

/* B_GET_EQUAL を使用して key 1 = 263512477 のレコードを
取得 */ 
memset(&dataBuf, 0, sizeof(dataBuf)); 
dataBufLen = sizeof(dataBuf); /* この値は 1047 */ 
account = 263512477; 
*(BTI_LONG BTI_FAR *)&keyBuf[0] = account; 
status = BTRV( B_GET_EQUAL, posBlock, &dataBuf, 
&dataBufLen, keyBuf, 1); 
/* dataBufLen は現在 56 */ 

Visual Basic での Get Equal オペレーション

dataBufLen= length(dataBuf) ' この値は 1047  
account% = 263512477 
status = BTRV(B_GETEQUAL, PosBlock$, dataBuf, 
dataBufLen, account%, 1) 
' dataBufLen は現在 56 

返されたレコードがデータ バッファー長で指定された値より長いと、MicroKernel はデータ バッファー長で設定されたサイズに従ってできるだけ多くのデータを返し、ステータス コード 22 を返します。

チャンクによるレコードへのアクセス

Btrieve のデータ バッファー長パラメーターは 16 ビットの符号なし整数であるため、レコード長を 65,535 に制限します。Chunk オペレーションは、レコードの部分の読み取りまたは書き込みを行えるようにして、この制限をはるかに超えてレコード長を拡張します。チャンクは、オフセットと長さとして定義されます。オフセットは 64 GB までの大きさにすることができますが、長さは 65,535 バイトに制限されます。オペレーティング システムおよびデータ バッファー長パラメーターの制限は、Chunk オペレーションにも適用されます。ただし、Chunk オペレーションはレコードのどの部分にもアクセスできるので、この制限はレコード長に影響を与えず、1 つのオペレーションでアクセスできるチャンクの最大サイズにのみ影響を与えます。

たとえば、Chunk オペレーションで、アプリケーションは 3 つのチャンク取得呼び出しを行うことによって 150,000 バイト レコードを読み取ることができます。この例の各チャンクの長さは、50,000 バイトです。最初のチャンクはオフセット 0 から始まり、次のチャンクはオフセット 50,000 から始まり、最後のチャンクはオフセット 100,000 から始まります。

チャンクのオフセットと長さは、キー セグメント、レコードの固定長部分、可変長部などの MicroKernel が認識するレコードの内部構造に対応する必要はありません。また、チャンクは、アプリケーションが定義するフィールドなどのレコードの部分に一致する必要はありません。ただし、定義された部分をチャンクとして更新すると便利な場合があります。


メモ

チャンクは、チャンクを定義しているオペレーションの実行中のみ有効です。


場合によっては、クライアント/サーバー環境で Chunk オペレーションを使用すると、クライアントのリクエスターはより小さなデータ バッファー長を設定してリクエスターのメモリ必要量を少なくすることができます。たとえば、アプリケーションがレコード全体のオペレーションを使用し、最高 50 KB 長のレコードにアクセスした場合、リクエスターはデータ バッファー長を最低でも 50 KB に設定しなければならず、それによって 50 KB の RAM を使用することになります。しかし、たとえば、アプリケーションが Chunk オペレーションを使用し、各チャンクのサイズを 10 KB に制限した場合、リクエスターはデータ バッファー長を 10 KB に設定することができ、それによって 40 KB の RAM が節約されることになります。

レコード内のカレンシー

レコード内のカレンシーが Chunk オペレーションに関連するのは、現在のレコード内のオフセットを追跡するからです。現在位置は、読み取りまたは書き込みが行われたチャンクの最後のバイトを 1 バイト越えたオフセットです。(これに関しては、最後のオペレーションでレコード全体を読み取ろうとし、MicroKernel がそのレコードの一部のみを返した場合でも同じです。レコードの一部のみを返す現象は、データ バッファー長が不十分であるときに発生します。)

例外は、Truncate サブファンクションを使用する Update Chunk オペレーション(53)の場合です。この場合、MicroKernel は切り捨てられたレコードの終わりから 1 バイト先のオフセットを現在位置と定義します。

MicroKernel はレコード内カレンシーを追跡することにより、以下のことが行えます。

Chunk オペレーション

Get Direct/Chunk オペレーション(23)と Update Chunk オペレーション(53)を使用して、チャンクにアクセスします。これらのオペレーションを使用するには、チャンクのオフセットと長さを定義するチャンク記述子構造を定義する必要があります。Get Direct/Chunk オペレーションの場合、チャンク記述子構造は MicroKernel がチャンクを返す先のアドレスも指定する必要があります。

Get Direct/Chunk オペレーションを使用する前に、Get Position オペレーション(22)を発行することによって現在のレコードの物理アドレスを取得する必要があります。1 つの Chunk オペレーションで、ネクストインレコード サブファンクション バイアスを使用してレコード内の複数のチャンクを取得または更新することができます。


オペレーションのシーケンス (トランザクショナル インターフェイス)

レコードの挿入と更新 (トランザクショナル インターフェイス)