# UDA User Defined Indexes

> ## User Defined Indexes

> User-defined indexes for the eXtremeDB native API are explained in the Indexes and Cursors page. As with native User-defined Functions (`udf`) the UDA API requires that the application supply two compare functions for `tree` indexes and two additional `hash` functions for hash indexes. For `tree` indexes, provide one custom function that compares two objects and one that compares an object to an external key value. For `hash` indexes, provide two pairs of functions: two returning a hash code and two compare functions (if a user-defined tree index is also defined then these compare functions are used for the `hash` index as well).

> These functions must then be registered with the runtime before cursor functions can be called on these indexes by passing a parameter of the following type:

>         typedef struct mco_uda_userdef_funcs_t_
>         {
>             mco_uda_compare_userdef_f         fcomp;
>             mco_uda_compare_extkey_userdef_f  fcomp_ext;
>             mco_uda_hash_userdef_f            fhash;
>             mco_uda_hash_extkey_userdef_f     fhash_ext;
>         } mco_uda_userdef_funcs_t, *mco_uda_userdef_funcs_h;

> The application implements these compare functions with the following function signatures:

>         /* Object - Object */
>         typedef int2(*mco_uda_compare_userdef_f)( mco_uda_object_handle_p obj1,
>                                 unsigned short index1,
>                                 mco_uda_object_handle_p obj2,
>                                 unsigned short index2,
>                                 void *user_context);

>         /* Object - external key(s) */
>         typedef int2(*mco_uda_compare_extkey_userdef_f)( mco_uda_object_handle_p obj,
>                                     unsigned short index,
>                                     mco_uda_value_t *keys,
>                                     uint2 keys_count,
>                                     void *user_context);

> These compare functions must return <0, =, or >0 depending on whether the object value is less than, equal to or greater than the external key value.

> In addition, for hash indexes, two custom functions need be implemented with the following function signatures:

>         /* Hash - Object */
>         typedef uint4 (*mco_uda_hash_userdef_f)( mco_uda_object_handle_p obj,
>                             unsigned short index,
>                             void *user_context);

>         /* Hash – external key(s) */
>         typedef uint4 (*mco_uda_hash_extkey_userdef_f)( mco_uda_value_t *keys,
>                                 uint2 keys_count,
>                                 void *user_context);

> Note that `hash` index compare functions return `0` if and only if two objects (or object and external key) are equal from the index point of view. This is necessary for `hash` index operations because hash codes may be equal yet the objects (keys) are not. When `mco_uda_lookup()` is called with a `hash` index, it will call the user-defined compare function to assure that any matching hash code actually exactly matches the indexed database field value.

> Notice also that the compare functions receive application specific data passed from the caller via the `user_context` parameter.

> In addition to the compare functions, the UDA API requires a `udf` map for the internal implementation of index navigation. This `udf` map must be allocated and passed to the runtime when the `udfs` are registered.

> The following function queries the database dictionary to determine the amount of memory to be allocated for the `udf` map:

>         MCO_RET mco_uda_get_udfmap_size( const mco_metadict_header_t * metadict,
>                             unsigned short dict_no,
>                             /* out */ unsigned int * size);

> Once the compare functions are defined, the `mco_uda_userdef_funcs_t` structure initialized, and the `udf` map allocated and its size determined, use the following API to register the `udfs` with the runtime:

>         MCO_RET mco_uda_register_udf( const mco_metadict_header_t * metadict,
>                         unsigned short dict_no,
>                         unsigned short struct_no,
>                         unsigned short index_no,
>                         mco_userdef_funcs_h udf_map,
>                         mco_uda_userdef_funcs_h udf_entry,
>                         void *user_context);

> The following code snippet demonstrates how to register `udf` compare functions:

>         /* allocate udfmap */
>         mco_uda_get_udfmap_size(metadict, 0, &udf_map_size);

>         udf_map = (mco_userdef_funcs_h) malloc(udf_map_size);

>         /* register user-defined compare & hash functions */
>         udf_entry.fcomp     = cmp_obj_obj;  /* Object – object compare */
>         udf_entry.fcomp_ext = cmp_obj_ext;  /* Object – key compare */
>         udf_entry.fhash     = hash_obj;     /* Hash – object compare */
>         udf_entry.fhash_ext = hash_ext;     /* Hash – key compare */
>         param.fld_no = name_no; /* will pass name_no to compare/hash functions */

>         rc = mco_uda_register_udf( metadict,
>                          0,
>                          Record_no,
>                          tudf_no,
>                          udf_map,
>                         &udf_entry,
>                          (void*) &param);

>         if ( MCO_S_OK != rc)
>         {
>             printf("Error in mco_uda_register_udf() : %s\n", mco_ret_string(rc, 0));
>             exit(0);
>         }

> Note that the user-context parameter `param` is used by the external key compare functions to call `mco_uda_get()` to retrieve the database field value to be compared to the external key value.

> The registration API must be called for all user-defined indexes, before the application makes a call to`mco_db_connect()`.

> Note that for shared-memory databases, the `udf` functions must be registered in each process separately.