PreviousBtrieve API Guide (v9 SP2 (9.5) revision 1) Next

Get Direct/Chunk (23)

Chapter contents

The Get Direct/Chunk operation (B_GET_DIRECT) can retrieve one or more portions, called chunks, of a record. This operation is especially useful on files containing records longer than 65,535 bytes. Such records are too long to be retrieved by the other Get and Step operations, due to restrictions on the length of the Data Buffer parameter. Your application specifies the record from which chunks are to be retrieved by supplying its physical address. The location of a chunk in a record is generally specified by its offset and length.

Parameters

 
Op Code
Pos Block
Data Buf
Data Buf Len
Key Buffer
Key Number
Sent

 

Returned
 

   

Prerequisites
Procedure
  1. Set the Operation Code to 23. Optionally, you can include a lock bias:
    • +100-Single wait record lock.
    • +200-Single no-wait record lock.
    • +300-Multiple wait record lock.
    • +400-Multiple no-wait record lock.
    • For more information about locking, refer to the Pervasive PSQL Programmer's Guide.

  2. Pass the Position Block for the file.
  3. Specify a Data Buffer, as described in Details.
  4. Specify the Data Buffer Length as either the length of the input structure (Table 2-12 or Table 2-13) or the number of bytes you requested for the transactional interface to retrieve, whichever is larger.
  5. Some options for the Get Direct/Chunk operation retrieve chunks to locations other than the Data Buffer. See the Details section for more information about calculating the Data Buffer Length.

  6. Set the Key Number parameter to -2 (0xFE).
Details

Use one of the following chunk descriptors in the Data Buffer:

Random Chunks

The following example shows a record with three randomly spaced chunks (shaded areas): chunk 0 (bytes 0x12 through 0x16), chunk 1 (bytes 0x2A through 0x31), and chunk 2 (bytes 0x41 through 0x4E).

00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
                               
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
                               
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
                               
30
31
32
33
34
35
36
37
38
39
3A
3B
3C
3D
3E
3F
                               
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F

To fetch random chunks, you must create a structure in the Data Buffer, based on the following table.

Table 2-12 Data Buffer for Random Chunk Operations 
Element
Length (in Bytes)
Description
Record Address
4
The 4-byte physical location of the record. You can retrieve this location with a Get Position operation (22).
Random Chunk Descriptor
Subfunction
 4
Type of chunk descriptor; one of the following:
  • 0x80000000 (Direct random chunk descriptor)-Retrieves chunks directly into the Data Buffer. The first chunk is retrieved and stored at offset 0 in the Data Buffer, the second chunk immediately follows the first, and so on.
  • 0x80000001 (Indirect random chunk descriptor)-Retrieves chunks into addresses specified by the Chunk Definitions.
NumChunks
 4
Number of chunks to retrieve. The value must be at least 1. Although no explicit maximum value exists, the chunk descriptor must fit in the Data Buffer, which is limited in size as described in Table 2-11.
Chunk Definition
(Repeat for each chunk)
12
Each Chunk Definition is a 4-byte Chunk Offset, followed by a 4-byte Chunk Length, followed by a 4-byte User Data, described as follows:
  • Chunk Offset-Indicates where the chunk begins as an offset in bytes from the beginning of the record. The minimum value is 0, and the maximum value is the offset of the last byte in the record.
  • Chunk Length-Indicates how many bytes are in the chunk. The minimum value is 0, and the maximum value 65,535; however, the chunk descriptor must fit in the Data Buffer, which is limited in size as described in Table 2-11.
  • User Data-(Used only for indirect descriptors.) A 32-bit pointer to the actual chunk data. The format you should use depends on your operating system.1 The transactional interface ignores this element for direct chunk descriptor subfunctions.
1For 16-bit applications, initialize User Data as a 16-bit offset and a 16-bit segment. User Data cannot address memory beyond the end of its segment. When Chunk Length is added to the offset portion of User Data, the result must be within the segment that User Data defines. By default, the transactional interface does not check for violations of this rule and does not properly handle such violations.

The following table shows a sample Data Buffer for fetching direct random chunks.

Element
Sample Value
Length (in Bytes)
Record Address
0x00000628
4
Subfunction
0x80000000
 4
NumChunks
3
 4
Chunk 0
Chunk Offset
18
 4
Chunk Length
5
 4
User Data
N/A
 4
Chunk 1
Chunk Offset
42
 4
Chunk Length
8
 4
User Data
N/A
 4
Chunk 2
Chunk Offset
65
 4
Chunk Length
14
 4
User Data
N/A
 4

Rectangle Chunk Descriptor Structure

When chunks of the same length are spaced equidistantly throughout a record, you can describe all the chunks to retrieve with a rectangle chunk descriptor. For example, consider the following diagram, which represents offset 0x00 through 0x4F in a record:

00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
0E
0F
                               
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
                               
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
                               
30
31
32
33
34
35
36
37
38
39
3A
3B
3C
3D
3E
3F
                               
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F

The record contains three chunks (shaded areas): chunk 0 (bytes 0x19 through 0x1C), chunk 1 (bytes 0x29 through 0x2C), and chunk 2 (bytes 0x39 through 0x3C). Each chunk is four bytes long, and a total of 16 (0x10) bytes, calculated from the beginning of each chunk, separates the chunks from one another.

You can retrieve all three chunks using a single rectangle descriptor. To fetch rectangle chunks, you must create a structure in the Data Buffer based on the following table.

