UDA Object Interfaces
To allocate a new database object call the following API function:
MCO_RET mco_uda_new( mco_trans_h t, unsigned short struct_no, const void * oid, const mco_uda_value_t * initializers, unsigned short initializers_no, /* out */ mco_uda_object_handle_t * obj );To remove an object from the database call the following API function:
MCO_RET mco_uda_delete ( mco_uda_object_handle_t * obj );To cause an object’s indexes to be created before the transaction in which it is instantiated or updated is commited, call the following API function:
MCO_RET mco_uda_checkpoint ( mco_uda_object_handle_t * obj );Put / Get Functions
To assign the field value for an object or structure use:
MCO_RET mco_uda_put( mco_uda_object_handle_p obj, unsigned short field_no, unsigned short index, const mco_uda_value_p value );In order to assign the value, the application sets the field type in
value->type
. The type must correspond to the DDL type:
- for simple types, assign the value (
value->v.u1
,value->v.u2
, etc)- for strings, arrays and blobs, set the appropriate pointer to reference the value (
value->v.p.p.c
,value->v.p.p.n
orvalue->v.p.p.v
) and put the size of the value intov.p.len
- for structure-based fields (
MCO_DD_STRUCT
), usemco_uda_put()
to initialize the descriptorv.o
; Use the descriptor as the first parameter passed tomco_uda_put()
Example
mco_uda_object_handle_t obj; MCO_RET rc; mco_uda_value_t v; ... rc = mco_uda_new( t, Rec_class_no, 0 /* no oid */, 0 /* no init.*/, 0, &obj); v.type = MCO_DD_UINT4; v.v.u4 = 100; rc = mco_uda_put( &obj, uint4_field_no, 0, &v ); v.type = MCO_DD_STRING; v.v.p.len = 5; v.v.p.p.c = "Hello"; rc = mco_uda_put( &obj, string_field_no, 0, &v ); v.type = MCO_DD_BLOB; v.v.p.len = blob_size; v.v.p.p.v = blob_value; rc = mco_uda_put( &obj, blob_field_no, 0, &v );To get the value of an object’s field:
MCO_RET mco_uda_get ( const mco_uda_object_handle_p obj, unsigned short field_no, unsigned short index, /* out */ mco_uda_value_t * val );
Note that for simple types (integers, float, double) the field value is returned in the corresponding
mco_uda_value_t
structure field.
For strings, byte arrays, and blobs, the application needs to allocate a buffer and pass it into the API:
val->v.p.p.c
–MCO_DD_CHAR
orMCO_DD_STRING
val->v.p.p.n
–MCO_DD_NCHAR_CHAR
orMCO_DD_NCHAR_STRING
val->v.p.p.v
–MCO_DD_BLOB
orMCO_DD_REF
In addition,
val->v.p.size
must hold the size of the buffer (in bytes).The function copies the field value into the buffer and also returns the actual number of symbols (bytes for blobs) copied in
val->v.p.len
.It is possible to use the
mco_uda_get()
function to receive the size of the buffer in advance. If the pointer (val->v.p.p.c
,val->v.p.p.n
orval->v.p.p.v
) is set to zero, the API just fills out theval.v.p.size
, and does not copy the actual value into the buffer.For structure-based fields (
MCO_DD_STRUCT
), the API fills outval->v.o
, that can be used to further pass it into themco_uda_get()
and gain access to the structure fields.Example 1
mco_uda_value_t val; val.type = MCO_DD_STRING; val.v.p.p.c = 0; /* figure out the actual size we need to allocate */ mco_uda_get(&obj, my_field_no, 0, &val); val.v.p.p.c = malloc(val.v.p.size); mco_uda_get(&obj, field_no, 0, &val); /* get the value */ ....<whatever processing is necessary> free(val.v.p.p.c); /* free up memory */Example 2 (strings)
mco_uda_value_t val; val.type = MCO_DD_STRING; val.v.p.p.c = 0; mco_uda_get(&obj, my_field_no, 0, &val); val.v.p.size += sizeof(char); val.v.p.p.c = malloc(val.v.p.size ); /* field value size */ ....<processing results> free(val.v.p.p.c); /* */Example 3 (Unicode strings)
mco_uda_value_t val; val.type = MCO_DD_NCHAR_STRING; val.v.p.p.c = 0; mco_uda_get(&obj, my_field_no, 0, &val); val.v.p.size += sizeof(nchar); val.v.p.p.c = malloc(val.v.p.size ); mco_uda_get(&obj, field_no, 0, &val); ....<processing results> free(val.v.p.p.c);
Note that
mco_uda_get()
can returnMCO_S_NULL_VALUE
, in which case nothing is copied to the output parameter.
Note that null indicator fields are just normal fields, identified by:
#define MCO_DICT_FI_NULL_INDICATOR 0x80 /* field is null indicator */Accordingly, to set (or clear) a
nullable
field to (from)null
, usemco_uda_put()
on the appropriatenull
indicator field. Indicator field names (mco_dict_field_info_t.name
) are the name of the base field appended with “_indicator
”. The following code snippet illustrates how to retrieve the field info for an indicator field’s base field:if (field_info.flags & MCO_DICT_FI_NULL_INDICATOR) { char nullable_fldname[MAX_NAME_LEN]; mco_dict_field_info_t nullable_field_info; strcpy(nullable_fldname, field_info.name); nullable_fldname[strlen(nullable_fldname) - strlen("_indicator")] = '\0'; mco_dict_field_name(metadict, dict_no, struct_no, nullable_fldname, &nullable_field_info); ... }
To update blob fields it may be more convenient to call the following append API rather than loading the entire blob and then rewriting it:
MCO_RET mco_uda_blob_append ( /*IN*/ mco_uda_object_handle_p obj, /*IN*/ unsigned short field_no, /*IN*/ const void *value, /*IN*/ uint4 size);Example 4 (Append to blob)
mco_uda_object_handle_t obj; MCO_RET rc; mco_uda_value_t v; void *append_value; uint4 append_size; ... rc = mco_uda_new( t, Rec_class_no, 0 /* no oid */,0 /* no init.*/, 0, &obj); v.type = MCO_DD_BLOB; v.v.p.len = blob_size; v.v.p.p.v = blob_value; rc = mco_uda_put( &obj, blob_field_no, 0, &v ); ... rc = mco_uda_blob_append( &obj, blob_field_no, append_value, append_size);