UDA Value

A structure of type mco_uda_value_t is required in the UDA data access calls like mco_uda_put() and mco_uda_get(). It is defined as follows in mcouda.h:

     
    typedef struct tag_mco_uda_value_t_ {
        mco_dict_type_t type;
        union {
            unsigned char           u1;   /* MCO_DD_UINT1 */
            unsigned short          u2;   /* MCO_DD_UINT2 */
            unsigned int            u4;   /* MCO_DD_UINT4, MCO_DD_DATE, MCO_DD_TIME */
            uint8                   u8;   /* MCO_DD_UINT8, MCO_DD_AUTOID, MCO_DD_AUTOOID, MCO_DD_DATETIME */
            char                    i1;   /* MCO_DD_INT1 */
            short                   i2;   /* MCO_DD_INT2 */
            int                     i4;   /* MCO_DD_INT4 */
            mco_int8                i8;   /* MCO_DD_INT8 */
            #ifdef MCO_TARGET_FLOAT_SUPPORTED
                float               f;    /* MCO_DD_FLOAT */
                double              d;    /* MCO_DD_DOUBLE */
            #endif
            mco_uda_object_handle_t o;    /* MCO_DD_STRUCT */
            struct {
                unsigned int        size; /* size of a buffer in bytes */
                unsigned int        len;  /* length of a string in characters */
                union {
                    char          * c;    /* char strings: MCO_DD_STRING, MCO_DD_CHAR, MCO_DD_BINARY, MCO_DD_VARBINARY */
                    nchar_t       * n;    /* nchar strings: MCO_DD_NCHAR_STRING, MCO_DD_NCHAR_CHAR */
                    #ifdef MCO_CFG_WCHAR_SUPPORT
                        wchar_t   * w;    /* wchar strings: MCO_DD_WCHAR_STRING, MCO_DD_WIDE_CHAR */
                    #endif
                    void          * v;    /* general pointer : MCO_DD_BLOB, MCO_DD_REF, MCO_DD_OID */
                } p;                      /* pointer to the buffer */
            } p;
        } v;
    } mco_uda_value_t, * mco_uda_value_p;
     

 

So the UDA value has two elements, a type and a value v. The type must be of the following:

MCO_DD_UINT1 An unsigned 1 byte integer
MCO_DD_UINT2 An unsigned 2 byte integer
MCO_DD_UINT4 An unsigned 4 byte integer
MCO_DD_UINT8 An unsigned 8 byte integer
MCO_DD_INT1 A signed 1 byte integer
MCO_DD_INT2 A signed 2 byte integer
MCO_DD_INT4 A signed 4 byte integer
MCO_DD_INT8 A signed 8 byte integer
MCO_DD_FLOAT A float
MCO_DD_DOUBLE A double
MCO_DD_DATE A 4 byte unsigned integer
MCO_DD_TIME A 4 byte unsigned integer
MCO_DD_DATETIME An 8 byte unsigned integer
MCO_DD_CHAR A 1 byte character
MCO_DD_NCHAR_CHAR A 2 byte Unicode character
MCO_DD_WIDE_CHAR A 2 byte Unicode character
MCO_DD_NCHAR_STRING A unicode (2 byte char) string
MCO_DD_WCHAR_STRING A unicode (2 byte char) string
MCO_DD_REF A 4 byte reference to an object's OID or autoid
MCO_DD_AUTOID A 4 byte autoid
MCO_DD_AUTOOID Undefined (for internal use only)
MCO_DD_STRUCT Structure
MCO_DD_BLOB A Binary Large OBject
MCO_DD_OID A user-defined Object ID
MCO_DD_BOOL A 1 byte boolean
MCO_DD_SEQUENCE_UINT1 A sequence of unsigned 1 byte integers
MCO_DD_SEQUENCE_UINT2 A sequence of unsigned 2 byte integers
MCO_DD_SEQUENCE_UINT4 A sequence of unsigned 4 byte integers
MCO_DD_SEQUENCE_UINT8 A sequence of unsigned 8 byte integers
MCO_DD_SEQUENCE_INT1 A sequence of signed 1 byte integers
MCO_DD_SEQUENCE_INT2 A sequence of signed 2 byte integers
MCO_DD_SEQUENCE_INT4 A sequence of signed 4 byte integers
MCO_DD_SEQUENCE_INT8 A sequence of signed 8 byte integers
MCO_DD_SEQUENCE_FLOAT A sequence of floats
MCO_DD_SEQUENCE_DOUBLE A sequence of doubles
MCO_DD_SEQUENCE_CHAR A sequence of char

