# 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);