Working with BLOBs

<< Click to Display Table of Contents >>

Navigation:  Application development > Accessing and updating tables >

Working with BLOBs

Previous pageReturn to chapter overviewNext page

Because BLOB fields are variable-sized and can be very large, BDE treats them differently from other fields; they are treated as byte streams. The application developer follows a similar procedure for accessing and updating records containing BLOB fields as with other records.

The following set of BDE functions is designed to work with BLOB fields:

DbiOpenBlob

DbiGetBlob

DbiGetBlobHeading

DbiGetBlobSize

DbiFreeBlob

DbiPutBlob

DbiTruncateBlob

Opening the BLOB

To write to or read from a BLOB, you must open the BLOB first. To open the BLOB, the record buffer must contain a copy of the record to be modified, or an initialized record, if the record is being inserted. The application calls DbiOpenBlob, passing the cursor handle, the pointer to the record buffer, the field number of the BLOB, and the access rights. (If the BLOB is opened in read-write mode, the table must also be opened in read-write mode.) DbiOpenBlob stores the BLOB handle in the record buffer. DbiOpenBlob must be called prior to calling any other BLOB functions.

Standard: It is advisable to lock the record before opening the BLOB in read-write mode. This ensures that another application does not change the record or lock the record, preventing the record from being updated.

SQL: For SQL servers that do not support BLOB handles for random reads and writes, full BLOB support requires uniquely identifiable rows. Most SQL servers limit a single sequential BLOB read to less than the maximum size of a BLOB. In cases with no row uniqueness and without BLOB handles, an entire BLOB might not be available.

Retrieving BLOB data

DbiGetBlob retrieves BLOB data from the specified BLOB. Any portion of the data can be retrieved, starting from the position specified in iOffSet, and extending to the number of bytes specified in iLen. Typically, the application does not know the length of the BLOB, and it makes a series of calls to DbiGetBlob to retrieve the entire BLOB. DbiGetBlob returns the number of bytes read when it completes. The application can tell when it has reached the end of the BLOB when the number of bytes specified in iLen is greater than the number of bytes read.

Alternatively, the application can determine beforehand the size of the BLOB by calling DbiGetBlobSize, and then specifying the actual length of the BLOB in the call to DbiGetBlob. That way, the entire BLOB can be retrieved with one DbiGetBlob call, instead of a series of calls.

Updating a BLOB

DbiPutBlob is the equivalent of DbiPutField for a BLOB. DbiPutBlob is used only to write data into a BLOB. The BLOB must be opened in read-write mode. The application passes a pointer to the block of data to be written. The application specifies the length of data to be written, as well as the offset within the BLOB to begin writing the data. The application can make a series of calls to DbiPutBlob to write the entire BLOB.

Updating or adding a record with a blob

To update or add a record, the application follows these steps:

1.Calls DbiAppendRecord or DbiInsertRecord to add a new record with a BLOB to the table or the application calls DbiModifyRecord to modify an existing record containing a BLOB. The pointer to the record buffer containing the new record is passed with the function.

2.Calls DbiFreeBlob to close the BLOB handle and all resources allocated to the BLOB by DbiOpenBlob. (DbiModifyRecord, DbiInsertRecord or DbiAppendRecord do not automatically release BLOB resources after record modification.)

Note:It is important to free the BLOB after adding or modifying the record. If DbiFreeBlob is called prior to DbiModifyRecord, DbiInsertRecord, or DbiAppendRecord, the changes are lost.
Note:Do not use DbiWriteBlock on tables that contain BLOBs.

This example illustrates BLOB processing:

DBIResult   rslt;

pCHAR       blobBuf;

UINT32      blobSize, bytesRead;

// Read the current record

DbiGetRecord(hCursor, dbiNOLOCK, pRecBuf, NULL);

// Open the BLOB

rslt = DbiOpenBlob(hCursor, pRecBuf, 3, dbiREADWRITE);

if (rslt == DBIERR_NONE)

{

  // Get the size of the BLOB then read it. Note that this

  // example assumes that the BLOB is less than 64k.

  DbiGetBlobSize(hCursor, pRecBuf, 3, &blobSize);

  blobBuf = malloc(blobSize);

  DbiGetBlob(hCursor, pRecBuf, 3, 0, blobSize, (pBYTE) blobBuf, &bytesRead);

  // Free the blob

  DbiFreeBlob(hCursor, pRecBuf, 3);

  // Clean up

  free(blobBuf);

}