Setting UDA Value elements for database fields

To prepare a mco_uda_value_t structure val to set a database object's field value with mco_uda_put(), the appropriate elements of val must be set according to the type of the field. The sections below demonstrate how to prepare val for fields of different types.

Simple scalar types

For simple scalar types, such as integer, float, double, date, time, datetime, bool, and autoid, set the appropriate element of val.v. For example:

 
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_1 = 1;
    unsigned short field_2 = 2;
    unsigned short field_3 = 3;
 
    /* Put  simple values */
    val.type = MCO_DD_UINT4; /* Set field's type */
    val.v.u4   = 999;      /* Set appropriate union field */
    mco_uda_put(&rec, field_1, 0, &val);
     
     
    val.type = MCO_DD_FLOAT; /* Set field's type */
    val.v.f   = 999.999;      /* Set appropriate union field */
    mco_uda_put(&rec, field_3, 0, &val);
     
    val.type = MCO_DD_AUTOID; /* Set field's type */
    val.v.u8   = 3;      /* Set appropriate union field */
    mco_uda_put(&rec, field_3, 0, &val);
     
     

String types

For strings, byte arrays and blobs, the application needs to provide a buffer, assign it to the appropriate buffer element and set the size and len elements as demonstrated in the following examples.

For types MCO_DD_CHAR or MCO_DD_STRING set elements val.v.p.p.c and val.v.p.len:

 
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_no = 2;
    unsigned short inner_field_no = 3;
    unsigned short vlength = 3;
    InnerStruct inner; /* a struct defined in the schema */
    char buf[1024];
    char msg[256];
     
    /* Put a vector of chars */
    mco_uda_field_alloc(&rec, field_no, vLength); /* Allocate vector */
    val.type = MCO_DD_CHAR;  /* Set field's type */
    val.v.p.p.c = buf;       /* Set pointer to buffer */
    val.v.p.len = 20;        /* Set string length */
    for (j = 0; j < vLength; ++j) 
    {
        sprintf(buf, "vch-%d:%d", 1, j); /* Put value to buffer */
        mco_uda_put(&rec, field_no, j, &val); /* Put value to object */
    }
     
    /* Put a vector of strings  */
    mco_uda_field_alloc(&inner, inner_field_no, vLength); /* allocate vector */
    val.type = MCO_DD_STRING;
    val.v.p.p.c = msg;
    val.v.p.len = 20;
    for (j = 0; j < vLength; ++j) {
        sprintf(msg, "vstr-%d:%d", 2, j);
        mco_uda_put(&rec, inner_field_no, j, &val);
    }
     

For types MCO_DD_NCHAR_CHAR or MCO_DD_NCHAR_STRING set elements v.p.p.n and val.v.p.len:

 
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_no = 2;
    unsigned short inner_field_no = 3;
    unsigned short vlength = 3;
    InnerStruct inner; /* a struct defined in the schema */
    char buf[1024];
    char msg[256];
     
    /* Put a vector of Unicode chars */
    mco_uda_field_alloc(&rec, field_no, vLength); /* Allocate vector */
    val.type = MCO_DD_NCHAR;  /* Set field's type */
    val.v.p.p.n = buf;       /* Set pointer to chars */
    val.v.p.len = 20;        /* Set string length */
    for (j = 0; j < vLength; ++j) 
    {
        sprintf(buf, "vch-%d:%d", 1, j); /* Put value to buffer */
        mco_uda_put(&rec, inner_field_no, j, &val); /* Put value to object */
    }
     
    /* Put a vector of strings  */
    mco_uda_field_alloc(&inner, inner_field_no, vLength); /* allocate vector */
    val.type = MCO_DD_NCHAR_STRING;
    val.v.p.p.n = msg;
    val.v.p.len = 20;
    for (j = 0; j < vLength; ++j) {
        sprintf(msg, "vstr-%d:%d", 2, j);
        mco_uda_put(&rec, inner_field_no, j, &val);
    } 

