# UDA Functions

> As explained in the introduction, the UDA is a generic API. So the objects are defined by descriptors that can contain any type of object, and the values stored in them are defined by descriptors that can handle any type of data.

> Instances of database classes are defined by the following generic descriptor:

>         typedef struct tag_mco_uda_object_handle_t_
>         {
>             MCO_Hf obj;                /* internal handle */
>             unsigned short struct_no;  /* structure number. It is set by */
>             /* functions that return an object*/
>             /* descriptor (mco_uda_new, mco_uda_get
>             /* etc). */
>         } mco_uda_object_handle_t, * mco_uda_object_handle_p;

> An object descriptor can be received:

> > 1. When a new object is created (see `mco_uda_new()`)

> > 2. From a `cursor`, after positioning the cursor via the `mco_uda_from_cursor()` API

> > 3. For structure-based fields the `mco_uda_get()`/`mco_uda_put()` functions return a handle to the structure. Note that this handle is not a real descriptor and can’t be used in certain object related functions (for instance,`mco_uda_delete()` or `mco_uda_checkpoint()`)

> A structure of the following typedef `mco_uda_value_t` is used to contain values (of any data types) for an object’s fields (see `mco_uda_get()` / `mco_uda_put()`), and external keys (see `mco_uda_lookup()` / `mco_uda_compare()` ).

>         typedef struct tag_mco_uda_value_t_
>         {
>             mco_dict_type_t type; /* type:  MCO_DD_... */
>             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 */
>                 char                   i1;   /* MCO_DD_INT1 */
>                 short                  i2;   /* MCO_DD_INT2 */
>                 int                    i4;   /* MCO_DD_INT4 */
>                 int8                   i8;   /* MCO_DD_INT8 */
>                 float                   f;   /* MCO_DD_FLOAT */
>                 double                  d;   /* MCO_DD_DOUBLE */
>                 mco_uda_object_handle_t o;   /* MCO_DD_STRUCT */
>                 struct
>                 {
>                     unsigned short      size;/* buffer size (in bytes) */
>                     unsigned short      len; /* string length (in characters)
>                     * or blob size (in bytes)*/
>                     union
>                     {
>                         char    * c;  /* a pointer to the buffer with
>                         * MCO_DD_CHAR or MCO_DD_STRING values */
>                         nchar_t * n;  /* a pointer to the buffer with */
>                         * MCO_DD_NCHAR_CHAR or
>                         * MCO_DD_NCHAR_STRING  value */
>                         void    * v;  /* pointer to the buffer to receive
>                         * MCO_DD_BLOB, MCO_DD_REF or
>                         * MCO_DD_OID values */
>                     } p;              /* pointer to the buffer */
>                 } p;
>             } v;
>         } mco_uda_value_t, * mco_uda_value_p;

> In order to use the `union` to assign values via the `mco_uda_put()`, `mco_uda_lookup()` and `mco_uda_compare()` functions, the value of the `type` field has to correspond to the DDL field type. Furthermore:

> - For simple data types (`int`, `float`, `double`), assign the value to either `v.u1` or `v.u2`, etc.
> - For strings, arrays and blobs set the pointer to the appropriate pointer type (`v.p.p.c`, `v.p.p.n` or `v.p.p.v`), and specify the size in bytes in `v.p.len`.
> - For structured fields, `mco_uda_put()` initializes the descriptor `v.o`, which, in turn, is used to set field values for the structure.

> In order to read data out (`mco_uda_get()`):

> - For simple types (integer, float, double) the value is returned in the appropriate field (`v.u1`, `v.u2`, etc.,).
> - For arrays and blobs it is necessary to assign the appropriate type pointer (`v.p.p.c`, `v.p.p.n` or `v.p.p.v`) to the buffer that receives the data first, and specify the size of the data in bytes in `v.p.size`. `mco_uda_get()` copies the value into the buffer (or truncates the output if the buffer is not large enough) and also returns the actual number of bytes received in the `v.p.len`.
> - For structure fields, `mco_uda_get()` first initializes the `v.o` descriptor that will be used to read the structure field values.