version 2003
PA_GetPackedRecord (tNum; packRec) long
Parameter | Type | Description | |
tNum | short | Table number | |
packRec | void * | Buffer to store the record data | |
Function result | long | Buffer size |
Description
The routine PA_GetPackedRecord fills the memory block pointed to by packRec with data that contains the concatenation of all the fields of the current record of the table whose number is passed in tNum, and returns its size. If there is no current record when the call is made, the routine returns 0. If packRec is nil, the routine returns the actual size of the record, so the developer can allocate a buffer of the correct size before filling it.
First, the 4D Plug-in usually calls the routine passing packRec to nil, then allocates the buffer, and finally recalls the routine with the buffer.
NOTE
4th Dimension uses a private data format for concatenating fields into one block. It is impossible for the 4D Plug-in to extract one particular Field from this block. The 4D Plug-in should never modify this data.
4th Dimension takes care of the data from one platform to another, and the 4D Plug-in can transparently get a packed record on a platform and use it on another.
The buffer returned in packRec can be reused with the routine PA_SetPackedRecord.
For example, if the 4D plug-in requires record duplication, this can be accomplished by first making the desired record the current record for the table and calling PA_GetPackedRecord to get a copy of all the record's fields. Once the packed record has been copied, the 4D plug-in should call PA_CreateRecord and then PA_SetPackedRecord to fill out all the fields of the new record. Finally, the 4D plug-in should save the new record by calling PA_SaveRecord and dispose of the buffer.
This method can also be used to export and import records from one database to another provided the source and destination files have an identical table definition. The use of the routines PA_GetPackedRecord and PA_SetPackedRecord however are not restricted to the duplication or export/import of records. PA_SetPackedRecord can be called on existing records in order to insure data synchronization between databases, provided the source and destination files have an identical table definition.
If new records are created, it is up to the 4D plug-in to handle the unity of field(s) if necessary.
If the 4D plug-in sends or receives record data returned by PA_GetPackedRecord over a phone line, a software or hardware protocol should be used, such as XOn/XOff, as record data may contain ASCII codes which interferes with a standard protocol.
Examples
(1) Duplicate the current record.
short DuplicateRecord (short tNum) { long size = 0; char *buffer; // Get the size of the packed record size = PA_GetPackedRecord(tNum, 0L); // Continue only if no error occurred and if there were a current record if( (PA_GetLastError() == eER_NoErr) && (size > 0) ) { // Allocate the buffer buffer = malloc(size); // Fill it if(buffer) { size = PA_GetPackedRecord(tNum, buffer); // Create and fill a new record if(PA_GetLastError() == eER_NoErr) { PA_CreateRecord(tNum); PA_SetPackedRecord(tNum, buffer, size); PA_SaveRecord(tNum); } } } return PA_GetLastError(); }
(2) BLOB and unBLOB a record as routines given to the 4D programer. The documentation of the Plug-in will look like this:
<<
To BLOB the current record of a table, use:
$error:=myplug_BlobRecord(tNum;blob)
where tNum is an integer (the number of the table) and blob is a BLOB in witch you want to store the record. $error is a long integer containing an error code, 0 = no error.
To unBLOB a record previously BLOBed with myplug_BlobRecord, use:
$error:=myplug_UnblobRecord(tNum;blob)
where tNum is an integer (the number of the table) and blob is a valid BLOB containing the record. The Plug-in does not save the record for you.
>>
void PluginMain( long selector, PA_PluginParameters params ) { switch ( selector ) { case kInitPlugin : // enter initialization code here if needed break; case kDeinitPlugin : // enter de-initialization code here if needed break; case kBLOB_RECORD : BlobTheRecord(params); break; case kUNBLOB_RECORD : UnblobTheRecord(params); break; case 3 : // enter code for third command here break; . . . } } // PluginMain // Declared for the 4D Developer as expecting: // - a short (table number), // - a BLOB // - and return a long (error) void BlobTheRecord (PA_PluginParameters params) { long size = 0; char *buffer; short tNum = 0; short err = 0; // Get the table number (first parameter) tNum = PA_GetShortParameter(params, 1); // Get the size of the packed record size = PA_GetPackedRecord(tNum, 0L); // error check err = PA_GetLastError(); if( (!err) && (size > 0) ) { buffer = malloc(size); if(buffer) { size = PA_GetPackedRecord(tNum, buffer); if( (!err) && (size > 0) ) { // The BLOB to fill is the second parameter PA_SetBlobParameter(params, 2, buffer, size); err = PA_GetLastError(); } } } PA_ReturnLong(params, (long) err); } // BlobTheRecord // Declared for the 4D Developer as expecting: // - a short (table number), // - a BLOB // - and return a long (error) void BlobTheRecord (PA_PluginParameters params) { long size = 0; PA_Handle theBlob; char *theBlobPtr; // Get the table number (first parameter) tNum = PA_GetShortParameter(params, 1); // transfer the data. In this case, it is more // simple to just use the handle to the BLOB, // since we do not have to modify it. theBlob = PA_GetBlobHandleParameter(params, 2); if(theBlob) { size = PA_GetHandleSize(theBlob); theBlobPtr = PA_LockHandle(theBlob);// because perhaps 4D does things that may move memory? PA_SetPackedRecord(tNum, theBlobPtr, size); PA_UnlockHandle(theBlob); } PA_ReturnLong(params, (long) PA_GetLastError()); } // BlobTheRecord
See Also
Error Handling
Use PA_GetLastError to see if an error occurred (bad table number, insufficient memory, etc.).