BLOB, OID and REF types

For types MCO_DD_BLOB, MCO_DD_OID or MCO_DD_REF set element val->v.p.p.v and val.v.p.len:

     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_1 = 1;
    unsigned short field_2 = 2;
    unsigned short vlength = 3;
    char buf[1024];
    char msg[256];
     
    /* Put a BLOB value */
    val.type = MCO_DD_BLOB; /* Set field's type */
    val.v.p.p.v = buf;      /* Set pointer to blob data */
    val.v.p.len = 128;      /* Set blob's length */
    mco_uda_put(&rec, field_3, 0, &val);
     

Structure types

For structure-based fields (which must be defined in the database schema) first set val.type to MCO_DD_STRUCT then fill out element val.v.o with the structure element values:

     
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short struct_no = 1;
    unsigned short inner_field_no = 3;
    unsigned short vlength = 3;
    InnerStruct inner; /* a struct defined in the schema */
     
    /* Put a STRUCT value */
    val.type = MCO_DD_STRUCT; /* Set struct type */
    mco_uda_put(&rec, struct_no, 0, &val); /* Initialize the struct handle */
     
    /* Assign inner to the struct handle and set element val.v */
    inner = val.v.o;
    val.type = MCO_DD_UINT4;
    val.v.u4   = 999;
    mco_uda_put(&inner, field_no, 0, &val);
 
     

Retrieving database field values into UDA Value elements

To prepare a mco_uda_value_t structure val to retrieve a database object's field value with mco_uda_get(), the appropriate elements of val must be set according to the type of the field. The sections below demonstrate how to prepare val for fields of different types.

Simple scalar types

For simple scalar types, such as integer, float, double, date, time, datetime, bool, and autoid, set val.type to the appropriate type, then call mco_uda_get() to retrieve the database field value into the appropriate element of val.v. For example:

 
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_1 = 1;
    unsigned short field_2 = 2;
    unsigned short field_3 = 3;
 
    /* Get simple values */
    val.type = MCO_DD_UINT4; /* Set field's type */
    rc = mco_uda_get(&rec, field1, 0, &value);
    printf("\n\tGet Record.u4                  : %d", val.v.u4);
     
    val.type = MCO_DD_FLOAT; /* Set field's type */
    rc = mco_uda_get(&rec, field2, 0, &value);
    printf("\n\tGet Record.u4                  : %d", val.v.f);
     
    val.type = MCO_DD_AUTOID; /* Set field's type */
    rc = mco_uda_get(&rec, field2, 0, &value);
    printf("\n\tGet Record.u4                  : %d", val.v.u8);
     
     

String types

For strings, byte arrays and blobs, the application needs to provide a buffer, assign it to the appropriate buffer element and set the size and len elements as demonstrated in the following examples.

For types MCO_DD_CHAR or MCO_DD_STRING set elements val.v.p.p.c and val.v.p.len:

 
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_no = 2;
    unsigned short inner_field_no = 3;
    unsigned short vlength = 3;
    InnerStruct inner; /* a struct defined in the schema */
    char buf[1024];
    char msg[256];
     
    /* Get a vector of chars */
    mco_uda_field_alloc(&rec, field_no, vLength); /* Allocate vector */
    val.type = MCO_DD_CHAR;  /* Set field's type */
    val.v.p.p.c = buf;       /* Set pointer to buf */
    val.v.p.size = sizeof(buf); /* Set buffer size */
    for (j = 0; j < vLength; ++j) 
    {
        mco_uda_get(&rec, inner_field_no, j, &value); 
        printf("\n\tGet Record.vch[%d]              : '%s', length %d", j, buf, val.v.p.len);
    }
     
    /* Gut a vector of strings  */
    mco_uda_field_alloc(&inner, inner_field_no, vLength); /* allocate vector */
    val.type = MCO_DD_NSTRING;
    val.v.p.size = sizeof(buf);
    for (j = 0; j < vLength; ++j) 
    {
        mco_uda_get(&inner, inner_field_no, j, &val);
        printf("\n\tGet Record.inner.inner_vstr[%d] : '%s', length %d", j, buf, val.v.p.len);
    }
     

