The C interface for sequences has two complementary layers:
classname_fieldname_*() functions that store, edit, search,
and open iterators for sequence fields in database objects. See Generated Sequence Field
Functions.mcoseq.h create and consume mco_seq_iterator_t
pipelines. These functions provide transformations, comparisons, joins, and aggregates. See C Sequence Functions.A sequence function normally initializes a result iterator; it does not materialize the complete result immediately. Values are calculated as the application consumes that iterator. Consequently, errors related to individual values can be reported either when the iterator is constructed or later while it is consumed.
The following schema defines an ordered day sequence and a parallel price sequence:
#define MAX_SYMBOL_LEN 16
class Quote {
char<MAX_SYMBOL_LEN> symbol;
sequence<uint4 asc> day;
sequence<float> price;
unique tree<symbol> by_symbol;
};
The schema compiler generates functions such as Quote_day_append(), Quote_price_append(),
and Quote_price_iterator(). The following transaction fragment creates an object and appends four
values to both sequence fields:
Quote quote;
mco_uint4 days[4] = { 1, 2, 4, 5 };
float prices[4] = { 10.0F, 20.0F, 40.0F, 50.0F };
MCO_RET rc;
rc = Quote_new(trans, "e);
if (rc == MCO_S_OK)
rc = Quote_symbol_put("e, "IBM", (mco_uint2)3);
if (rc == MCO_S_OK)
rc = Quote_day_append("e, days, 4);
if (rc == MCO_S_OK)
rc = Quote_price_append("e, prices, 4);
Applications are responsible for keeping related sequence fields aligned. Appending four days does not automatically
append, remove, or validate four values in another field. An asc or desc modifier does not
sort input. It causes the runtime to reject values that violate the declared order.
Use the generated insert, delete, store, and ordered search
functions for positional updates and range operations. Positions and counts always refer to logical sequence
elements, including when the RLE implementation is active.
Allocate an iterator for every independent traversal and initialize it to zero before passing it to an iterator constructor. A generated field iterator remains associated with its database object and transaction, so consume it before ending that transaction.
mco_seq_iterator_t price_iterator = { 0 };
float price;
MCO_RET rc;
rc = Quote_price_iterator("e, &price_iterator);
while (rc == MCO_S_OK)
{
rc = mco_seq_next_float(&price_iterator, &price);
if (rc == MCO_S_OK)
printf("%g\n", (double)price);
}
if (rc == MCO_S_CURSOR_END)
rc = MCO_S_OK;
mco_seq_next_TYPE() returns one logical value. It returns MCO_S_CURSOR_END after the final
value. The typed traversal interface is representation-neutral: with RLE storage, it expands runs and still returns
one logical value per successful call.
mco_seq_get_TYPE() can consume several values into an application buffer. On input, *size is
the buffer capacity in elements; on success, it is the number of elements written.
Most C sequence functions take a result iterator as their first argument and save references to their input iterators. All iterators in the pipeline must therefore remain alive and unchanged until the result has been completely consumed.
mco_seq_iterator_t price_iterator = { 0 };
mco_seq_iterator_t absolute_iterator = { 0 };
float value;
MCO_RET rc;
rc = Quote_price_iterator("e, &price_iterator);
if (rc == MCO_S_OK)
rc = mco_seq_abs_float(&absolute_iterator, &price_iterator);
while (rc == MCO_S_OK)
{
rc = mco_seq_next_float(&absolute_iterator, &value);
if (rc == MCO_S_OK)
use_value(value);
}
if (rc == MCO_S_CURSOR_END)
rc = MCO_S_OK;
Iterators are stateful consumers. Do not attach one input iterator independently to two pipelines and then expect both
pipelines to see the complete input. Create two equivalent source iterators or use mco_seq_tee() when
two consumers must share one traversal.
To traverse a completed pipeline again, call the reset callback installed by its constructor:
if (absolute_iterator.reset != NULL)
rc = absolute_iterator.reset(&absolute_iterator);
The callback resets the appropriate operand subtree. The lower-level mco_seq_reset_iterator(),
mco_seq_reset_unary_iterator(), and mco_seq_reset_binary_iterator() functions are
primarily building blocks for iterator implementations; applications should not guess which one a pipeline needs.
A nullable sequence field and nullable elements are separate properties. Generated nullable field accessors manage
whether the whole field is NULL. Generated append_nullable and insert_nullable functions,
and the generic get_nullable/unget_nullable functions, use a bitmap for element-level NULL
values. A set bit denotes a NULL element.
When a typed mco_seq_next_TYPE() call reaches a NULL element, it returns
MCO_E_SEQ_NULL_VALUE and advances past that element. The payload returned for a NULL element is
unspecified and must not be read. Use mco_seq_get_nullable_TYPE() when the application needs values
and their NULL bitmap in bulk.
NULL propagation depends on the operation. For example, element-wise operators preserve a NULL result for a NULL operand, while aggregate functions generally ignore NULL values and define separate behavior for empty or all-NULL input. See each function family and the Sequence Error Codes page for operation-specific contracts.
mco_seq_free_buffer()
only for an iterator whose API contract says that the iterator owns such a buffer. This function does not
recursively destroy the operand tree.memcpy and do not modify its callback pointers, operands,
context, buffer flags, or position fields.The plain and RLE implementations export the same common C sequence symbols and are selected for the process as a pair of libraries:
mcoseq and mcoseqmath.mcoseqrle and mcoseqrlemath.Do not link both implementations into one executable as competing providers of the same symbols. When the core is
loaded dynamically through mco_core_load(),
pass MCO_SEQUENCE_LIBRARY_PLAIN or MCO_SEQUENCE_LIBRARY_RLE. The indirect loader accepts
MCO_SEQUENCE_LIBRARY=PLAIN or MCO_SEQUENCE_LIBRARY=RLE. Use
mco_sequence_library_loaded() to query the loader and mco_seq_is_rle() to query the
active sequence implementation.
Typed traversal and the sequence operators hide the physical representation. Applications that call an iterator's
raw next callback and read tiles directly must account for physical RLE runs. See RLE Compression and RLE C Sequence Functions.