User-defined Field types (FieldCallBack)

FieldCallBack is the method used by the database engine to support field types not natively used by the database. To do this, the application creates fields with their own field types (starting at USER_FIELD). Those fields are automatically registered as callback fields. The application additionally must provide a function on opening/creating the database that knows how to deal with the additional types. This function is the FieldCallBack. The FieldCallBack function must have the following prototype:

                    int far CallBack(DBBLOCK *dblk,int action, int buffersize, 
                    int intarg, void far *ptrarg1, void far *ptrarg2);

Although the DBBLOCK is passed to the callback, it should be used for reading database structures only. The CallBack function is not allowed to make any calls to the database engine. The database engine will use the callback with the following calling sequences:

1. CallBack(dblk, USERTYPE_TOSTRING, buffersize, userfieldtype, userptr, buffer);

This function is used to convert the user defined fields into a string. userfieldtype identifies the field type, userptr is a pointer to the user field in a data record, buffer points to a ram buffer allocated by the Engine to hold the ASCIIZ string, and buffersize is the maximum size of the buffer.

Under no circumstances should the callback copy more than buffersize bytes into the buffer; if the string is too large, it should be truncated. The return value is ignored.

2. CallBack(dblk,USERTYPE_FROMSTRING, userptrbufsize, (int near *)size, buffer, userptr);

This function is used to convert a string into some user defined field type. buffer points to the ASCIIZ string to convert, and userptr points to the buffer to place the converted type. userptrbufsize is the size of the buffer at userptr: if the string cannot be converted, the callback should return DB_SYNTAX. If the callback cannot fit the converted result into the buffer at userptr, the callback should return DB_MEMORY. Otherwise, the function should return the type of the data that was converted, and place the size of the converted type in the int pointed at by size. Under no circumstances should the callback copy more than userptrbufsize bytes into the buffer.

3. CallBack(dblk,USERTYPE_COMPARE, 0, userfieldtype, userptr1, userptr2);

This function is used to compare two user defined fields. userfieldtype is used to identify the field type for both user-defined fields. userptr1 and userptr2 point to the those fields in (perhaps) two different data records. The value returned should be 1 if *userptr1>*userptr2, -1 if *userptr1<*userptr2, and 0 if *userptr1==*userptr2 (just like C's strcmp).

4. CallBack(dblk,USERTYPE_CONTAINS, 0, userfieldtype, userptr, buffer);

This function is used to see if a string is contained in the user type. This is provided in case the user field has some special meaning for the CONTAINS relation (e.g. the user type is a set). The number returned should be 0 if the string at buffer is not contained in userptr, else the returned value should be >0.

A return value of DB_COMPLEX indicates to the database engine that the CallBack does not provide the CONTAINS relation; in this case, the database engine simply uses USERTYPE_TOSTRING to convert the type to a string and does a string search. Note that since the database uses a limited size buffer to convert the string, very large fields should support their own CONTAINS.

5. ROM CallBack.

ROMCallBack is another method of expanding the database, by providing data records that do not physically exist in the file. The ROM method can be applicable to other types of not-saved or calculated records with the following limitations:

                    int far ROMCallBack(DBBLOCK *dblk, int n, char far *dest, 
                    int bufsize, int *sizeread); 

The WorldTime application uses the ROM record feature of the database engine. The callback should fill the buffer up to the requested amount of information, and should return the number of bytes written.