UDA Collation Implementation

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