|
ここでは、以下の項目について説明します。
Web ダウンロードにより提供される以下のプログラム例では、Btrieve の一般的な操作方法を説明します。これらの操作は、MicroKernel との依存関係で要求される順番(ファイルを開いてから I/O を実行するなど)で行われます。
{********************************************************************* ** ** Copyright 1982-2003 Pervasive Software Inc. All Rights Reserved ** *********************************************************************} {********************************************************************* BTRSAM32.DPR これは、目的の環境で、コンパイラ ツールを使用した Btrieve アプリケーションの コンパイル、リンク、実行が可能なことを確認するための簡単なサンプルです。 このプログラムでは、Btrieve の Delphi インターフェイスを示します。 MS Windows NT/2000 および Windows 9x/ME 上の Delphi 2.0、3.0、4.0 および 5.0 で動作します。 このプログラムでは、サンプル ファイルで以下の操作を行います。 - BTRVID を使用して Microkernel Database エンジンのバージョン情報を取得する - sample.btr を開く - Key 0 の既知の値を持つレコードを取得する - 読み込んだレコードを表示する - Stat オペレーションを実行する - 空の sample.btr のクローンを作成して開く - Get Next Extended オペレーションを実行して sample.btr のレコードのサブセットを抽出する - クローン ファイルにこれらのレコードを挿入する - 両ファイルを閉じる 重要: Btrieve データ ファイルのサンプル sample.btr が保存されているディレクトリは、 フルパスを指定してください。また、それぞれの「重要」項目も参考にしてください。 Delphi 2.0/3.0/4.0/5.0 Btrieve プロジェクトは、 Delphi プロジェクト環境のプルダウン メニューから以下を選択後コンパイルします。 PROJECT OPTIONS... COMPILER CODE GENERATION ALIGNED RECORD FIELDS ( de-select this ) これを行わない場合、レコードが正しく出力されません。 これは、レコードがバイトパックされていないためです。 代わりに、(*A-*) コンパイラ命令を使用するか、下に示すように、 すべてのレコードを「パック」として宣言します。 詳細については、Delphi のマニュアルを参照してください。 PROJECT FILES: - btr32.dpr Borland project file - btr32.dof Borland project file - btrsam32.dfm Borland project file - btrsam32.pas Source code for the simple sample - btrapi32.pas Delphi interface to Btrieve - btrconst.pas Btrieve constants file ****************************************************************************} unit btrsam32; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, BtrConst, BtrAPI32; {********************************************************************* プログラム定数 *********************************************************************} const { プログラム定数 } MY_THREAD_ID = 50; EXIT_WITH_ERROR = 1; VERSION_OFFSET = 0; REVISION_OFFSET = 2; PLATFORM_ID_OFFSET = 4; {******************************************************************** 重要:以下を変更し、使用する sample.btr へのフルパスを指定してください。 ********************************************************************} FILE_1 = 'c:¥samples¥sample.btr'; FILE_2 = 'c:¥samples¥sample2.btr'; {*************************************************************************** バージョン処理用のレコードの型定義 ****************************************************************************} type CLIENT_ID = packed record networkandnode :array[1..12] of char; applicationID :array[1..3] of char; threadID :smallint; end; VERSION_STRUCT = packed record version :smallint; revision :smallint; MKDEId :char; end; {*************************************************************************** sample.btr のレコードの定義 ****************************************************************************} {* writeln() への対応のため、ゼロ基準のキャラクター配列を使用 *} PERSON_STRUCT = packed record ID :longint; FirstName:array[0..15] of char; LastName:array[0..25] of char; Street :array[0..30] of char; City :array[0..30] of char; State:array[0..2] of char; Zip :array[0..10] of char; Country :array[0..20] of char; Phone :array[0..13] of char; end; {*************************************************************************** Stat および Create 処理用のレコードの型定義 ****************************************************************************} FILE_SPECS = packed record recLength :smallint; pageSize :smallint; indexCount :smallint; reserved :array[0..3] of char; flags :smallint; dupPointers :byte; notUsed :byte; allocations :smallint; end; KEY_SPECS = packed record position :smallint; length :smallint; flags :smallint; reserved :array[0..3] of char; keyType :char; nullChar :char; notUsed :array[0..1] of char; manualKeyNumber :byte; acsNumber :byte; end; FILE_CREATE_BUF = packed record fileSpecs :FILE_SPECS; keySpecs :array[0..4] of KEY_SPECS; end; {*************************************************************************** Get Next Extended 処理用のレコードの型定義 ****************************************************************************} GNE_HEADER = packed record descriptionLen :smallint; currencyConst :array[0..1] of char; rejectCount :smallint; numberTerms :smallint; end; TERM_HEADER = packed record fieldType :byte; fieldLen :smallint; fieldOffset :smallint; comparisonCode :byte; connector :byte; value :array[0..2] of char; end; RETRIEVAL_HEADER = packed record maxRecsToRetrieve :smallint; noFieldsToRetrieve :smallint; end; FIELD_RETRIEVAL_HEADER = packed record fieldLen :smallint; fieldOffset :smallint; end; PRE_GNE_BUFFER = packed record gneHeader :GNE_HEADER; term1 :TERM_HEADER; term2 :TERM_HEADER; retrieval :RETRIEVAL_HEADER; recordRet :FIELD_RETRIEVAL_HEADER; end; RETURNED_REC = packed record recLen :smallint; recPos :longint; personRecord :PERSON_STRUCT; end; POST_GNE_BUFFER = packed record numReturned :smallint; recs :packed array[0..19] of RETURNED_REC; end; GNE_BUFFER_PTR = ^GNE_BUFFER; GNE_BUFFER = packed record case byte of 1 : (preBuf :PRE_GNE_BUFFER); 2 : (postBuf :POST_GNE_BUFFER); end; {*************************************************************************** Delphi で作成されたフォームの定義 ****************************************************************************} TForm1 = class(TForm) RunButton:TButton; ExitButton:TButton; ListBox1:TListBox; procedure FormCreate(Sender:TObject); procedure ExitButtonClick(Sender:TObject); procedure RunButtonClick(Sender:TObject); private { Private 宣言 } ArrowCursor, WaitCursor:HCursor; status:smallint; bufferLength:smallint; personRecord :PERSON_STRUCT; recordsRead:longint; procedure RunTest; public { Public 宣言 } end; var Form1:TForm1; {*********************************************************************** ここからプログラム開始 ************************************************************************} implementation {$R *.DFM} {*********************************************************************** プログラム変数 ************************************************************************} var { Btrieve 関数パラメーター } posBlock1 :string[128]; posBlock2 :string[128]; dataBuffer :array[0..255] of char; dataLen :word; keyBuf1 :string[255]; keyBuf2 :string[255]; keyNum :smallint; btrieveLoaded :boolean; personID :longint; file1Open :boolean; file2Open :boolean; status:smallint; getStatus :smallint; i :smallint; posCtr :smallint; client :CLIENT_ID; versionBuffer :array[1..3] of VERSION_STRUCT; fileCreateBuf :FILE_CREATE_BUF; gneBuffer :GNE_BUFFER_PTR; personRecord :PERSON_STRUCT; {*********************************************************************** ListBox に書き込むためのヘルパー関数 ************************************************************************} procedure WritelnLB( LB:TListBox; Str:String); begin LB.Items.Add(Str); end; procedure TForm1.FormCreate(Sender:TObject); begin ArrowCursor := LoadCursor(0, IDC_ARROW); WaitCursor := LoadCursor(0, IDC_WAIT); end; {*********************************************************************** サンプルのメイン プロシージャ ************************************************************************} procedure TForm1.RunTest; begin ListBox1.Clear; WritelnLB( ListBox1, 'Test started ...' ); { 変数の初期化 } btrieveLoaded := FALSE; file1Open := FALSE; file2Open := FALSE; keyNum := 0; status := B_NO_ERROR; getStatus := B_NO_ERROR; { クライアント ID のセットアップ } fillchar(client.networkAndNode, sizeof(client.networkAndNode), #0); client.applicationID := 'MT'・+ #0; { "AA" 以上を設定 } client.threadID := MY_THREAD_ID; fillchar(versionBuffer, sizeof(versionBuffer), #0); dataLen := sizeof(versionBuffer); status = BTRVID( B_VERSION, posBlock1, versionBuffer, dataLen, keyBuf1[1], keyNum, client); if status = B_NO_ERROR then begin writelnLB( ListBox1, '返された Btrieve バージョンは' ); for i := 1 to 3 do begin with versionBuffer[i] do begin if (version > 0) then begin writelnLB(ListBox1, intToStr(version) + '.' + intToStr(revision) + ' ' + MKDEId); end end end; btrieveLoaded := TRUE; end else begin writelnLB(ListBox1, 'Btrieve B_VERSION status = ' + intToStr(status)); if status <> B_RECORD_MANAGER_INACTIVE then begin btrieveLoaded := TRUE; end end; { sample.btr を開く } if status = B_NO_ERROR then begin fillchar(dataBuffer, sizeof(dataBuffer), #0); fillchar(keyBuf1, sizeof(keyBuf1), #0); keyNum := 0; dataLen := 0; keyBuf1 := FILE_1 + #0; keyBuf2 := FILE_2 + #0; status = BTRVID( B_OPEN, posBlock1, dataBuffer, dataLen, keyBuf1[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status)); if status = B_NO_ERROR then begin file1Open := TRUE; end end; {* B_GET_EQUAL を使用して key 0 が既知の値であるレコードを取得 *} if status = B_NO_ERROR then begin fillchar(personRecord, sizeof(personRecord), #0); dataLen := sizeof(personRecord); personID := 263512477; {* 実際これは社会保障番号 *} status = BTRVID( B_GET_EQUAL, posBlock1, personRecord, dataLen, personID, keyNum, client); writelnLB(ListBox1, 'Btrieve B_GET_EQUAL status = ' + intToStr(status)); if status = B_NO_ERROR then with personRecord do begin writelnLB(ListBox1, ''); writelnLB(ListBox1, 'Selected fields from the retrieved record are:'); writelnLB(ListBox1, 'ID:' + intToStr(ID)); writelnLB(ListBox1, 'Name:' + FirstName + ' ' + LastName); writelnLB(ListBox1, 'Street:' + Street); writelnLB(ListBox1, 'City:' + City); writelnLB(ListBox1, 'State:' + State); writelnLB(ListBox1, 'Zip:' + Zip); writelnLB(ListBox1, 'Country:' + Country); writelnLB(ListBox1, 'Phone:' + Phone); writelnLB(ListBox1, ''); end; end; { Stat オペレーションを実行し、CreateBuffe(作成バッファー)を取得 } fillchar(fileCreateBuf, sizeof(fileCreateBuf), #0); dataLen := sizeof(fileCreateBuf); keyNum := -1; status := BTRVID(B_STAT, posBlock1, fileCreateBuf, dataLen, keyBuf1[1], keyNum, client); if (status = B_NO_ERROR) then begin { sample2.btr を作成して開く } keyNum := 0; dataLen := sizeof(fileCreateBuf); status := BTRVID(B_CREATE, posBlock2, fileCreateBuf, dataLen, keyBuf2[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_CREATE status = ' + intToStr(status)); end; if (status = B_NO_ERROR) then begin keyNum := 0; dataLen := 0; status = BTRVID( B_OPEN, posBlock2, dataBuffer, dataLen, keyBuf2[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_OPEN status = ' + intToStr(status)); if (status = B_NO_ERROR) then begin file2Open := TRUE; end; end; { 元のファイルからデータを抽出し、新しいファイルへ挿入 } if (status = B_NO_ERROR) then begin { getFirst を実行してカレンシーを確立 } keyNum := 2; { STATE-CITY index } fillchar(personRecord, sizeof(personRecord), #0); fillchar(keyBuf1, sizeof(keyBuf1), #0); dataLen := sizeof(personRecord); getStatus := BTRVID( B_GET_FIRST, posBlock1, personRecord, dataLen, keyBuf1[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_GET_FIRST status = ' + intToStr(GETstatus)); writelnLB(ListBox1, ''); end; { ヒープ メモリの割り当て } gneBuffer := new(GNE_BUFFER_PTR); fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0); strPCopy(gneBuffer^.preBuf.gneHeader.currencyConst, 'UC'); while (getStatus = B_NO_ERROR) do begin gneBuffer^.preBuf.gneHeader.rejectCount := 0; gneBuffer^.preBuf.gneHeader.numberTerms := 2; posCtr := sizeof(GNE_HEADER); { 最初の条件を代入 } gneBuffer^.preBuf.term1.fieldType := 11; gneBuffer^.preBuf.term1.fieldLen := 3; gneBuffer^.preBuf.term1.fieldOffset := 108; gneBuffer^.preBuf.term1.comparisonCode := 1; gneBuffer^.preBuf.term1.connector := 2; strPCopy(gneBuffer^.preBuf.term1.value, 'TX'); inc(posCtr, (sizeof(TERM_HEADER))); { 2 つ目の条件を代入 } gneBuffer^.preBuf.term2.fieldType := 11; gneBuffer^.preBuf.term2.fieldLen := 3; gneBuffer^.preBuf.term2.fieldOffset := 108; gneBuffer^.preBuf.term2.comparisonCode := 1; gneBuffer^.preBuf.term2.connector := 0; strPCopy(gneBuffer^.preBuf.term2.value, 'CA'); inc(posCtr, sizeof(TERM_HEADER)); { プロジェクション ヘッダーを設定してレコード全体を読み込む } gneBuffer^.preBuf.retrieval.maxRecsToRetrieve := 20; gneBuffer^.preBuf.retrieval.noFieldsToRetrieve := 1; inc(posCtr, sizeof(RETRIEVAL_HEADER)); gneBuffer^.preBuf.recordRet.fieldLen := sizeof(PERSON_STRUCT); gneBuffer^.preBuf.recordRet.fieldOffset := 0; inc(posCtr, sizeof(FIELD_RETRIEVAL_HEADER)); gneBuffer^.preBuf.gneHeader.descriptionLen := posCtr; dataLen := sizeof(GNE_BUFFER); getStatus := BTRVID( B_GET_NEXT_EXTENDED, posBlock1, gneBuffer^, dataLen, keyBuf1, keyNum, client); writelnLB(ListBox1, 'Btrieve B_GET_NEXT_EXTENDED status = ' + intToStr(getStatus)); { Get Next Extended は、ファイルの終わりまで到達してもレコードを返すことがあります } if ((getStatus = B_NO_ERROR) or (getStatus = B_END_OF_FILE)) then begin writelnLB(ListBox1, 'GetNextExtended returned ' + intToStr(gneBuffer^.postBuf.numReturned) + ' records.'); for i := 0 to gneBuffer^.postBuf.numReturned - 1 do begin dataLen := sizeof(PERSON_STRUCT); personRecord := gneBuffer^.postBuf.recs[i].personRecord; status = BTRVID( B_INSERT, posBlock2, personRecord, dataLen, keyBuf2, -1, { カレンシー変更なし } client); if (status <> B_NO_ERROR) then begin writelnLB(ListBox1, 'Btrieve B_INSERT status = ' + intToStr(status)); break; end; end; writelnLB(ListBox1, 'Inserted ' + intToStr(gneBuffer^.postBuf.numReturned) + ' records in new file, status = ' + intToStr(status)); writelnLB(ListBox1, ''); end; fillchar(gneBuffer^, sizeof(GNE_BUFFER), #0); gneBuffer^.preBuf.gneHeader.currencyConst := 'EG'; end; dispose(gneBuffer); { 開いているファイルを閉じる } keyNum := 0; if file1Open = TRUE then begin dataLen := 0; status = BTRVID( B_CLOSE, posBlock1, dataBuffer, dataLen, keyBuf1[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample.btr) = ' + intToStr(status)); end; if file2Open = TRUE then begin dataLen := 0; status = BTRVID( B_CLOSE, posBlock2, dataBuffer, dataLen, keyBuf2[1], keyNum, client); writelnLB(ListBox1, 'Btrieve B_CLOSE status (sample2.btr) = ' + intToStr(status)); end; { リソース解放 } dataLen := 0; status := BTRVID(B_STOP, posBlock1, DataBuffer, dataLen, keyBuf1[1], 0, client); WritelnLB(ListBox1, 'Btrieve B_STOP status = ' + intToStr(status) ); end; procedure TForm1.ExitButtonClick(Sender:TObject); begin Close; end; procedure TForm1.RunButtonClick(Sender:TObject); begin SetCursor(WaitCursor); RunTest; SetCursor(ArrowCursor); end; end.
Delphi 3、4、5 では、サンプル プログラムのコンパイル、リンク、実行を、以下の方法で行います。
Delphi 1 では、サンプル プログラムのコンパイル、リンク、実行を、以下の方法で行います。
|