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 |
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.
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);
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); }
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);
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);
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.
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);
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); }
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);
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);