The following topics provide information to help you begin developing a Zen application by making direct calls to the Btrieve API. The most common programming tasks are included with sample code and sample structures for Visual Basic and Delphi.
The following flow charts demonstrate which Btrieve operations to use in your applications to insert, update, and delete records. For more detailed information about APIs, see Btrieve API Guide.
Btrieve API Flow Chart
Inserting Records
1 OPEN (0)
2 INSERT (2) to add record (repeat)
3 CLOSE (1) file
4 STOP (25) to release resources
Updating Records
1 OPEN (0)
2 GET EQUAL (5) or some other single-record retrieval operation to find existing record and establish physical currency
3 Modify record
4 UPDATE (3)
5 CLOSE (1)
6 STOP (25) to release resources
Deleting Records
1 OPEN(0)
2 GET EQUAL(5) or some other single-record retrieval operation to find existing record and establish physical currency
3 DELETE(4)
4 CLOSE(1)
5 STOP (25) to release resources
Visual Basic Notes
When you develop Zen applications with Visual Basic, be aware of the following things.
Visual Basic has a known byte alignment issue with user-defined data types. You can also see the Visual Basic topic regarding the Btrieve API for information about this issue and using the PAln32.DLL, the Btrieve Alignment DLL.
Creating a record class for each type of resulting record facilitates data access as shown in the following steps:
1 Create a class named Record.
2 Create a structure defining the layout of your record:
Type Byte2
field1 byte
field2 byte
End Type
Type Rec
Size As Byte2
Name As String*30 'SQL Mask = x30
Salary As String*10 'SQL Mask = zzzzzzz.99
End Type
3 Use iAsciiFlag = 1 and ispacing=0 to read data into an instance of Rec:
Dim instofRec As New Rec
4 Use dot notation to access data:
instofRec.Name="Jeff"
5 Use the record class to handle all the instofRec data manipulation.
Delphi Notes
The following are things to consider when you use Delphi to develop your Zen application.
•Unlike older versions of Pascal, Delphi’s string type (without a length specifier) is dynamic and null terminated. This means that you are not guaranteed to have memory allocated to the string buffer until you assign it a value. This means when using the type string, you need to pad it large enough to hold the expected results. Using the StringOfChar() function, you can assign a blank string large enough to accommodate the expected return value from Btrieve, as illustrated in the following example:
CustKeyBuffer: string; //long string
CustBufLen : word;
//MAX_KEY_LEN is 255 since BTRV() always passes 255 for the Key Length :
CustKeyBuffer := StringOfChar('', MAX_KEY_LEN);
CustBufLen := SizeOf(CustRec);
Status := BTRV(B_GET_FIRST, CustPosBLock, CustRec, CustBufLen, CustKeyBuffer, 0);
{CustKeyBuffer now has the value of the key for}
{the record retrieved}
•Not all of the Delphi samples included in this chapter illustrate error reporting. However, you should check return codes after every call.
•If you try the samples in this chapter, for the Fetches that use the INTERNAL_FORMAT style, the order of the fields in the query must match the order of members you fetch from the data record. When you use the FillGridHeaders() routine, you must stuff the grid in the same order as the query lists the fields.
Starting a Zen Application
When you are developing a Zen application, you must include the appropriate source module for the specific programming interface.
•BTRCONST and BTRAPI32 – source modules needed for Btrieve applications
Adding Zen Source Modules
You need to include either the Btrieve source module into the programming interface in which you are developing your applications.
►To add a Btrieve source module in a Visual Basic project
1 Start a new project in Visual Basic.
2 Add an existing standard module to your project, if appropriate.
3 Add the Zen source modules.
►To add a Btrieve source module in a Delphi project
1 Start a new project in Delphi.
2 Select Options from the Project menu.
3 Click the Directories tab.
4 Insert the location <path>\INTF\DELPHI in the Search Path data field (path refers to where you installed the Zen SDK components).
5 Include source modules in your USES clause.
Btrieve API Code Samples
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, see Btrieve API Guide.
Sample Code
The following sample code illustrates how to create a file using the Create operation.
Visual Basic (Creating a File)
This subroutine creates a file called Orders.
Sub CreateOrdersFile(OrdFileLocation As String)
'The following syntax sets up file specifications.
These are the sample structures used in the previous code sample for Visual Basic, Delphi, and C/C++, respectively.
Visual Basic (Creating a File) – Sample Structure
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
Delphi (Creating a File) – Sample Structure
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}
Note that the alternate collating sequence (ACS) is placed after the entire Keys array for ease of definition. Because Btrieve expects the ACS to immediately follow the last key segment, the ACS must be moved down to that position within the structure.
C/C++ (Creating a File)– Sample Structure
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
Inserting Records
The Insert (2) operation inserts a record into a file. Before you can make a call to this API:
•The file must be open.
•The record to be inserted must be the proper length, and the key values must conform to the keys defined for the file.
You can insert a row by calling BINSERT with the row to be inserted in the data buffer. For specific information about this API, see Btrieve API Guide. The following sample code and sample structures illustrate how to perform the Insert operation in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates how to insert a record using the Insert operation.
'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
Delphi (Inserting Records) – Sample Structure
type
CustomerRecordType = packed record
Anything you want…
end; //CustomerRecordType
C/C++(Inserting Records) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Updating Records
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 information about this API, see Btrieve API Guide. The following sample code and sample structures illustrate how to perform the update operation in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates modifying a file using the update operation.
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, see Btrieve API Guide.
The following sample code and sample structures illustrate how to perform the Step operations in Delphi and C/C++.
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.
Sample Code
The following sample code illustrates how to retrieve a record using the Step operations.
Delphi (Step Operations)
The following code example returns the record in the first physical location in the file.
{ 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);
C/C++ (Step Operations)
/* 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);
Sample Structures
These are the sample structures used in the previous code sample for Delphi and C/C++, respectively.
Delphi (Step Operations) – Sample Structure
type
CustomerRecordType = packed record
Anything you want…
end; //CustomerRecordType
C/C++ (Step Operations) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Performing Get Operations
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, see Btrieve API Guide.
The following sample code and sample structures illustrate how to perform some Get operations in Visual Basic, Delphi, and C/C++.
Sample Code
The following sample code illustrates how to retrieve a file using the Get operations.
Visual Basic (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
{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);
C/C++ (Get Operations)
/* 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);
Sample Structures (Get Operations)
These are the sample structures used in the previous code sample for Visual Basic and Delphi, respectively.
Visual Basic (Get Operations) – Sample Structure
Global Const BGETNEXT = 6
Global Const BGETDIRECT = 23
Global Const BGETPOS = 22
Delphi (Get Operations) – Sample Structure
type
CustomerRecordType = packed record
Anything you want…
end; //CustomerRecordType
C/C++ (Get Operations) – Sample Structure
struct CustRec
{
anything you want…
} //CustRec
Chunking, BLOBs, and Variable-Length Records
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 (65535 bytes). Use chunking when you want to access portions of a record beyond the first 65535 bytes.
Sample Code
The following sample code illustrates how to handle chunking, binary large objects (BLOBs), and variable-length records.