UDA Object Interfaces

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:

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.cMCO_DD_CHAR or MCO_DD_STRING

val->v.p.p.nMCO_DD_NCHAR_CHAR or MCO_DD_NCHAR_STRING

val->v.p.p.vMCO_DD_BLOB or MCO_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 or val->v.p.p.v) is set to zero, the API just fills out the val.v.p.size, and does not copy the actual value into the buffer.

For structure-based fields (MCO_DD_STRUCT), the API fills out val->v.o, that can be used to further pass it into the mco_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 return MCO_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, use mco_uda_put() on the appropriate null 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);