To support fields of type
sequence
, three flags are accepted inmco_dict_field_info_t::flags
:#define MCO_DICT_FI_ASC_SEQUENCE 0x100 #define MCO_DICT_FI_DESC_SEQUENCE 0x200 #define MCO_DICT_FI_SEQUENCE 0x400If the field type is defined as
sequence
themco_dict_field()
andmco_dict_field_name()
functions setMCO_DICT_FI_SEQUENCE
for it. If thesequence
is monotonic additionally eitherMCO_DICT_FI_DESC_SEQUENCE
orMCO_DICT_FI_ASC_SEQUENCE
is set. A newmco_uda_seq_values_t
structure allows retrieving and updating sequence elements:typedef struct tag_mco_uda_seq_values_t_ { mco_size_t size; mco_dict_type_t elem_type; uint2 elem_size; /* for MCO_DD_CHAR */ union { mco_uint1 *u1; mco_uint2 *u2; mco_uint4 *u4; mco_uint8 *u8; mco_int1 *i1; mco_int2 *i2; mco_int4 *i4; mco_int8 *i8; #ifdef MCO_TARGET_FLOAT_SUPPORTED float *f; double *d; #endif char *c; } v; } mco_uda_seq_values_t;Here
size
is the number of elements in the structureelem_type
- the sequence element type - which can be one of the following:MCO_DD_UINT1, MCO_DD_UINT2, MCO_DD_UINT4, MCO_DD_UINT8, MCO_DD_INT1, MCO_DD_INT2, MCO_DD_INT4, MCO_DD_INT8, MCO_DD_FLOAT, MCO_DD_DOUBLE or MCO_DD_CHARNote that
elem_size
- the element size - only makes sense for theelem_type == MCO_DD_CHAR.
The
union
elementv
-references arrays of the corresponding types (the type is defined by theelem_type
). The arrays must be allocated and deallocated by the applicationThe function mco_uda_is_sequence() can be called to determine if a field is of type
sequence
:mco_bool mco_uda_is_sequence(mco_dict_type_t type);This function returns
MCO_YES
, if the field is defined as asequence
type (i.e.MCO_DD_SEQUENCE_UINT1
,MCO_DD_SEQUENCE_FLOAT
, etc.).
Sequence Functions
The sequence wrapper functions correspond to the function generated by the DDL compiler for sequences, such as:
MCO_RET mco_uda_seq_first(const mco_uda_object_handle_p obj, unsigned short field_no,/*OUT*/ mco_uda_value_t *value); MCO_RET mco_uda_seq_last(const mco_uda_object_handle_p obj, unsigned short field_no,/*OUT*/ mco_uda_value_t *value); MCO_RET mco_uda_seq_append(mco_uda_object_handle_p obj, unsigned short field_no, mco_uda_seq_values_t *values); MCO_RET mco_uda_seq_insert(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_no_t pos, mco_uda_seq_values_t *values); MCO_RET mco_uda_seq_delete(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_no_t from, mco_seq_no_t till); MCO_RET mco_uda_seq_count(const mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_no_t *count); MCO_RET mco_uda_seq_search(const mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h iterator, const mco_uda_value_t *low, mco_seq_boundary_kind_t low_boundary, const mco_uda_value_t *high, mco_seq_boundary_kind_t high_boundary); MCO_RET mco_uda_seq_join(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h result, mco_seq_iterator_h join_with); MCO_RET mco_uda_seq_obj_map(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h dst_iterator, mco_seq_iterator_h map_iterator); MCO_RET mco_uda_seq_subseq(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h iterator, mco_seq_no_t from, mco_seq_no_t till); MCO_RET mco_uda_seq_iterator(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h iterator); MCO_RET mco_uda_seq_project(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h dst, mco_seq_iterator_h src); MCO_RET mco_uda_seq_store(mco_uda_object_handle_p obj, unsigned short field_no, mco_seq_iterator_h src); MCO_RET mco_uda_seq_truncate(const mco_uda_object_handle_p udaobj, unsigned short field_no);Each
mco_uda_seq_<operation>(const mco_uda_object_handle_p obj, unsigned short field_no, ...)
function corresponds to the generated<classname>_<fieldname>_<operation>(<classname> *obj, ...)
. Instead of the type-aware parameters the generalmco_uda_value_t
structure is used.For example if the schema defines a
sequence
field assequence<float>
, thenMCO_RET mco_uda_seq_first(const mco_uda_object_handle_p obj, unsigned short field_no, /*OUT*/ mco_uda_value_t *value);corresponds to
MCO_RET Classname_fieldname_first(Classname *handle, float* val);One small exclusion from the naming convention is the
<classname>_<fieldname>_map(...)
function. It is calledmco_uda_seq_obj_map(...)
. (This is to avoid a conflict with the iterator API below.)Example Usage:
The following code snippet demonstrates how a sequence of values can be appended to a database object:
mco_uda_seq_values_t seqvals; seqvals.elem_type = MCO_DD_UINT4; seqvals.size = seq_size; seqvals.v.u4 = malloc(sizeof(uint4) * seqvals.size); for (i = 0; i < seqvals.size; ++i) { seqvals.v.u4[i] = <...>; } mco_uda_seq_append(&obj, timestamp_no, &seqvals); free(seqvals.v.u4);Iterator API
Overall instead of the elements'
mco_seq_<operation>_<type>(...)
function (such asmco_seq_add_float()
,mco_seq_add_uint1()
, etc.,) the UDA definesmco_uda_seq_<operation>()
. For examplemco_uda_seq_add()
. Note that the value for the<type>
is determined according to the elements' type (if possible). Instead of the type-specific arguments themco_uda_value_t
is used. For example instead of the functionMCO_RET mco_seq_next_uint1(mco_seq_iterator_h iterator, uint1 *val);The UDA APi defines
MCO_RET mco_uda_seq_next(mco_seq_iterator_h iterator, mco_uda_value_t* uda_val);The later function assigns
MCO_DD_UINT1
to theuda_val
and returns the element in theuda_val->v.u1
;Similarly instead of the arrays of the type-specific values the UDA API uses the generic
mco_uda_seq_values_t
structure. For example instead ofMCO_RET mco_seq_get_float(mco_seq_iterator_h input, float *result, mco_size_t *size);use
MCO_RET mco_uda_seq_get(mco_seq_iterator_h input, mco_uda_seq_values_t *values);The
values.size
argument takes the place of thesize
, andvalues.v.f
is the result.Overall, the UDA API consists of over a hundred different functions. The entire list can be found in file
include/mcouda.h.
Example Usage:
The following example code adds the values of two sequences:
mco_seq_iterator_t result, it1, it2, cast_it2; mco_uda_seq_iterator(&obj, field1_no, &it1); // get iterator for object's field field1 mco_uda_seq_iterator(&obj, field2_no, &it2); // get iterator for object's field field2 mco_uda_seq_cast(&cast_it2, it1.elem_type, &it2); // cast elements from field2 to field1's type mco_uda_seq_add(&result, &it1, &cast_it2); // add elements of field1 and field2