Realization principle of 20.1.7.2 Tblobstream
Describes the implementation principle of the Tblobstream object, inevitably involving its private domain, and the following is the definition of a private domain:
Tblobstream = Class (Tstream)
Private
Ffield:tblobfield;
Fdataset:tdataset;
Frecord:pchar;
Fbuffer:pchar;
Ffieldno:integer;
Fopened:boolean;
Fmodified:boolean;
Fposition:longint;
Public
End
Ffield is a database blob domain that is associated with a blob stream, which is used for internal access to BLOB streams. Fdataset is the database that represents Ffield, it can be a ttable part, or it can be a tquery part. Both Frecord and Fbuffer are buffers used internally by the Blob stream to store the data in the record that contains the Ffield, which does not contain BLOB data, Tblobstream uses Frecord as the parameter value of the calling BDE API function. Ffieldno represents the field number of the Blob field, also used for parameter passing of the BDE API, fopened and fmocified are state information, fposition represents the current position of the Blob stream, and the Tblobstream method implementation is described below.
1. Create method and the realization of Destroy method
The main function of the Create method is to establish the connection between the Blobstream stream and the Blob field and initialize some of the private variables. It is implemented as follows:
Constructor Tblobstream.create (Field:tblobfield; Mode:tblobstreammode);
Var
Openmode:dbiopenmode;
Begin
FField: = Field;
Fdataset: = Field.dataset;
Frecord: = Fdataset.activebuffer;
Ffieldno: = Field.fieldno;
If fdataset.state = Dsfilter Then
DBERRORFMT (snofieldaccess, [ffield.displayname]);
If not ffield.fmodified then
Begin
If Mode = Bmread Then
Begin
Fbuffer: = AllocMem (fdataset.recordsize);
Frecord: = Fbuffer;
If not Fdataset.getcurrentrecord (Fbuffer) then Exit;
OpenMode: = dbireadonly;
End Else
Begin
If not (fdataset.state in [DsEdit, Dsinsert]) then Dberror (snotediting);
OpenMode: = Dbireadwrite;
End
Check (Dbiopenblob (Fdataset.handle, Frecord, Ffieldno, OpenMode));
End
fopened: = True;
If Mode = Bmwrite then Truncate;
End
The method first assigns values to Ffield,fdataset,frecord and Ffieldno with the passed-in field parameters. method to allocate memory in the current record size with AllocMem and assign the pointer to the Fbuffer, and assign the recorded value to Fbuffer with the Getcurrentrecord method of the dataset part, but not to include BLOB data.
The Dbiopenblob function used in the method is a BDE API function that opens the BLOB field in the database.
Finally, if the method passed in the mode parameter value is Bmwrite, call truncate the current position pointer after the
Data deletion.
It is not difficult to know the source of this program:
Read and Write Blob field, do not allow BLOB field contains the dataset part has filter, or else generate exception event
To read and write a BLOB field, you must set the dataset to an edit or insert state
If the data in the BLOB field is modified, the DBIOPENBLOB function is not called again when the Blob stream is created, but simply the fopened is set to true so that you can read and write to the same BLOB field with multiple BLOB streams
The Destroy method frees BLOB fields and buffers allocated for Fbuffer, which are implemented as follows:
destructor Tblobstream.destroy;
Begin
If Fopened Then
Begin
If fmodified then ffield.fmodified: = True;
If not ffield.fmodified then
Dbifreeblob (Fdataset.handle, Frecord, Ffieldno);
End
If Fbuffer <> nil then Freemem (Fbuffer, fdataset.recordsize);
If Fmodified Then
Try
ffield.datachanged;
Except
Application.handleexception (Self);
End
End
If the data in the Blob stream is modified, the Ffield fmodified is set to true, and the Blob field is released if the modified of Ffield is false, and temporary memory is freed if the fbuffer is not empty. Finally, depending on the value of the fmodified, the event-handling process of the Ffield is initiated datachanged.
It is easy to see that if a BLOB field is modified, the Blob field is not released, and the change to the BLOB field is committed only to destroy, because the Ffield is bypassed when the BLOB field is read and written, and the BDE API function is called directly. This is important in the application of BDE API programming, that is, be sure to modify the state of the corresponding database parts.