# UDA Collation Implementation

> Collation support in the eXtremeDB core API is explained in section “Character String Collation” in the Object Interfaces page. As with the core collation API, the user-defined collations are registered with the runtime before connecting to the database, then essential sorting logic is implemented in the application-supplied compare functions for `tree` indexes and/or `hash` indexes.

> To register them with UDA however, it is first necessary to extract the desired collations from the meta-dictionary. To facilitate this, the UDA Collation API provides dictionary functions to count and extract collation definitions by name and number, as well as to determine the collation map size.

> Then, as with the core collation API, the helper functions, `mco_uda_collate_get()` and `mco_uda_collate_get_range()`, are provided to facilitate the implementation of the user-defined collation compare functions called by the UDA cursor functions.

> The following sample code snippets demonstrate a normal sequence of UDA operations performed by the main application and a UDA collation compare function.

> Example 1

> Sample schema:

>         class Record
>         {
>             string name;
>             uint4  value;

>             unique tree <name> tstd;
>             unique tree <name collate C1> tcoll;
>             hash <name collate C1> hcoll[100];
>         };

> Sample UDA collation compare functions and main application:

>         int2 coll_cmp(mco_collate_h c1, uint2 len1, mco_collate_h c2, uint2 len2)
>         {
>             mco_uda_value_t val1, val2;
>             char buf1[20], buf2[20];

>             /* get first object's value */
>             val1.type = MCO_DD_STRING;
>             val1.v.p.size = sizeof(buf1);
>             val1.v.p.p.c = buf1;

>             mco_uda_collate_get(c1, &val1);

>             /* get second object's value */
>             val2.type = MCO_DD_STRING;
>             val2.v.p.size = sizeof(buf2);
>             val2.v.p.p.c = buf2;

>             mco_uda_collate_get(c2, &val2);

>             /* compare values */
>             return STR_CMP(buf1, buf2);
>         }

>         uint4 coll_hash(mco_collate_h c, uint2 len)
>         {
>             mco_uda_value_t val;
>             char buf[20];

>             /* get object's value */
>             val.type = MCO_DD_STRING;
>             val.v.p.size = sizeof(buf);
>             val.v.p.p.c = buf;
>             mco_uda_collate_get(c, &val);

>             /* hash value */
>             return strlen(buf);
>         }

>         int main(void)
>         {
>             MCO_RET rc;
>             ...
>             mco_dict_struct_info_t struct_info;
>             mco_dict_collation_info_t coll_info;
>             mco_uda_value_t value;
>             mco_uda_object_handle_t obj;
>             char buf[16];

>             ...

>             /* initialize metadict and register dictionary */

>             mco_metadict_size(1, &metadict_size);
>             metadict = (mco_metadict_header_t *) malloc(metadict_size);
>             mco_metadict_init (metadict, metadict_size, 0);
>             mco_metadict_register(metadict, db_name, udacoll_get_dictionary(), 0);

>             /* get id numbers of ‘Record’, field ‘name’, index ‘tcoll’ */
>             Record_no = get_struct_no("Record");
>             name_no   = get_field_no(Record_no, "name");
>             tcoll_no  = get_index_no("Record", "tcoll");

>             /* get id number of collation ‘C1’ */
>             rc = mco_dict_collation_name(metadict, 0, "C1", &coll_info);

>             if ( MCO_S_OK == rc ) coll_no = coll_info.collation_no;

>             /* allocate collation map */
>             mco_uda_get_collmap_size(metadict, 0, &coll_map_size);

>             coll_map = (mco_collation_funcs_h) malloc(coll_map_size);

>             /* register collation compare & hash functions */
>             rc = mco_uda_register_collation(metadict,
>                                 0,
>                                 coll_no,
>                                  coll_map,
>                                 &coll_cmp,
>                                  &coll_hash);

>             /* open the database */
>             if ( MCO_S_OK == rc )
>             {

>                 /* connect to database */
>                 rc = mco_db_connect(db_name, &db);

>                 if ( MCO_S_OK == rc )
>                 {

>                     /* fill database with records setting field s to fruit names */
>                     rc = mco_trans_start(db, MCO_READ_ONLY,
>                                 MCO_TRANS_FOREGROUND, &t);

>                     if (rc == MCO_S_OK)
>                     {
>                         /* using custom collate tree index iterate through the cursor */
>                         rc = mco_uda_cursor(t, Record_no, tcoll_no, &c);

>                         if (rc == MCO_S_OK)
>                         {
>                             for (rc = mco_cursor_first(t, &c);
>                             MCO_S_OK == rc;
>                             rc = mco_cursor_next(t, &c))
>                             {
>                                 mco_uda_from_cursor(t, &c, &obj);
>                                 value.type = MCO_DD_STRING;
>                                 value.v.p.p.c = buf;
>                                 value.v.p.size = 15;
>                                 mco_uda_get(&obj, name_no, 0, &value);
>                                 printf("\n\t%-15s", buf);
>                             }
>                         }
>                     }
>                     rc = mco_trans_commit(t);
>                 }
>             }
>         ...
>         }