Table 2-13 Data Buffer for Rectangle Chunks 
Element
Length (in Bytes)
Description
Record Address
4
The 4-byte physical location of the record. You can retrieve this location with a Get Position operation (22).
Rectangle Chunk Descriptor
Subfunction
4
Type of chunk descriptor; one of the following:
  • 0x80000002 (Direct rectangle chunk descriptor)-Retrieves chunks directly into the Data Buffer. The first chunk is retrieved and stored at offset 0 in the Data Buffer, the second chunk immediately follows the first, and so on.
  • 0x80000003 (Indirect rectangle chunk descriptor)-Retrieves chunks into addresses specified by the User Data and Application Distance Between Rows elements.
Number of Rows
4
Number of chunks on which the rectangle chunk descriptor must operate. The minimum value is 1. No explicit maximum value exists.
Offset
4
Offset from the beginning of the record of the first byte to retrieve. The minimum value is 0, and the maximum value is the offset of the last byte in the record. If the record is viewed as a rectangle, this element refers to the offset of the first byte in the first row to be retrieved.
Bytes Per Row
4
Number of bytes to retrieve in each chunk. The minimum value is 0, and the maximum value is 65,535; however, the chunk descriptor must fit in the Data Buffer, which is limited in size as described in Table 2-11.
Distance Between Rows
4
Number of bytes between the beginning of each chunk.
User Data
4
(Used only with indirect descriptors.) A 32-bit pointer to the location into which the transactional interface stores bytes after retrieving them from each row. The format you should use depends on your operating system.1 The transactional interface ignores this element for direct rectangle descriptors; however, you must still allocate the element and initialize it to 0.
Application Distance Between Rows
4
(Used only with indirect rectangle descriptors.) Number of bytes between the beginning of each chunk in the rectangle, as the rectangle is stored in your application's memory, at the address specified by User Data. The transactional interface ignores this element for direct rectangle descriptors; however, you must still allocate the element and initialize it to 0.
1For 16-bit applications, express User Data as a 16-bit offset followed by a 16-bit segment.

When you use an indirect descriptor, be sure that the User Data pointer is initialized so that the chunks retrieved do not overwrite your chunk descriptor. The transactional interface uses the descriptor when copying the returned chunks to the locations that the User Data elements specify. In the event that you overwrite your chunk descriptor, the transactional interface returns Status Code 62.

If the rectangle has the same number of bytes between rows when it is in memory as when it is stored as a record, set Application Distance Between Rows with the same value as Distance Between Rows. However, if the rectangle is arranged in your application's memory with either more or fewer bytes between rows, Application Distance Between Rows allows you to pass that information to the transactional interface.

When you use an indirect rectangle descriptor, the transactional interface uses both the User Data and the Application Distance Between Rows elements to determine the locations in which to store the data after retrieving it. The transactional interface stores data from the first row in offset 0 of User Data. The transactional interface stores the second row's data to an address specified by User Data plus Application Distance Between Rows. The transactional interface stores the third row's data in the address specified by User Data plus (Application Distance Between Rows * 2), and so on.

The following table shows a sample Data Buffer for fetching a direct rectangle chunk.

Element Name
Sample Value
Length (in Bytes)
Record Address
0x00000628
4
Subfunction
0x80000002
4
Number of Rows
3
4
Offset
25
4
Bytes Per Row
4
4
Distance Between Rows
16
4
User Data
0
4
Application Distance Between Rows
0
4

Next-in-Record Subfunction Bias

If you add a bias of 0x40000000 to any of the subfunctions previously listed, the transactional interface calculates the subfunction's Offset element values based on your physical intrarecord currency (that is, your current physical location within the record). When you use the Next-in-Record subfunction, the transactional interface ignores the Offset element in the chunk descriptor.

Result

If the Get Direct/Chunk operation is successful and a direct chunk descriptor is used, the transactional interface returns the chunks one after another in the Data Buffer. If you used an indirect random chunk descriptor, the transactional interface returns the data to the locations that each chunk's User Data element specifies. If you used an indirect rectangle descriptor, the transactional interface returns the data to locations it derives from the User Data and Application Distance Between Rows elements.

The transactional interface also stores the total length of the chunks retrieved in the Data Buffer Length parameter. (The returned value reflects all bytes retrieved, whether they were retrieved and stored directly into the Data Buffer, or the indirect descriptor was used to retrieve and store the bytes elsewhere.) If the operation was partially successful, your application can use the value returned in the Data Buffer Length parameter to determine which chunks could not be retrieved and how many bytes of the final chunk were retrieved.

The Get Direct/Chunk operation is only partially successful if any chunk begins beyond the end of the record (resulting in the transactional interface returning Status Code 103), or if any chunk's offset and length combine to exceed the length of the record. In the latter case, the transactional interface returns Status Code 0 but ceases processing subsequent chunks, if any, in the operation.


Note
Only the Data Buffer Length parameter shows that not all of the chunks were properly retrieved. For this reason, be sure that you always check the value returned in the Data Buffer Length parameter after a Get Direct/Chunk operation.

The following status codes indicate a partially successful Get Direct/Chunk operation. When the transactional interface returns one of these status codes, your application should check the Data Buffer Length parameter's return value to see how much data the transactional interface actually returned.

22

The data buffer parameter is too short.

54

The variable-length portion of the record is corrupt.

103

The chunk offset is too big.

If the transactional interface returns any of the following status codes, it has returned no data.

43

The specified record address is invalid.

58

The compression buffer length is too short.

62

The descriptor is incorrect.

97

The data buffer is too small.

106

The transactional interface cannot perform a Get Next Chunk operation.

Positioning

The Get Direct/Chunk operation has no effect on logical currency. In terms of physical currency, Get Direct/Chunk makes the record from which chunks are retrieved the physical current record.


Chapter contents
Book contents

Prev topic: Get By Percentage (44)
Next topic: Get Direct/Record (23)