|
ここでは、Btrieve API で実行できる以下のタスクの Visual Basic、Delphi および C/C++ のコード サンプルを示します。
Create(14)オペレーションを使用して、アプリケーション内からファイルを作成することができます。ファイルを作成するには、新しい Btrieve ファイルの作成に必要な情報を含む構造体を作成する必要があります。
この API の詳細については、『Btrieve API Guide』を参照してください。
以下のサンプル コードは、Create オペレーションでファイルを作成する方法を示しています。
以下のサブルーチンは、Orders というファイルを作成します。
Sub CreateOrdersFile(OrdFileLocation As String) ' 次の構文はファイル仕様を設定します OrdFixedRecSize = Len(OrdRecBuf) FileDefinitionBuffer.RecLen = OrdFixedRecSize FileDefinitionBuffer.PageSize = 4096 FileDefinitionBuffer.IndxCnt = 2 FileDefinitionBuffer.FileFlags = VARIABLELENGTH ' キー 0、注文番号 FileDefinitionBuffer.KeyBuf0.KeyPos = 1 FileDefinitionBuffer.KeyBuf0.KeyLen = 4 FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC) ' キー 1、連絡先番号 FileDefinitionBuffer.KeyBuf1.KeyPos = 5 FileDefinitionBuffer.KeyBuf1.KeyLen = 4 FileDefinitionBuffer.KeyBuf1.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf1.KeyType = Chr$(BUNSGBIN) BufLen = Len(FileDefinitionBuffer) OrdFileLocation = OrdFileLocation & " " KeyBufLen = Len(OrdFileLocation) CopyMemory OrdKeyBuffer, OrdFileLocation, Len(OrdFileLocation) giStatus = BTRCALL(BCREATE, OrdPosBlock, FileDefinitionBuffer, BufLen, _ ByValOrdFileLocation, KeyBufLen, 0) End Sub
以下のルーチンは、Customer という可変長ファイルを作成します。
function CreateCustomerFile(FileName:String):SmallInt; var CustRec :CustomerRecordType; // ユーザー定義のレコード構造体 CustBufLen :word; CustPosBlock :TPositionBlock; // [1..128] のバイト配列 CustFileLocation :String[255]; CustFixedRecSize :LongInt; FileDefinitionBuffer :FileCreateBuffer; // ファイル作成用の構造体 FilebufLen :Word; KeyNum :ShortInt; begin { 次の構文はファイル仕様を定義します } { レコードの固定長部分のみのサイズを計算 } CustFixedRecSize := SizeOf(CustRec) - SizeOf(CustRec.Notes); FileDefinitionBuffer.fileSpec.recLen := CustFixedRecSize; FileDefinitionBuffer.fileSpec.PageSize := 4096; FileDefinitionBuffer.fileSpec.IndexCount:= 4; FileDefinitionBuffer.fileSpec.FileFlags := VARIABLELENGTH; { キー仕様の定義、キー 0 連絡先番号 } FileDefinitionBuffer.keyspecArray[0].Position := 1; FileDefinitionBuffer.keyspecArray[0].Length := 4; { 4 バイト整数 } FileDefinitionBuffer.keyspecArray[0].Flags := KFLG_EXTTYPE_KEY + KFLG_MODX; FileDefinitionBuffer.keyspecArray[0].KeyType := AUTOINCREMENT_TYPE; {キー 1、連絡先名 } FileDefinitionBuffer.keyspecArray[1].Position := 5; FileDefinitionBuffer.keyspecArray[1].Length := 30; FileDefinitionBuffer.keyspecArray[1].Flags := KFLG_EXTTYPE_KEY +KFLG_MODX + KFLG_DUP; FileDefinitionBuffer.keyspecArray[1].KeyType := STRING_TYPE; { キー 2、会社名 } FileDefinitionBuffer.keyspecArray[2].Position := 35; FileDefinitionBuffer.keyspecArray[2].Length := 60; FileDefinitionBuffer.keyspecArray[2].Flags := KFLG_EXTTYPE_KEY + KFLG_MODX + KFLG_DUP; FileDefinitionBuffer.keyspecArray[2].KeyType := STRING_TYPE; { キー 3、販売員、次回の連絡日 } FileDefinitionBuffer.keyspecArray[3].Position := 220; FileDefinitionBuffer.keyspecArray[3].Length := 4; FileDefinitionBuffer.keyspecArray[3].Flags := KFLG_EXTTYPE_KEY + KFLG_MODX + KFLG_DUP + KFLG_SEG; FileDefinitionBuffer.keyspecArray[3].KeyType := LSTRING_TYPE; FileDefinitionBuffer.keyspecArray[4].Position := 223; FileDefinitionBuffer.keyspecArray[4].Length := 4; FileDefinitionBuffer.keyspecArray[4].Flags := KFLG_EXTTYPE_KEY + KFLG_MODX + KFLG_DUP; FileDefinitionBuffer.keyspecArray[4].KeyType := DATE_TYPE; CustFileLocation := FileName + #0; { 作成するファイルのパスおよびファイル名 } FilebufLen := sizeof(FileDefinitionBuffer); KeyNum := 0; FillChar(CustPosBlock, SizeOf(CustPosBlock), #0); Result := BTRV(B_CREATE, //OpCode 14 CustPosBLock, // ポジション ブロック("cursor" または "handle") FileDefinitionBuffer, // 新規ファイルの定義 FileBufLen, // 定義の長さ CustFileLocation[1], // パスとファイル名 keyNum); // 0(ゼロ)は既存のファイルを上書きする end; {CreateCustomerFile}
BTI_SINT CreateCustomerFile(LPCTSTR szCustomerFileName) { Customer_Record_Type CustRec; // ユーザー定義のレコード構造体 char CustPosBlock[POS_BLOCK_SIZE]; // customer ファイル内の "Cursor" char CustFileLocation[255]; size_t CustFixedRecSize; FileDescriptionType FileDefBuf; // ファイル作成用の構造体 BTI_WORD FilebufLen; char KeyNum; // 1 バイトの符号付き整数 BTI_SINT iStatus; /* レコードの固定長部分のサイズを計算 */ CustFixedRecSize = sizeof(CustRec) - sizeof(CustRec.Notes); FileDefBuf.RecLen = CustFixedRecSize; FileDefBuf.PageSize = 4096; FileDefBuf.IndxCnt = 4; FileDefBuf.DupPointers = 4; FileDefBuf.FileFlags = VAR_RECS | BALANCED_KEYS; /* キー仕様の定義、キー 0 連絡先番号 */ FileDefBuf.KeyBuf[0].KeyPos = 1; FileDefBuf.KeyBuf[0].KeyLen = 4; FileDefBuf.KeyBuf[0].KeyFlags = EXTTYPE_KEY | MOD; FileDefBuf.KeyBuf[0].KeyType = AUTOINCREMENT_TYPE; /* キー 1 - 連絡先名 */ FileDefBuf.KeyBuf[1].KeyPos = 5; FileDefBuf.KeyBuf[1].KeyLen = 30; FileDefBuf.KeyBuf[1].KeyFlags = EXTTYPE_KEY | DUP | MOD ; FileDefBuf.KeyBuf[1].KeyType = STRING_TYPE; /* キー 2 - 会社名 */ FileDefBuf.KeyBuf[2].KeyPos = 35; FileDefBuf.KeyBuf[2].KeyLen = 60; FileDefBuf.KeyBuf[2].KeyFlags = EXTTYPE_KEY | DUP | MOD ; FileDefBuf.KeyBuf[2].KeyType = STRING_TYPE; /* キー 3 - 販売員、次回の連絡日 */ FileDefBuf.KeyBuf[3].KeyPos = 220; FileDefBuf.KeyBuf[3].KeyLen = 3; FileDefBuf.KeyBuf[3].KeyFlags = EXTTYPE_KEY | DUP | MOD | SEG; FileDefBuf.KeyBuf[3].KeyType = STRING_TYPE; FileDefBuf.KeyBuf[4].KeyPos = 223; FileDefBuf.KeyBuf[4].KeyLen = 4; FileDefBuf.KeyBuf[4].KeyFlags = EXTTYPE_KEY | DUP | MOD ; FileDefBuf.KeyBuf[4].KeyType = DATE_TYPE; // //------------------------------------------------------------------------ FilebufLen = sizeof(FileDefBuf); KeyNum = 0; // 上書き処理 strcpy(CustFileLocation, szCustomerFileName); iStatus = BTRV(B_CREATE, CustPosBlock, &FileDefBuf, &FilebufLen, CustFileLocation, KeyNum); return(iStatus); } // CreateCustomerFile()
以下のサンプル構造体はそれぞれ、前の Visual Basic、Delphi および C/C++ のコード サンプルで使用される構造体です。
Declare Function BTRCALL Lib "w3btrv7.dll" (ByVal OP, ByVal Pb$, Db As Any, _ DL As Long, Kb As Any, ByVal Kl, ByVal Kn) As Integer Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _ (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long) Type OrderRecordBufferType OrderNumberAs typ_byte4 ' 4 バイト unsigned ContactNumber As typ_byte4 ' 4 バイト unsigned OrderDateAs DateType OrderTotal As typ_byte4 ' 4 バイト real NotUsed As String * 64 End Type Type OrderKeyBufferType BufferValue(255) As Byte OrderNumber As typ_byte4 CustNumber As typ_byte4 NotUsed As String * 64 End Type Type FileSpec RecLenAs Integer PageSize As Integer IndxCnt As Integer NotUsedAs String * 4 FileFlags As Integer Reserved As String * 2 Allocation As Integer KeyBuf0 As KeySpec KeyBuf1 As KeySpec KeyBuf2 As KeySpec KeyBuf3 As KeySpec KeyBuf4 As KeySpec KeyBuf5 As KeySpec End Type Global FileDefinitionBuffer As FileSpec { 以下は Order テーブル変数 } Global OrdPosBlock As Byte(0 to 127) Global OrdRecPos As typ_byte4 Global OrdRecBuf As OrderRecordBufferType Global OrdKeyBuffer As OrderKeyBufferType Global OrdFixedRecSize As Long Global OrdFileLocation As String
type CustomerRecordType = packed record 必要に応じた処理 end; //CustomerRecordType type TPositionBlock = array[0..127] of byte; type BTI_KEY_DESC = packed record Position :BTI_SINT; Length :BTI_SINT; KeyFlags :BTI_SINT; NumUnique :BTI_LONG; ExtKeyType:BTI_BYTE; NullVal :BTI_BYTE; Reserv :array [0..1] of BTI_CHAR; KeyNumber :BTI_UBYTE; ACSNumber :BTI_UBYTE; end; {BTI_KEY_DESC} BTI_KEY_ARRAY = array [0..MAX_KEY_SEG - 1] of BTI_KEY_DESC; BTI_ACS = array [0..ACS_SIZE - 1] of BTI_CHAR; type FileCreateBuffer = packed record RecLen :BTI_SINT; PageSize :BTI_SINT; NumKeys :BTI_SINT; Reserved1 :BTI_LONG; FileFlags :BTI_SINT; DupPointers:BTI_BYTE; Reserved2 :BTI_BYTE; Alloc :BTI_SINT; Keys :BTI_KEY_ARRAY; ACS :BTI_ACS; end; {BTI_FILE_DESC}
ここで留意すべき点は、定義を簡単にするために、オルタネート コレーティング シーケンス(ACS)をキー配列全体の後に置くということです。Btrieve は、最後のキー セグメントの直後に ACS が続くことを期待しているため、ACS を構造体内の該当位置まで移動させる必要があります。
struct CustRec { 必要に応じた処理 } //CustRec struct date_type { BTI_BYTE day; BTI_BYTE month; BTI_SINT year; }; //date_type struct KeySpec { BTI_SINT KeyPos; BTI_SINT KeyLen; BTI_SINT KeyFlags; BTI_LONG KeyTot; BTI_CHAR KeyType; BTI_CHAR NulValue; BTI_CHAR NotUsed[2]; BTI_BYTE KeyNumber; BTI_BYTE ACSNum; }; //KeySpec struct FileDescriptionType { BTI_SINT RecLen; BTI_SINT PageSize; BTI_SINT IndxCnt; BTI_LONG RecTot; BTI_SINT FileFlags; BTI_BYTE DupPointers; BTI_BYTE NotUsed; BTI_SINT Allocation; KeySpec KeyBuf[119]; }; //FileDescriptionType
Insert(2)オペレーションは、ファイルにレコードを挿入します。この API への呼び出しを行うには以下の前提条件を満たす必要があります。
データ バッファーに挿入する行を設定して BINSERT を呼び出すことにより、行を挿入できます。この API の詳細については、『Btrieve API Guide』を参照してください。以下のサンプル コードとサンプル構造体は、Visual Basic、Delphi および C/C++ で Insert オペレーションを実行する方法を示しています。
以下のサンプル コードは、Insert オペレーションでレコードを挿入する方法を示しています。
FillCustBufFromCustomerEdit InsertCustomerRecord ' BtrCallModule プロシージャ Sub FillCustBufFromCustomerEdit() Dim tmplong As Long Dim StrDay As String * 2 Dim StrMonth As String * 2 Dim StrYear As String * 4 tmplong = CLng(FormCustomerEdit.EdContactNumber.Text) CustRecBuf.ContactNumber = ToType4(tmplong) ' この関数は、サンプル構造体(レコードの挿入)のサンプルを参照してください CustRecBuf.ContactName = FormCustomerEdit.EdContactName.Text CustRecBuf.CompanyName = FormCustomerEdit.EdCompanyName.Text CustRecBuf.Address1 = FormCustomerEdit.EdAddress1.Text CustRecBuf.Address2 = FormCustomerEdit.EdAddress2.Text CustRecBuf.City = FormCustomerEdit.EdCity.Text CustRecBuf.State = FormCustomerEdit.EdState.Text CustRecBuf.ZipCode = FormCustomerEdit.EdZip.Text CustRecBuf.Country = FormCustomerEdit.EdCountry.Text CustRecBuf.SalesRep = FormCustomerEdit.EdSalesRep.Text StrDay = Mid$(FormCustomerEdit.EdContactDate.Text, 1, 2) StrMonth = Mid$(FormCustomerEdit.EdContactDate.Text, 4, 2) StrYear = Mid$(FormCustomerEdit.EdContactDate.Text, 7, 4) CustRecBuf.NextContact.Day = CByte(StrDay) CustRecBuf.NextContact.Month = CByte(StrMonth) CustRecBuf.NextContact.Year = CInt(StrYear) CustRecBuf.PhoneNumber = FormCustomerEdit.EdPhone.Text CustRecBuf.Notes = Trim(FormCustomerEdit.EdNotes.Text) & Chr$(0) FormCustomerEdit.EdRecLength = Str(CustBufLength) End Sub Sub InsertCustomerRecord() Dim lCustBufLength As Long Dim iKeyNum As Integer Dim iKeyBufLen As Integer lCustBufLength = Len(CustRecBuf) - MaxNoteFieldSize + Len(Trim(CustRecBuf.Notes)) ' CustBufLength = 238 iKeyBufLen = KEY_BUF_LEN iKeyNum = CustKeyBuffer.CurrentKeyNumber giStatus = BTRCALL(BINSERT, CustPosBlock, CustRecBuf, _ lCustBufLength, CustKeyBuffer, iKeyBufLen, iKeyNum) End Sub
function InsertCustomerRecord( var CustPosBlock : TPositionBlock; CustRec : CustomerRecordType) : SmallInt; var CustBufLen :Word; KeyNum :ShortInt; CustKeyBuffer:String[255]; begin { 可変長レコードの全体のサイズを計算 } CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) + Length(CustRec.Notes); KeyNum := -1; { 挿入時の "カレンシー変更なし" を指定 } FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); { 実行は不要 } Result := BTRV(B_INSERT, //OpCode 2 CustPosBLock, // 既に開いているポジション ブロック CustRec, // 挿入するレコード CustBufLen, // 新規レコードの長さ CustKeyBuffer[1], // NCC insert には不要 KeyNum); end; {InsertCustomerRecord}
BTI_SINT InsertCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE], Customer_Record_Type CustRec) { BTI_WORD CustBufLen; char KeyNum; // 1 バイトの符号付きバイト char CustKeyBuffer[255]; BTI_SINT iStatus; /* 可変長レコードの全体のサイズを計算 */ CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes); KeyNum = -1; // insert 中の "カレンシー変更なし" を指定 memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //実行は不要 iStatus = BTRV(B_INSERT, //OpCode 2 CustPosBlock, // 既に開いているポジション ブロック &CustRec, // 挿入するレコード &CustBufLen, // 新規レコードの長さ CustKeyBuffer, // NCC insert には不要 KeyNum); PrintStatus("B_INSERT:status = %d", iStatus); return(iStatus); } // InsertCustomerRecord()
以下のサンプル構造体はそれぞれ、前の Visual Basic、Delphi および C/C++ のコード サンプルで使用される構造体です。
Global Const BINSERT = 2 ' 以下は Customer テーブルのデータ構造 Type CustomerRecordBufferType ContactNumber As typ_byte4 ContactNameAs String * 30 CompanyName As String * 60 Address1 As String * 30 Address2 As String * 30 City As String * 30 StateAs String * 2 ZipCodeAs String * 10 CountryAs String * 3 PhoneNumberAs String * 20 SalesRepAs String * 3 NextContactAs DateType NotUsedAs String * 12 Notes As String * MaxNoteFieldSize End Type ' 以下は Customer ファイルの変数 Global CustPosBlockAs Byte(0 to 127) Global CustRecBuf As CustomerRecordBufferType Global CustKeyBufferAs CustomerKeyBufferType Global CustFixedRecSize As Long Global CustFileLocationAs String Global CustPositionAs typ_byte4 Global CustPosPercent As typ_byte4 Function ToInt(vValue As typ_byte4) As Long Dim iInt As Long CopyMemory iInt, vValue, 4 ToInt = iInt End Function Function ToType4(vValue As Long) As typ_byte4 Dim tmpTyp4 As typ_byte4 CopyMemory tmpTyp4, vValue, 4 ToType4 = tmpTyp4 End Function
Update(3)オペレーションは、既存のレコード内の情報を変更します。この Btrieve 呼び出しを行うには、ファイルが開いており、物理カレンシーが確立していなければなりません。トランザクション内でレコードを更新する場合は、レコードの取得もトランザクション内で行う必要があります。
この API の詳細については、『Btrieve API Guide』を参照してください。以下のサンプル コードとサンプル構造体は、Visual Basic、Delphi および C/C++ で Update オペレーションを実行する方法を示しています。
以下のサンプル コードは、Update オペレーションでファイルを変更する方法を示しています。
FillCustBufFromCustomerEdit UpdateCustomerRecord 'BtrCallModule プロシージャ Sub FillCustBufFromCustomerEdit() Dim tmplong As Long Dim StrDay As String * 2 Dim StrMonth As String * 2 Dim StrYear As String * 4 tmplong = CLng(FormCustomerEdit.EdContactNumber.Text) CustRecBuf.ContactNumber = ToType4(tmplong) CustRecBuf.ContactName = FormCustomerEdit.EdContactName.Text CustRecBuf.CompanyName = FormCustomerEdit.EdCompanyName.Text CustRecBuf.Address1 = FormCustomerEdit.EdAddress1.Text CustRecBuf.Address2 = FormCustomerEdit.EdAddress2.Text CustRecBuf.City = FormCustomerEdit.EdCity.Text CustRecBuf.State = FormCustomerEdit.EdState.Text CustRecBuf.ZipCode = FormCustomerEdit.EdZip.Text CustRecBuf.Country = FormCustomerEdit.EdCountry.Text CustRecBuf.SalesRep = FormCustomerEdit.EdSalesRep.Text StrDay = Mid$(FormCustomerEdit.EdContactDate.Text, 1, 2) StrMonth = Mid$(FormCustomerEdit.EdContactDate.Text, 4, 2) StrYear = Mid$(FormCustomerEdit.EdContactDate.Text, 7, 4) CustRecBuf.NextContact.Day = CByte(StrDay) CustRecBuf.NextContact.Month = CByte(StrMonth) CustRecBuf.NextContact.Year = CInt(StrYear) CustRecBuf.PhoneNumber = FormCustomerEdit.EdPhone.Text CustRecBuf.Notes = Trim(FormCustomerEdit.EdNotes.Text) & Chr$(0) FormCustomerEdit.EdRecLength = Str(CustBufLength) End Sub Sub UpdateCustomerRecord() Dim lCustBufLength As Long Dim iKeyBufLen As Integer Dim iKeyNum As Integer ' 次の構文は customer レコードを更新します lCustBufLength = Len(CustRecBuf) - MaxNoteFieldSize + Len(Trim(CustRecBuf.Notes)) iKeyBufLen = KEY_BUF_LEN iKeyNum = CustKeyBuffer.CurrentKeyNumber giStatus = BTRCALL(bUpdate, CustPosBlock, CustRecBuf, _ lCustBufLength, CustKeyBuffer, iKeyBufLen, iKeyNum) End Sub
function UpdateCustomerRecord( var CustPosBlock:TPositionBlock; CustRec :CustomerRecordType) :SmallInt; var CustBufLen :Word; KeyNum :ShortInt; CustKeyBuffer :String[255]; begin { 可変長レコードの全体のサイズを計算 } CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) + Length(CustRec.Notes); KeyNum := -1; { 更新時の "カレンシー変更なし" を指定 } FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); { 実行は不要 } Result := BTRV(B_UPDATE, //OpCode 3 CustPosBLock, // 既に開いているポジション ブロック CustRec, // 新規レコード CustBufLen, // 新規レコードの長さ CustKeyBuffer[1], // NCC update には不要 KeyNum); end; {UpdateCustomerRecord}
BTI_SINT UpdateCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE], Customer_Record_Type CustRec) { BTI_WORD CustBufLen; char KeyNum; // 1 バイトの符号付きバイト char CustKeyBuffer[255]; BTI_SINT iStatus; /* 可変長レコードの全体のサイズを計算 */ CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes); KeyNum = -1; // 更新時の "カレンシー変更なし" を指定 memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //実行は不要 iStatus = BTRV(B_UPDATE, //OpCode 3 CustPosBlock, // 既に開いているポジション ブロック &CustRec, // 挿入するレコード &CustBufLen, // 新規レコードの長さ CustKeyBuffer, // NCC insert には不要 KeyNum); PrintStatus("B_UPDATE:status = %d", iStatus); return(iStatus); } //UpdateCustomerRecord()
以下のサンプル構造体はそれぞれ、前の Visual Basic、Delphi および C/C++ のコード サンプルで使用される構造体です。
Insert オペレーションについては、サンプル構造体(レコードの挿入)を参照してください。
Step オペレーション(Step First、Step Next、Step Last、Step Previous)では、レコードを取得してデータ バッファーに入れることができます。レコードを取得するためにキー パスは使用されません。これらの API の詳細については、『Btrieve API Guide』を参照してください。
以下のサンプル コードとサンプル構造体は、Delphi および C/C++ で Step オペレーションを実行する方法を示しています。
メモ
レコードが返される順序に決して依存しないでください。MicroKernel は、いつでもファイル内のレコードを移動できます。特定の順序でレコードを必要とする場合は、Get オペレーションを使用してください。
以下のサンプル コードは、Step オペレーションでレコードを取得する方法を示しています。
以下のコード例は、ファイル内の最初の物理位置を返します。
{ ファイルから最初の物理レコードを取得 } CustBufLen := SizeOf(CustRec); // データ レコードの最大サイズ Status := BTRV(B_STEP_FIRST, //OpCode 33 CustPosBLock, // 既に開いているポジション ブロック CustRec, // レコードが返されるバッファー CustBufLen, // 返される最大長 CustKeyBuffer[1], // Step では不要 CustKeyNumber); // Step では不要 { ファイルから 2 番目のレコードを取得(順序は保証されない) } CustBufLen := SizeOf(CustRec); // リセット - 前の Step によって変更されている Status := BTRV(B_STEP_NEXT, //OpCode 24 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1] CustKeyNumber); { 先頭レコードに戻る } CustBufLen := SizeOf(CustRec); // リセット - 前の Step によって変更されている Status := BTRV(B_STEP_PREV, //OpCode 35 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1], CustKeyNumber);
/* ファイルから最初の物理レコードを取得 */ CustBufLen = sizeof(CustRec); // データ レコードの最大サイズ iStatus = BTRV(B_STEP_FIRST, //OpCode 33 CustPosBLock, // 既に開いているポジション ブロック &CustRec, // レコードが返されるバッファー &CustBufLen, // 返される最大長 CustKeyBuffer, // Step では不要 KeyNum); // Step では不要 /* ファイルから 2 番目のレコードを取得(順序は保証されない) */ CustBufLen = sizeof(CustRec); // リセット - 前の Step によって変更されている iStatus = BTRV(B_STEP_NEXT, //OpCode 24 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, KeyNum); /* 先頭レコードに戻る */ CustBufLen = sizeof(CustRec); // リセット - 前の Step によって変更されている iStatus = BTRV(B_STEP_PREVIOUS, //OpCode 35 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, KeyNum);
以下のサンプル構造体はそれぞれ、前の Delphi および C/C++ のコード サンプルで使用される構造体です。
Get オペレーションでは、レコードを取得できます。これらのオペレーションは、どの行を返すかを指定するためにキー バッファー パラメーターを必要とします。これらの API の詳細については、『Btrieve API Guide』を参照してください。
以下のサンプル コードとサンプル構造体は、Visual Basic、Delphi および C/C++ でいくつかの Get オペレーションを実行する方法を示しています。
以下のサンプル コードは、Get オペレーションでファイルを取得する方法を示しています。
Sub LoadContactBox(RecPosition As typ_byte4) FormBrowseCustomers.lstContact.Clear GetDirectCustomerRecord ' BtrCallModule プロシージャ If giStatus = 0 Then ' 次の構文は contact リスト ボックス文字列を作成します FormatContListBoxString If giStatus = 0 Then PosIndex = 0 PosArray(PosIndex) = RecPosition FirstRecPosition = RecPosition End If Else FormBrowseCustomers.lblMsg.Caption = "didn't get record" End If ' 次の構文はリスト ボックスの残りを埋めます While giStatus = 0 And PosIndex < CustMaxNumRows - 1 GetNextCustomerRecord ' BtrCallModule プロシージャ If giStatus = 0 Then ' contact リスト ボックス文字列を作成 FormatContListBoxString ' 次の構文はレコード位置を返します GetPositionCustomerRecord ' BtrCallModule プロシージャ If giStatus = 0 Then PosIndex = PosIndex + 1 PosArray(PosIndex) = RecPosition ' 次の構文はレコード位置配列へのポインターを構築します Select Case PosIndex Case 1 SecondRecPosition = RecPosition Case 10 SecToLastRecPosition = RecPosition Case 11 LastRecPosition = RecPosition End Select End If End If Wend If FormBrowseCustomers.lstContact.ListCount <> 0 Then FormBrowseCustomers.lstContact.ListIndex = 0 End If End Sub Sub GetDirectCustomerRecord() Dim iKeyBufLen As Integer Dim iKeyNum As Integer ' 次の構文はレコード位置によって直接レコードを取得します BufLen = Len(CustRecBuf) iKeyBufLen = MaxKeyBufLen iKeyNum = CustKeyBuffer.CurrentKeyNumber ' 次の構文はデータ バッファーにアドレスを設定します CustRecBuf.Notes = "" ' 取得の前に可変長領域をクリア LSet CustRecBuf = RecPosition giStatus = BTRCALL(BGETDIRECT, CustPosBlock, _ CustRecBuf, BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum) DBLen = BufLen End Sub Sub GetNextCustomerRecord() Dim iKeyNum As Integer Dim iKeyBufLen As Integer ' 次の構文は次の customer レコードを返します BufLen = Len(CustRecBuf) iKeyBufLen = KEY_BUF_LEN iKeyNum = CustKeyBuffer.CurrentKeyNumber giStatus = BTRCALL(BGETNEXT, CustPosBlock, CustRecBuf, _ BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum) End Sub Sub GetPositionCustomerRecord() Dim iKeyBufLen As Integer Dim iKeyNum As Integer ' 次の構文はレコード位置を返します BufLen = MaxDataBufLen iKeyBufLen = KEY_BUF_LEN iKeyNum = CustKeyBuffer.CurrentKeyNumber giStatus = BTRCALL(BGETPOS, CustPosBlock, RecPosition, _ BufLen, CustKeyBuffer, iKeyBufLen, iKeyNum) End Sub
var CustKeyBuffer:LongInt; begin CustBufLen := SizeOf(CustRec); CustKeyNumber := 0; { Contact ID 順 } { 次の構文は指定したソート順を使用してファイルから最初のレコードを返します } CustBufLen := SizeOf(CustRec); // データ レコードの最大サイズ Status := BTRV(B_GET_FIRST, //OpCode 12 CustPosBLock, // 既に開いているポジション ブロック CustRec, // レコードが返されるバッファー CustBufLen, // 返される最大長 CustKeyBuffer, // レコードから抽出したキー値を返す CustKeyNumber); // 取得時に使用するインデックス順 { 次の構文は指定したソート順でファイル内の次のレコードを返します } CustBufLen := SizeOf(CustRec); // リセット - 前の Get によって変更されている Status := BTRV(B_GET_NEXT, //OpCode 6 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1], CustKeyNumber); { 次の構文はファイル内の前のレコードを返します } CustBufLen := SizeOf(CustRec); // リセット - 前の Step によって変更されている Status := BTRV(B_GET_PREV, //OpCode 7 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1], CustKeyNumber);
/* ファイルから最初の論理レコードを取得 */ CustBufLen = sizeof(CustRec); // データ レコードの最大サイズ iStatus = BTRV(B_GET_FIRST, //OpCode 12 CustPosBLock, // 既に開いているポジション ブロック &CustRec, // レコードが返されるバッファー &CustBufLen, // 返される最大長 CustKeyBuffer, // レコードから抽出したキー値を返す CustKeyNumber); // 取得時に使用するインデックス順 /* ファイルから 2 番目のレコードを取得選択したキー順 */ CustBufLen = sizeof(CustRec); // リセット - 前の Get によって変更されている iStatus = BTRV(B_GET_NEXT, //OpCode 6 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, CustKeyNumber); /* 先頭レコードに戻る */ CustBufLen = sizeof(CustRec); // リセット - 前の Get によって変更されている iStatus = BTRV(B_GET_PREVIOUS, //OpCode 7 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, CustKeyNumber);
以下のサンプル構造体はそれぞれ、前の Visual Basic および Delphi のコード サンプルで使用される構造体です。
Btrieve のチャンク オペレーションを使用すると、可変長レコード部分および BLOB 部分の読み書きが行えます。最大レコード長は 64 GB ですが、固定レコード長の最大は 64 KB(65,535 バイト)です。最初の 65,535 バイトを越えた先にあるレコードの各部分にアクセスしたいときに、チャンクを使用します。
以下のサンプル コードは、チャンク、バイナリ ラージ オブジェクト(BLOB)および可変長レコードを処理する方法を示しています。
Private Sub LoadImageFromBtrieve() ' 次の構文は、Btrieve に格納されているイメージを ' 出力イメージ テキスト ボックスで指定したファイルに返します Dim lBytes As Long Dim lBytesread As Long Dim sLine As String Dim lBytesToRead As Long Dim iKey As Integer Dim lAddressMode As Long Dim lNumberOfChunks As Long Dim lChunkOffset As Long Dim lChunkAddress As Long Dim lChunkLength As Long Dim iNumChunksRead As Integer GetEqualGraphicRecord ' レコードと BLOB の一部を取得 On Error GoTo FileNotFound FormCustomerGraphic.MousePointer = 11 lNumberOfChunks = 0 On Error GoTo BMPOpenError Open txtOutputImage.Text For Binary Access Write As #1 lBytesread = (BufLen - 68) '読み取ったバイト数からグラフィック レコードの '固定長を差し引いた値を保存する 'グラフィック レコードの最初のチャンクの固定長は '68 です(上の GetEqualGraphicRecord) sLine = Right(ChunkReadBuffer.ChunkArray, lBytesread) Put #1, , sLine '最初のチャンクを bmp ファイルに書き出す iNumChunksRead = 1 If giStatus = 22 And (BufLen = MaxChunkSize) Then GetPositionGraphicRecord 'チャンクを取得する前に '現在のレコードの位置を取得する必要がある Do lNumberOfChunks = 1 lChunkOffset = 0 lChunkAddress = 0 lChunkLength = MaxChunkSize iNumChunksRead = iNumChunksRead + 1 ChunkGetBuffer.RecordAddress = GrphPosition 'H80000000(ランダム チャンクの取得) 'H40000000(ネクスト イン レコード バイアス)はレコード内カレンシーを使用させる ChunkGetBuffer.AddressMode = ToType4((&H80000000 + &H40000000)) ChunkGetBuffer.NumberOfChunks = ToType4(lNumberOfChunks) ChunkGetBuffer.ChunkOffset = ToType4(lChunkOffset) ChunkGetBuffer.ChunkAddress = ToType4(lChunkAddress) ChunkGetBuffer.ChunkLength = ToType4(lChunkLength) ' 前の構文は読み取りバッファーを使用します。 ' 最初のチャンクの取得 GetEqualGraphicRecord で ' レコードの固定長が読み取られているため、以降の ' チャンクの取得ではバッファー全体を使用します。 ' 次の構文は読み取りバッファーと取得バッファーを読み込みます CopyMemory ChunkReadBuffer, ChunkGetBuffer, Len (ChunkGetBuffer) GetGraphicChunk If giStatus = 0 Then 'レコードの終わりを越えて読むと 103 が返される If MaxChunkSize <> BufLen Then sLine = Left(ChunkReadBuffer.ChunkArray, BufLen) lBytesread = lBytesread + (BufLen) Else sLine = ChunkReadBuffer.ChunkArray Bytesread = lBytesread + MaxChunkSize End If If Len(sLine) > 0 Then Put #1, , sLine End If End If Loop While (giStatus = 0) End If Close #1 On Error Resume Next Set Image1.Picture = LoadPicture(txtOutputImage.Text) FormCustomerGraphic.MousePointer = 0 NumChunks.Text = iNumChunksRead NumBytes.Text = lBytesread LastStatus.Text = giStatus On Error GoTo 0 Exit Sub 'InvalidPicture: MsgBox Err.Number & ":" & Err.Description & vbCrLf & "Load from disk and save", vbOKOnly, "Invalid Picture in Graphic file" Resume Next FileNotFound: MsgBox Err.Number & ":" & Err.Description, vbOKOnly, "Graphic Load Error" FormCustomerGraphic.MousePointer = 0 On Error GoTo 0 BMPOpenError: MsgBox "Directory for temporary imaging work does not exist." & vbCrLf & _ "Please select a valid directory for image out.", vbOKOnly, "User path error" Screen.MousePointer = vbDefault On Error GoTo 0 End Sub Sub GetGraphicChunk() Dim sKeyBuffer As String Dim iKeyBufLen As Integer BufLen = Len(ChunkReadBuffer) sKeyBuffer = Space$(KEY_BUF_LEN) iKeyBufLen = KEY_BUF_LEN { 次の構文では、キー番号にチャンク モードの -2 を設定する必要があります } giStatus = BTRCALL(BGETDIRECT, GrphPosBlock, ChunkReadBuffer, _ BufLen, ByVal sKeyBuffer, iKeyBufLen, -2) End Sub
次のサンプル構造体は、前の Visual Basic のコード サンプルで使用される構造体です。
Type GraphicRecordBufferType ContactNumber As typ_byte4 NotUsed As String * 64 End Type Type GraphicKeyBufferType BufferValue(255) As Byte CurrentKeyNumberAs Integer ContactNumber As typ_byte4 NotUsed As String * 64 End Type Type ChunkReadDescriptorNext ChunkArray As String * MaxChunkSize End Type Type ChunkGetDescriptor RecordAddressAs typ_byte4 AddressModeAs typ_byte4 NumberOfChunks As typ_byte4 ChunkOffsetAs typ_byte4 ChunkLengthAs typ_byte4 ChunkAddress As typ_byte4 End Type Global ChunkGetBuffer As ChunkGetDescriptor Global ChunkReadBuffer As ChunkReadDescriptorNext ' グラフィック テーブル変数 Global GrphPosBlock As Byte(0 to 127) Global GrphRecBuf As GraphicRecordBufferType Global GrphKeyBuffer As GraphicKeyBufferType Global GrphFixedRecSize As Long Global GrphFileLocation As String Global GrphKeyNumber As Integer Global GrphPosition As typ_byte4
以下のサンプル コードは、セグメント化されたインデックスを処理する方法を示しています。
Sub CreateCustomerFile(CustFileLocation As String) ' 次の構文は customer ファイルを作成し、ファイル仕様を設定します CustFixedRecSize = Len(CustRecBuf) - Len(CustRecBuf.Notes) FileDefinitionBuffer.RecLen = CustFixedRecSize FileDefinitionBuffer.PageSize = 4096 FileDefinitionBuffer.IndxCnt = 4 FileDefinitionBuffer.FileFlags = VARIABLELENGTH ' 以下はキー仕様を定義します ' キー 0、連絡先番号 FileDefinitionBuffer.KeyBuf0.KeyPos = 1 FileDefinitionBuffer.KeyBuf0.KeyLen = 4 FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC) ' キー 1、連絡先名 FileDefinitionBuffer.KeyBuf1.KeyPos = 5 FileDefinitionBuffer.KeyBuf1.KeyLen = 30 FileDefinitionBuffer.KeyBuf1.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf1.KeyType = Chr$(BSTRING) ' キー 2、連絡先名 FileDefinitionBuffer.KeyBuf2.KeyPos = 35 FileDefinitionBuffer.KeyBuf2.KeyLen = 60 FileDefinitionBuffer.KeyBuf2.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf2.KeyType = Chr$(BSTRING) ' キー 3、販売員、次回の連絡日 ' これはセグメント キー FileDefinitionBuffer.KeyBuf3.KeyPos = 220 FileDefinitionBuffer.KeyBuf3.KeyLen = 3 FileDefinitionBuffer.KeyBuf3.KeyFlags = EXTTYPE + _ MODIFIABLE + DUP + SEGMENT FileDefinitionBuffer.KeyBuf3.KeyType = Chr$(BSTRING) FileDefinitionBuffer.KeyBuf4.KeyPos = 223 FileDefinitionBuffer.KeyBuf4.KeyLen = 4 FileDefinitionBuffer.KeyBuf4.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf4.KeyType = Chr$(BDATE) BufLen = Len(FileDefinitionBuffer) CustFileLocation = CustFileLocation & " " KeyBufLen = Len(CustFileLocation) giStatus = BTRCALL(BCREATE, CustPosBlock, FileDefinitionBuffer, _ BufLen, ByVal CustFileLocation, KeyBufLen, 0) End Sub
セグメント化されたインデックスの作成に関するコードを参照するには、Delphi(ファイルの作成)コード サンプルの「キー 3」を参照してください。
var CustKeyBuffer:record // セグメント キー バッファー SalesRep :array[0..2] of Char; NextContact :DateType; //Btrieve データ構造 end; CustBufLen :Word; CustKeyNumber:ShortInt; begin CustKeyNumber := 3; //SalesRep/Date 順 CustKeyBuffer.SalesRep := 'TO'; //イニシャル TO の人物を検索 CustKeyBuffer.NextContact.Day := 9; //NextContact が 9/9/98 CustKeyBuffer.NextContact.Month := 9; CustKeyBuffer.NextContact.Year := 1998; CustBufLen := SizeOf(CustRec); { 次の構文は、指定したソート順(KeyNum)を使用してファイルから先頭レコードを取得します } Status := BTRV(B_GET_EQUAL, //OpCode 5 CustPosBLock, // 既に開いているポジション ブロック CustRec, // レコードが返されるバッファー CustBufLen, // 返される最大長 CustKeyBuffer, // レコードから抽出したキー値を返す CustKeyNumber); // 取得時に使用するインデックス順
struct // セグメント化されたキー バッファー { char SalesRep[3]; date_type NextContact; //Btrieve データ構造 } CustKeyBuffer; BTI_WORD CustBufLen; char CustKeyNumber; CustKeyNumber = 3; // SalesRep/Date 順 CustKeyBuffer.SalesRep = "TO"; // イニシャル TO の人物を検索 CustKeyBuffer.NextContact.Day = 9; // NextContact が 9/9/98 CustKeyBuffer.NextContact.Month = 9; CustKeyBuffer.NextContact.Year = 1998; CustBufLen = sizeof(CustRec); /* 指定したソート順(KeyNum)を使用してファイルから先頭レコードを取得する */ iStatus = BTRV(B_GET_EQUAL, //OpCode 5 CustPosBLock, // 既に開いているポジション ブロック &CustRec, // レコードが返されるバッファー &CustBufLen, // 返される最大長 CustKeyBuffer, // 検索するレコードを指定 CustKeyNumber); // 取得時に使用するインデックス順
|