The buffer to receive a string field value can also be dynamically allocated. To determine the exact size of the string to be retrieved, the val->v.p.p.c element can be set to 0 to cause mco_uda_get() to return just the size of the string in the specified database field. Then val.p.p.c can be allocated and the string value retrieved by a second mco_uda_get() call. For example:

     
    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 */
    printf("\n\tGet Record.vch[%d]              : '%s', length %d", j, val.v.p.p.c, val.v.p.len);
    free(val.v.p.p.c); /* free up memory */
     

For types MCO_DD_NCHAR_CHAR or MCO_DD_NCHAR_STRING set elements v.p.p.n and val.v.p.size:

 
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_no = 2;
    unsigned short inner_field_no = 3;
    unsigned short inner_vstr_field_no = 4;
    unsigned short vlength = 3;
    InnerStruct inner; /* a struct defined in the schema */
    char buf[1024];
    char msg[256];
     
    /* Get a vector of Unicode chars */
    mco_uda_field_alloc(&rec, field_no, vLength); /* Allocate vector */
    val.type = MCO_DD_NCHAR;  /* Set field's type */
    val.v.p.p.n = buf;       /* Set pointer to buf */
    val.v.p.size = sizeof(buf); /* Set buffer size */
    for (j = 0; j < vLength; ++j) 
    {
        mco_uda_get(&rec, inner_field_no, j, &value); 
        printf("\n\tGet Record.vch[%d]              : '%s', length %d", j, buf, value.v.p.len);
    }
     
    /* Get a vector of strings  */
    mco_uda_field_alloc(&inner, inner_vstr_field_no, vLength); /* allocate vector */
    val.type = MCO_DD_NCHAR_STRING;
    val.v.p.p.n = buf;  /* Set pointer to buf */
    val.v.p.size = sizeof(buf); /* Set buffer size */
    for (j = 0; j < vLength; ++j) {
        mco_uda_get(&inner, inner_field_no, j, &value);
        printf("\n\tGet Record.inner.inner_vstr[%d] : '%s', length %d", j, buf, val.v.p.len);
    } 

BLOB, OID and REF types

For types MCO_DD_BLOB, MCO_DD_OID or MCO_DD_REF set element val->v.p.p.v and val.v.p.size:

     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short field_1 = 1;
    char buf[1024];
     
    /* Put a BLOB value */
    val.type = MCO_DD_BLOB; /* Set field's type */
    val.v.p.p.v = buf;      /* Set pointer to blob data */
    val.v.p.size = sizeof(buf); /* Set buffer size */
    mco_uda_get(&rec, field_1, 0, &val);
    printf("\n\tGet Record.b value             : length %d", val.v.p.len);
     

Structure types

For structure-based fields (which must be defined in the database schema) first set val.type to MCO_DD_STRUCT then call mco_uda_get() to retrieve the struct field into element val.v.o. Then call mco_uda_get() again for each of the structure element values:

     
    Schema struct definition:
     
    struct InnerStruct
    {
        vector<string> inner_vstr;
        uint4 inner_data;
    };
     
    Application code snippet:
     
    mco_uda_object_handle_t rec;
    mco_uda_value_t val;
    unsigned short struct_no = 1;
    unsigned short field_no = 2;
    unsigned short inner_field_no = 3;
    unsigned short inner_data_field_no = 5;
    InnerStruct inner; /* a struct defined in the schema */
     
    /* Get STRUCT value and get simple value from the inner struct */
    val.type = MCO_DD_STRUCT; /* Set struct type */
    mco_uda_get(&rec, inner_field_no, 0, &val); /* Initialize inner struct handler */
    inner = val.v.o; /* Get inner struct handle */
    val.type = MCO_DD_UINT4;
    mco_uda_get(&inner, inner_data_field_no, 0, &val);
    printf("\n\tGet Record.inner.inner_data    : %d", val.v.u4);