更新レコードの配列の存在、および各レコードが示す処理のタイプが確認されたため、この項では、返される行データを確認します。
ttXlaNextUpdateまたはttXlaNextUpdateWait関数によって返される各レコードは、処理が実行された表について記述するttXlaUpdateDesc_tヘッダーで始まります。このヘッダーには、レコードがトランザクションの最初のレコードか最後の(コミット・)レコードか、レコードが示す処理のタイプ、返された行データの長さ(該当する行データがある場合)、行内の更新された列(該当する列がある場合)などの情報が記述されます。図3.7に、トランザクション・ログ内の更新レコードの例を示します。
ttXlaUpdateDesc_tヘッダーは固定長で、処理のタイプに応じて、データ・ストアから0(ゼロ)から2行の行(タプル)が続きます。ttXlaUpdateDesc_tのアドレスを取得し、それにsizeof ttXlaUpdateDesc_tを追加することによって、最初に返された行のアドレスを検出できます。
tup1 = (void*) ((char*) ttXlaUpdateDesc_t +
sizeof(ttXlaUpdateDesc_t));
ttXlaUpdateDesc_t →typeフィールドは、更新を生成したSQL処理についての記述です。UPDATETTUP型のトランザクション・レコードは、UPDATE処理についての記述であるため、更新の前後の行データをレポートするために2行の行を返します。afterという値が含まれている2番目に返された行のアドレスは、レコード内の1つ目の行のアドレスをその長さに追加すると検出できます。
if (ttXlaUpdateDesc_t->type == UPDATETUP) {
tup2 = (void*) ((char*) tup1 + ttXlaUpdateDesc_t->tuple1);
}
この例では、ttXlaNextUpdateWait 関数によって返された各レコードをHandleChange 関数に渡します。この関数は、レコードがINSERT、UPDATEまたはCREATE VIEWのいずれの処理と関連しているかを判別します。この例では、わかりやすくするために、その他の処理はすべて無視されています。
HandleChange関数は、PrintColValues関数(例3.16を参照)をコールする前に各タイプのSQL処理を異なる方法で処理します。
void HandleChange(ttXlaUpdateDesc_t* xlaP)
{
void * tup1;
void * tup2;
tup1 = (void*) ((char*) xlaP + sizeof(ttXlaUpdateDesc_t));
switch(xlaP->type) {
case INSERTTUP: /* Handle INSERT operations */
printf("Inserted new row:\n");
PrintColValues(tup1);
break;
case UPDATETUP: /* Handle UPDATE operations */
tup2 = (void*) ((char*) tup1 + xlaP->tuple1);
printf("Updated row:\n");
PrintColValues(tup1);
printf("To:\n");
PrintColValues(tup2);
break;
case DELETETUP: /* Handle DELETE operations */
printf("Deleted row:\n");
PrintColValues(tup1);
break;
default: /* Ignore all other operations */
break;
}
}