|
This section shows Visual Basic, Delphi, and C/C++ code samples for the following tasks you can perform using the Btrieve API:
The Create (14) operation lets you generate a file from within your application. To create a file, you need to create a structure that contains the necessary information required to build a new Btrieve file.
For specific information about this API, refer to the API Programmer's Reference.
The following sample code illustrates how to create a file using the Create operation.
Sub CreateOrdersFile(OrdFileLocation As String) `The following syntax sets up file specifications. OrdFixedRecSize = Len(OrdRecBuf) FileDefinitionBuffer.RecLen = OrdFixedRecSize FileDefinitionBuffer.PageSize = 4096 FileDefinitionBuffer.IndxCnt = 2 FileDefinitionBuffer.FileFlags = VARIABLELENGTH `Key 0, by order number. FileDefinitionBuffer.KeyBuf0.KeyPos = 1 FileDefinitionBuffer.KeyBuf0.KeyLen = 4 FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC) `Key 1, by contact number. 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
function CreateCustomerFile(FileName: String): SmallInt; var CustRec : CustomerRecordType; //User defined record structure CustBufLen : word; CustPosBlock : TPositionBlock; // array[1..128] of byte CustFileLocation : String[255]; CustFixedRecSize : LongInt; FileDefinitionBuffer : FileCreateBuffer; // Structure type for creating a file FilebufLen : Word; KeyNum : ShortInt; begin {The following syntax defines file specifications.} {calculate the size of just the fixed portion of the record.} CustFixedRecSize := SizeOf(CustRec) - SizeOf(CustRec.Notes); FileDefinitionBuffer.fileSpec.recLen := CustFixedRecSize; FileDefinitionBuffer.fileSpec.PageSize := 4096; FileDefinitionBuffer.fileSpec.IndexCount:= 4; FileDefinitionBuffer.fileSpec.FileFlags := VARIABLELENGTH; {Define key specifications, Key 0 by contact number} FileDefinitionBuffer.keyspecArray[0].Position := 1; FileDefinitionBuffer.keyspecArray[0].Length := 4;{4 byte integer} FileDefinitionBuffer.keyspecArray[0].Flags := KFLG_EXTTYPE_KEY + KFLG_MODX; FileDefinitionBuffer.keyspecArray[0].KeyType := AUTOINCREMENT_TYPE; {Key 1, by contact name.} FileDefinitionBuffer.keyspecArray[1].Position := 5; FileDefinitionBuffer.keyspecArray[1].Length := 30; FileDefinitionBuffer.keyspecArray[1].Flags := KF LG_EXTTYPE_KEY +KFLG_MODX + KFLG_DUP; FileDefinitionBuffer.keyspecArray[1].KeyType := STRING_TYPE; {Key 2, by company name.} FileDefinitionBuffer.keyspecArray[2].Position := 35; FileDefinitionBuffer.keyspecArray[2].Length := 60; FileDefinitionBuffer.keyspecArray[2].Flags := KF LG_EXTTYPE_KEY + KFLG_MODX + KFLG_DUP; FileDefinitionBuffer.keyspecArray[2].KeyType := STRING_TYPE; {Key 3 by sales representative, by next contact date.} FileDefinitionBuffer.keyspecArray[3].Position := 220; FileDefinitionBuffer.keyspecArray[3].Length := 4; FileDefinitionBuffer.keyspecArray[3].Flags := KFLG_EXTTY PE_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; {path and file name of file to create} FilebufLen := sizeof(FileDefinitionBuffer); KeyNum := 0; FillChar(CustPosBlock, SizeOf(CustPosBlock), #0); Result := BTRV(B_CREATE, //OpCode 14 CustPosBLock, //Position Block (the "cursor" or "handle") FileDefinitionBuffer, // Definition of new file FileBufLen, //Length of the definition CustFileLocation[1], //Path and file name keyNum); //0 (zero) means Overwrite any existing file end; {CreateCustomerFile}
BTI_SINT CreateCustomerFile(LPCTSTR szCustomerFileName) { Customer_Record_Type CustRec; // User defined record structure char CustPosBlock[POS_BLOCK_SIZE]; //"Cursor" into customer file char CustFileLocation[255]; size_t CustFixedRecSize; FileDescriptionType FileDefBuf; // Structure type for creating a file BTI_WORD FilebufLen; char KeyNum; // 1 byte signed int BTI_SINT iStatus; /* calculate the size of just thge fixed portion of the record: */ CustFixedRecSize = sizeof(CustRec) - sizeof(CustRec.Notes); FileDefBuf.RecLen = CustFixedRecSize; FileDefBuf.PageSize = 4096; FileDefBuf.IndxCnt = 4; FileDefBuf.DupPointers = 4; FileDefBuf.FileFlags = VAR_RECS | BALANCED_KEYS; /* DEFINE KEY SPECIFICATIONS KEY 0 - BY CONTACT NUMBER */ FileDefBuf.KeyBuf[0].KeyPos = 1; FileDefBuf.KeyBuf[0].KeyLen = 4; FileDefBuf.KeyBuf[0].KeyFlags = EXTTYPE_KEY | MOD; FileDefBuf.KeyBuf[0].KeyType = AUTOINCREMENT_TYPE; /* KEY 1 - BY CONTACT NAME */ FileDefBuf.KeyBuf[1].KeyPos = 5; FileDefBuf.KeyBuf[1].KeyLen = 30; FileDefBuf.KeyBuf[1].KeyFlags = EXTTYPE_KEY | DUP | MOD ; FileDefBuf.KeyBuf[1].KeyType = STRING_TYPE; /* KEY 2 - BY COMPANY NAME */ FileDefBuf.KeyBuf[2].KeyPos = 35; FileDefBuf.KeyBuf[2].KeyLen = 60; FileDefBuf.KeyBuf[2].KeyFlags = EXTTYPE_KEY | DUP | MOD; FileDefBuf.KeyBuf[2].KeyType = STRING_TYPE; /* KEY 3 - BY SALES REP BY NEXT CONTACT DATE */ 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; // Overwrite trans strcpy(CustFileLocation, szCustomerFileName); iStatus = BTRV(B_CREATE, CustPosBlock, &FileDefBuf, &FilebufLen, CustFileLocation, KeyNum); return(iStatus); } //CreateCustomerFile()
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
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 byte unsigned ContactNumber As typ_byte4 '4 byte unsigned OrderDateAs DateType OrderTotal As typ_byte4 '4 byte 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 {The following are the Order table variables.} 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 Anything you want... 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}
struct CustRec { anything you want... } //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
The Insert (2) operation inserts a record into a file. Before you can make a call to this API:
You can insert a row by calling BINSERT with the row to be inserted in the data buffer. For specific information about this API, refer to the API Programmer's Reference. The following sample code and sample structures illustrate how to perform the Insert operation in Visual Basic and Delphi.
The following sample code illustrates how to insert a record using the Insert operation.
FillCustBufFromCustomerEdit InsertCustomerRecord 'BtrCallModule Procedure 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) `see this function in the Sample Structures (Inserting Records) Sample 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 {Calculate the total size of variable-length record} CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) + Length(CustRec.Notes); KeyNum := -1; {specify "No Currency Change" during insert} FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); {not needed going in} Result := BTRV(B_INSERT, //OpCode 2 CustPosBLock, //Already opened position block CustRec, //record to be inserted CustBufLen, //Length of new record CustKeyBuffer[1], //not needed for NCC insert KeyNum); end; {InsertCustomerRecord}
BTI_SINT InsertCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE], Customer_Record_Type CustRec) { BTI_WORD CustBufLen; char KeyNum; //signed byte char CustKeyBuffer[255]; BTI_SINT iStatus; /* Calculate the total size of variable length record : */ CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes); KeyNum = -1; //specify "No Currency Change" during insert memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //not needed going in iStatus = BTRV(B_INSERT, //OpCode 2 CustPosBlock, //Already opened position block &CustRec, //record to be inserted &CustBufLen, //Length of new record CustKeyBuffer, //not needed for NCC insert KeyNum); PrintStatus("B_INSERT: status = %d", iStatus); return(iStatus); } // InsertCustomerRecord()
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
Global Const BINSERT = 2 `The following are Customer table data structures. 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 `The following are Customer file variables. 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
The Update (3) operation changes the information in an existing record. To make this Btrieve call, the file must be open and have physical currency established. If you want to update a record within a transaction, you must retrieve the record within the transaction.
For more detailed information about this API, refer to the API Programmer's Reference. The following sample code and sample structures illustrate how to perform the Update operation in Visual Basic and Delphi.
The following sample code illustrates how to modify a file using the Update operation.
FillCustBufFromCustomerEdit UpdateCustomerRecord 'BtrCallModule Procedure 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 `The following syntax updates a customer record. 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 { Calculate the total size of variable length record : } CustBufLen := SizeOf(CustRec) - SizeOf(CustRec.Notes) + Length(CustRec.Notes); KeyNum := -1; {specify "No Currency Change" during update} FillChar(CustKeyBuffer, SizeOf(CustKeyBuffer), #0); {not needed going in} Result := BTRV(B_UPDATE, //OpCode 3 CustPosBLock, //Already opened position block CustRec, //new record CustBufLen, //Length of new record CustKeyBuffer[1], //not needed for NCC update KeyNum); end; {UpdateCustomerRecord}
BTI_SINT UpdateCustomerRecord(char CustPosBlock[POS_BLOCK_SIZE], Customer_Record_Type CustRec) { BTI_WORD CustBufLen; char KeyNum; //signed byte char CustKeyBuffer[255]; BTI_SINT iStatus; /* Calculate the total size of variable length record : */ CustBufLen = sizeof(CustRec) - sizeof(CustRec.Notes) + strlen(CustRec.Notes); KeyNum = -1; //specify "No Currency Change" during update memset(CustKeyBuffer, sizeof(CustKeyBuffer), 0); //not needed going in iStatus = BTRV(B_UPDATE, //OpCode 3 CustPosBlock, //Already opened position block &CustRec, //record to be inserted &CustBufLen, //Length of new record CustKeyBuffer, //not needed for NCC insert KeyNum); PrintStatus("B_UPDATE: status = %d", iStatus); return(iStatus); } //UpdateCustomerRecord()
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
The Step operations (Step First, Step Next, Step Last, Step Previous) allow you to retrieve a record into the data buffer. The MicroKernel does not use a key path to retrieve the record. For more detailed information about these APIs, refer to the API Programmer's Reference.
The following sample code and sample structures illustrate how to perform the Step operations in Delphi.
Note
You should never depend on the order in which the records are returned. The MicroKernel may move a record within the file at any time. Use Get Operations if you need the records in a specific order.
The following sample code illustrates how to retrieve a record using the Step operations.
{ Get First physical record from file : }
CustBufLen := SizeOf(CustRec); //Maximum
size of the data record
Status := BTRV(B_STEP_FIRST, //OpCode 33
CustPosBLock, //Already
opened position block
CustRec, //Buffer for
record to be returned in
CustBufLen, //Maximum
length to be returned
CustKeyBuffer[1], //Not needed
in Steps
CustKeyNumber); //Not needed
in Steps
{Get Second record in file: (no guaranteed
order) }
CustBufLen := SizeOf(CustRec); //Reset -
previous Step may
have changed it.
Status := BTRV(B_STEP_NEXT, //OpCode 24
CustPosBLock,
CustRec,
CustBufLen,
CustKeyBuffer[1]
CustKeyNumber);
{ Back to the First record : }
CustBufLen := SizeOf(CustRec); //Reset - previous
Step may have changed it.
Status := BTRV(B_STEP_PREV, //OpCode 35
CustPosBLock,
CustRec,
CustBufLen,
CustKeyBuffer[1],
CustKeyNumber);
/* Get First physical record from file : */ CustBufLen = sizeof(CustRec); //Maximum size of the data record iStatus = BTRV(B_STEP_FIRST, //OpCode 33 CustPosBLock, //Already opened position block &CustRec, //Buffer for record to be returned in &CustBufLen, //Maximum length to be returned CustKeyBuffer, //Not needed in Steps KeyNum); //Not needed in Steps /* Get Second record in file: (no guaranteed order) */ CustBufLen = sizeof(CustRec); //Reset - previous Step may have changed it. iStatus = BTRV(B_STEP_NEXT, //OpCode 24 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, KeyNum); /* Back to the First record : */ CustBufLen = sizeof(CustRec); //Reset - previous Step may have changed it. iStatus = BTRV(B_STEP_PREVIOUS, //OpCode 35 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, KeyNum);
These are the sample structures used in the previous code sample for Delphi and C/C++, respectively.
The Get operations allow you to retrieve a record. These operations require the key buffer parameter to specify which row (or rows) to return. For more detailed information about these APIs, refer to the API Programmer's Reference.
The following sample code and sample structures illustrate how to perform some Get operations in Visual Basic and Delphi.
The following sample code illustrates how to retrieve a file using the Get operations.
Sub LoadContactBox(RecPosition As typ_byte4) FormBrowseCustomers.lstContact.Clear GetDirectCustomerRecord 'BtrCallModule Procedure If giStatus = 0 Then `The following syntax writes the contact list box string. FormatContListBoxString If giStatus = 0 Then PosIndex = 0 PosArray(PosIndex) = RecPosition FirstRecPosition = RecPosition End If Else FormBrowseCustomers.lblMsg.Caption = "didn't get record" End If `The following syntax fills the rest of list box. While giStatus = 0 And PosIndex < CustMaxNumRows - 1 GetNextCustomerRecord 'BtrCallModule Procedure If giStatus = 0 Then 'write contact listbox string FormatContListBoxString `The following syntax returns the record position. GetPositionCustomerRecord'BtrCallModule Procedure If giStatus = 0 Then PosIndex = PosIndex + 1 PosArray(PosIndex) = RecPosition `The following syntax configures the pointers to the array of the record `positions. 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 `The following syntax retrieves the direct record by the Record Position. BufLen = Len(CustRecBuf) iKeyBufLen = MaxKeyBufLen iKeyNum = CustKeyBuffer.CurrentKeyNumber `The following syntax places the address in the data buffer. CustRecBuf.Notes = "" 'clear variable length area before retrieve 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 `The following syntax returns the next customer record. 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 `The following syntax returns the record position. 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; {In order by Contact ID} {The following syntax returns the first record from the file using the specified} {sort order.} CustBufLen := SizeOf(CustRec); //Maximum size of the data record Status := BTRV(B_GET_FIRST, //OpCode 12 CustPosBLock, //Already opened position block CustRec, //Buffer for record to be returned in CustBufLen, //Maximum length to be returned CustKeyBuffer, //Returns the key value extracted from the record CustKeyNumber); //Index order to use for retrieval {The following syntax returns the second record in a file in the specified sort} {order.} CustBufLen := SizeOf(CustRec); //Reset - previous Get may have changed it. Status := BTRV(B_GET_NEXT, //OpCode 6 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1], CustKeyNumber); {The following syntax returns the previous record in the file.} CustBufLen := SizeOf(CustRec); //Reset - previous Step may have changed it. Status := BTRV(B_GET_PREV, //OpCode 7 CustPosBLock, CustRec, CustBufLen, CustKeyBuffer[1], CustKeyNumber);
/* Get First logical record from file : */ CustBufLen = sizeof(CustRec); //Maximum size of the data record iStatus = BTRV(B_GET_FIRST, //OpCode 12 CustPosBLock, //Already opened position block &CustRec, //Buffer for record to be returned in &CustBufLen, //Maximum length to be returned CustKeyBuffer, //Returns the key value extracted from the record CustKeyNumber); //Index order to use for retrieval /* Get Second record in file: in order by chosen key */ CustBufLen = sizeof(CustRec); //Reset - previous Get may have changed it. iStatus = BTRV(B_GET_NEXT, //OpCode 6 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, CustKeyNumber); /* Back to the First record : */ CustBufLen = sizeof(CustRec); //Reset - previous Get may have changed it. iStatus = BTRV(B_GET_PREVIOUS, //OpCode 7 CustPosBLock, &CustRec, &CustBufLen, CustKeyBuffer, CustKeyNumber);
These are the sample structures used in the previous code sample for Visual Basic and Delphi, respectively.
Btrieve's chunk operations allow you to read or write portions of variable-length records and BLOBs. The maximum record length is 64 GB; however, the maximum fixed-record length is 64 KB (65,535 bytes). Use chunking when you want to access portions of a record beyond the first 65,535 bytes.
The following sample code illustrates how to handle chunking, binary large objects (BLOBs), and variable-length records.
Private Sub LoadImageFromBtrieve() `The following syntax returns the image stored in Btrieve into the file described `in the output image text box. 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 'gets the record and part of the 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) 'saves the number of bytes read - fixed length of `graphic record.fixed length = 68 bytes on first `chunk of graphic record (GetEqualGraphicRecord `above). sLine = Right(ChunkReadBuffer.ChunkArray, lBytesread) Put #1, , sLine 'write the first chunk to the bmp file. iNumChunksRead = 1 If giStatus = 22 And (BufLen = MaxChunkSize) Then GetPositionGraphicRecord 'you have to have the position of the current record 'before you can do a get chunk Do lNumberOfChunks = 1 lChunkOffset = 0 lChunkAddress = 0 lChunkLength = MaxChunkSize iNumChunksRead = iNumChunksRead + 1 ChunkGetBuffer.RecordAddress = GrphPosition 'H80000000 (Get random chunk) 'H40000000 (Next in record bias) causes use of intrarecord currency. ChunkGetBuffer.AddressMode = ToType4((&H80000000 + &H40000000)) ChunkGetBuffer.NumberOfChunks = ToType4(lNumberOfChunks) ChunkGetBuffer.ChunkOffset = ToType4(lChunkOffset) ChunkGetBuffer.ChunkAddress = ToType4(lChunkAddress) ChunkGetBuffer.ChunkLength = ToType4(lChunkLength) `The previous syntax uses the read buffer. Subsequent get chunks use the entire `buffer because the fixed length of the record was read with the first get chunk `GetEqualGraphicRecord `The following syntax loads the read buffer with the get buffer. CopyMemory ChunkReadBuffer, ChunkGetBuffer, Len (ChunkGetBuffer) GetGraphicChunk If giStatus = 0 Then 'you should get a 103 if you read past the end of the `record 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 {In the following syntax, the key number must be set to -2 for chunking mode.} giStatus = BTRCALL(BGETDIRECT, GrphPosBlock, ChunkReadBuffer, _ BufLen, ByVal sKeyBuffer, iKeyBufLen, -2) End Sub
These are the sample structures used in the previous code sample for 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 ' Graphic Table Variables 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
The following sample code illustrates how to handle segmented indexes.
Sub CreateCustomerFile(CustFileLocation As String) `The following syntax creates the customer file and configures the file `specifications. CustFixedRecSize = Len(CustRecBuf) - Len(CustRecBuf.Notes) FileDefinitionBuffer.RecLen = CustFixedRecSize FileDefinitionBuffer.PageSize = 4096 FileDefinitionBuffer.IndxCnt = 4 FileDefinitionBuffer.FileFlags = VARIABLELENGTH `The following defines key specifications. `Key 0, by contact number. FileDefinitionBuffer.KeyBuf0.KeyPos = 1 FileDefinitionBuffer.KeyBuf0.KeyLen = 4 FileDefinitionBuffer.KeyBuf0.KeyFlags = EXTTYPE + MODIFIABLE FileDefinitionBuffer.KeyBuf0.KeyType = Chr$(BAUTOINC) `Key 1, by contact name. FileDefinitionBuffer.KeyBuf1.KeyPos = 5 FileDefinitionBuffer.KeyBuf1.KeyLen = 30 FileDefinitionBuffer.KeyBuf1.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf1.KeyType = Chr$(BSTRING) `Key 2, by contact name. FileDefinitionBuffer.KeyBuf2.KeyPos = 35 FileDefinitionBuffer.KeyBuf2.KeyLen = 60 FileDefinitionBuffer.KeyBuf2.KeyFlags = EXTTYPE + MODIFIABLE + DUP FileDefinitionBuffer.KeyBuf2.KeyType = Chr$(BSTRING) `Key 3, by sales representative, by next contact date. `This is a segmented key: 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
var CustKeyBuffer : record // Segmented key buffer SalesRep : array[0..2] of Char; NextContact : DateType; //Btrieve Date structure end; CustBufLen: Word; CustKeyNumber: ShortInt; begin CustKeyNumber := 3; //In order by SalesRep/Date CustKeyBuffer.SalesRep := `TO'; //Look for person with initials TO CustKeyBuffer.NextContact.Day := 9; //and NextContact of 9/9/98 CustKeyBuffer.NextContact.Month := 9; CustKeyBuffer.NextContact.Year := 1998; CustBufLen := SizeOf (CustRec); {The following syntax gets the first record from the file using the specified} {sort order (KeyNum) :} Status := BTRV(B_GET_EQUAL, //OpCode 5 CustPosBLock, //Already opened position block CustRec, //Buffer for record to be returned in CustBufLen, //Maximum length to be returned CustKeyBuffer, //Returns the key value extracted from the record CustKeyNumber); //Index order to use for retrieval
struct //Segmented key buffer { char SalesRep[3]; date_type NextContact; //Btrieve Date structure } CustKeyBuffer; BTI_WORD CustBufLen; char CustKeyNumber; CustKeyNumber = 3; //In order by SalesRep/Date CustKeyBuffer.SalesRep = "TO"; //Look for person with initials TO CustKeyBuffer.NextContact.Day = 9; // and NextContact of 9/9/98 CustKeyBuffer.NextContact.Month = 9; CustKeyBuffer.NextContact.Year = 1998; CustBufLen = sizeof(CustRec); /* Get First record from file using specified sort order (KeyNum): */ iStatus = BTRV(B_GET_EQUAL, //OpCode 5 CustPosBLock, //Already opened position block &CustRec, //Buffer for record to be returned in &CustBufLen, //Maximum length to be returned CustKeyBuffer, //Specifies the record to look for CustKeyNumber); //Index order to use for retrieval
|
Chapter contents
Prev topic: Starting a Pervasive PSQL Application
|