Building the Input: Data Records
There is a special list type of lpar used to construct and manipulate data records:
The record is a child record if the parent key string is present. The parent key string is a null-terminated character string that is used to identify the parent record of the child record. The value is the key string value of the parent record. The record is a child record if, and only if, the parent key string is present. The value of the parent key string must not be null or empty.
A record is a list object possessing the following entries:
| • | Key string (mandatory) |
| • | Searchable text (mandatory) |
| • | Record field structure (mandatory) |
| • | Parent key string (optional) |
The key string is a null-terminated character string used to identify the record in record update, delete, or fetch operations. It must be at least one-character in length without counting the terminating null character.
The searchable text must be Unicode UTF-8 encoded text data. It is the data for all fields of the record given as a single concatenated text block.
The field structure defines how the search text block is to be split into fields by defining the length of each field within the searchable text in bytes.
Every data record passed to the DevKit must have the three mandatory entries. If the optional parent key entry is given, it must be populated.
Each record entry is itself an lpar which is a member of the record. Do not use lpar_append_lst to fill a record list! For efficiency, the DevKit expects record entries to be stored in a predefined order. The DevKit has functions for setting record entries that create the entry lpar and insert it in its proper place in the record.
The following segment of the code creates and populates either a standard record or a child record, and then adds it to a list. It assumes that the input records have the structure shown, and that all data fields are null-terminated UTF-8 encoded strings.
typedef unsigned char UCHAR ;
...
{
int srchtxtlen;
int fldlens[2];
int srchtxt[1024];
lpar_t reclst;
lpar_t record;
struct parent_child_rec {
const char *key; /* record key */
int is_parent_record; /* 1 if parent, 0 if child */
/* for parent records. */
const char *first_name;
const char *last_name;
/* for child records. */
const char *parent_key;
const char *street;
const char *city;
} cur_record;
reclst = lpar_create_lst(LPAR_LST_GENERIC);
for ( /* all records */ ) {
/* ... */
if ( cur_record.is_parent_record ) {
/* Get parent record data. */
/* get field lengths and create searchable text block */
fldlens[0] = strlen(cur_record.first_name);
fldlens[1] = strlen(cur_record.middle_name);
strcpy(srchtxt, cur_record.first_name);
strcat(srchtxt, cur_record.last_name);
srchtxtlen = fldlens[0] + fldlens[1];
/* Create the standard record. */
record = lpar_create_record();
lpar_set_record_key(record, cur_record.key);
lpar_set_record_srchtxt(record, srchtxt, srchtxtlen);
lpar_set_record_srchflds(record, fldlens, 2);
} else {
/* Get child record data. */
/* get field lengths and create searchable text block */
fldlens[0] = strlen(cur_record.street);
fldlens[1] = strlen(cur_record.city);
strcpy(srchtxt, cur_record.street);
strcat(srchtxt, cur_record.city);
srchtxtlen = fldlens[0]+fldlens[1] ;
/* Create the child record. */
record = lpar_create_child_record();
lpar_set_record_key(record, cur_record.key);
lpar_set_record_parent_key(record, cur_record.parent_key);
lpar_set_record_srchtxt(record, srchtxt, srchtxtlen);
lpar_set_record_srchflds(record, fldlens, 2);
}
lpar_append_lst(reclst, record);
}
/* ... Pass list of records to a command function ... */
lpar_destroy(reclst);
}
You create a record list and add record objects to it in the same simple way as for other types of lpars. And when you destroy the list, you thereby destroy its elements.
Note that although the searchable text data is in UTF-8, the length values are in bytes, not characters. UTF-8 is a convenient encoding of Unicode data to use in "C" as all of the standard "C" string functions work with UTF-8 data as it has no embedded \0- (null) bytes. But the functions still work in terms of bytes and not characters.
Since the key and searchable text are copied by the lpar_set_record_<entry> functions, the data passed to them is not destroyed by lpar_destroy. If it is dynamically allocated, you must free it explicitly.
Invoking TIBCO Patterns Matching (lkt_dbsearch) shows how to specify which fields to search and which to ignore.