The
mco_seq_join_TYPE()
C function takes a metaiterator in input and produces the result sequence of the same type. (This function is not to be confused with the generated
CLASS_FIELD_join()
API!)The input metaiterator parameter is an "iterator of iterators", i.e. special kind of iterator which provides a way to concatenate multiple sequences by traversing its elements until it reaches the end of the sequence, then it takes the next iterator and iterates through it and so on.
The metaiterator structure has the following form:
typedef struct mco_seq_meta_iterator_t_ { mco_seq_meta_iterator_next_t next; mco_seq_meta_iterator_first_t first; mco_seq_iterator_t iterator; /* iterator initialized by call to next */ void* user_data; /* user context can be provided through this field */ } mco_seq_meta_iterator_t, *mco_seq_meta_iterator_h;The intent of this function is to combine an eXtremeDB record iterator (or cursor) with a sequence iterator since sequences are normal eXtremeDB field types, i.e. a sequence field belongs to the record. For example, consider the following schema:
#define uint4 unsigned<4> #define MAX_SYMBOL_LEN 21 declare database stockdb; class Quote { char<MAX_SYMBOL_LEN> symbol; sequence<date asc> day; sequence<float> price; unique tree<symbol> by_sym; };The sequence price specifies the price for a particular stock Quote. The Quote table has as primary key the index by_sym on field symbol. If one wishes to calculate the total price for all quotes, it would be necessary to iterate through all of the records in the Quote table, calculate the total price for each record using
mco_seq_agg_sum_float()
on the sequence price, and then sum all of these results.The
mco_seq_join_TYPE()
API allows one to construct a metaiterator to perform this operation more efficiently. The metaiterator traverses the Quote table and returns sequence iterators for the price field. Then one can apply themco_seq_agg_sum
() to the result ofmco_seq_join_float()
to get the required total sum.Clearly this function requires some programming to implement the metaiterator. The following sample code demonstrates how to use
mco_seq_join_float()
andmco_seq_agg_max_float()
to obtain the maximum low for all quotes. We will use a more realistic Quote table:#define uint4 unsigned<4> #define MAX_SYMBOL_LEN 21 declare database stockdb; class Quote { char<MAX_SYMBOL_LEN> symbol; sequence<date asc> day; sequence<float> low; sequence<float> high; sequence<float> open; sequence<float> close; sequence<uint4> volume; sequence<char<15>> day_str; unique tree<symbol> by_sym; };The application specific
user_data
is provided to the metaiterator using the following structure:typedef struct quote_low_dsc_t { mco_trans_h trans; // Transaction handle mco_cursor_t quote_cursor; // Cursor for Quote records Quote quote; // Current Quote record } quote_low_dsc;The metaiterator's
first
andnext
functions are implemented as follows:MCO_RET join_low_first(mco_seq_meta_iterator_h meta_iterator) { quote_low_dsc *ud = (quote_low_dsc *)meta_iterator->user_data; MCO_RET rc = mco_cursor_first(ud->trans, &ud->quote_cursor); if (rc != MCO_S_OK) return rc; CHECK(Quote_from_cursor(ud->trans, &ud->quote_cursor, &ud->quote)); CHECK(Quote_low_iterator(&ud->quote, &meta_iterator->iterator)); return MCO_S_OK; } MCO_RET join_low_next(mco_seq_meta_iterator_h meta_iterator) { quote_low_dsc *ud = (quote_low_dsc *)meta_iterator->user_data; MCO_RET rc = mco_cursor_next(ud->trans, &ud->quote_cursor); if (rc != MCO_S_OK) return rc; CHECK(Quote_from_cursor(ud->trans, &ud->quote_cursor, &ud->quote)); CHECK(Quote_low_iterator(&ud->quote, &meta_iterator->iterator)); return MCO_S_OK; }Now the function join() initializes the metaiterator and the Quote cursor, then calls
mco_seq_join_float()
to obtain a sequence of all of the low sequence elements for all Quote records. Then the maximum value is extracted from the result of callingmco_seq_agg_max_float()
with the combined low sequences:void join(mco_db_h db) { mco_seq_iterator_t all_low_it; mco_seq_iterator_t min_low_it; mco_seq_iterator_t count_low_it; mco_seq_meta_iterator_t low_meta_it; MCO_RET rc; float min_low; quote_low_dsc muluser_data; CHECK(mco_trans_start(db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &user_data.trans)); printf("--- JOIN --------------------\n"); /* Initialize the metaiterator */ low_meta_it.next = join_low_next; low_meta_it.first = join_low_first; low_meta_it.user_data = &user_data; /* Initialize the cursor over all Quote objects */ CHECK(Quote_by_sym_index_cursor(user_data.trans, &user_data.quote_cursor)); CHECK(mco_seq_join_float(&all_low_it, &low_meta_it)); /* now all_low_it is a sequence which consists of all low sequences for all Quote objects */ CHECK(mco_seq_agg_max_float(&min_low_it, &all_low_it)); CHECK(mco_seq_next_float(&min_low_it, &min_low)); printf("Maximum of lows: %g\n", min_low); CHECK(mco_trans_commit(user_data.trans)); }