SordIter* sord_find(SordModel* sord, const SordQuad pat) { if (!pat[0] && !pat[1] && !pat[2] && !pat[3]) return sord_begin(sord); SearchMode mode; int n_prefix; const SordOrder index_order = sord_best_index(sord, pat, &mode, &n_prefix); SORD_FIND_LOG("Find " TUP_FMT " index=%s mode=%d n_prefix=%d\n", TUP_FMT_ARGS(pat), order_names[index_order], mode, n_prefix); if (pat[0] && pat[1] && pat[2] && pat[3]) mode = SINGLE; // No duplicate quads (Sord is a set) ZixBTree* const db = sord->indices[index_order]; ZixBTreeIter* cur = NULL; zix_btree_lower_bound(db, pat, &cur); if (zix_btree_iter_is_end(cur)) { SORD_FIND_LOG("No match found\n"); zix_btree_iter_free(cur); return NULL; } const SordNode** const key = (const SordNode**)zix_btree_get(cur); if (!key || ( (mode == RANGE || mode == SINGLE) && !sord_quad_match_inline(pat, key) )) { SORD_FIND_LOG("No match found\n"); zix_btree_iter_free(cur); return NULL; } return sord_iter_new(sord, cur, pat, index_order, mode, n_prefix); }
static inline ZixTreeIter* index_lower_bound(ZixTree* db, const SordQuad search_key) { ZixTreeIter* iter = NULL; zix_tree_find(db, (const void*)search_key, &iter); if (!iter) { return NULL; } ZixTreeIter* prev = NULL; while ((prev = zix_tree_iter_prev(iter))) { if (!prev) { return iter; } const SordNode** const key = (const SordNode**)zix_tree_get(prev); if (!sord_quad_match_inline(key, search_key)) { return iter; } iter = prev; } return iter; }
/** Seek forward as necessary until `iter` points at a match. @return true iff iterator reached end of valid range. */ static inline bool sord_iter_seek_match(SordIter* iter) { for (iter->end = true; !zix_btree_iter_is_end(iter->cur); sord_iter_forward(iter)) { const SordNode** const key = (const SordNode**)zix_btree_get(iter->cur); if (sord_quad_match_inline(key, iter->pat)) return (iter->end = false); } return true; }
static SordIter* sord_iter_new(const SordModel* sord, ZixBTreeIter* cur, const SordQuad pat, SordOrder order, SearchMode mode, int n_prefix) { SordIter* iter = (SordIter*)malloc(sizeof(SordIter)); iter->sord = sord; iter->cur = cur; iter->order = order; iter->mode = mode; iter->n_prefix = n_prefix; iter->end = false; iter->skip_graphs = order < GSPO; for (int i = 0; i < TUP_LEN; ++i) { iter->pat[i] = pat[i]; } switch (iter->mode) { case ALL: case SINGLE: case RANGE: assert( sord_quad_match_inline((const SordNode**)zix_btree_get(iter->cur), iter->pat)); break; case FILTER_RANGE: sord_iter_seek_match_range(iter); break; case FILTER_ALL: sord_iter_seek_match(iter); break; } #ifdef SORD_DEBUG_ITER SordQuad value; sord_iter_get(iter, value); SORD_ITER_LOG("New %p pat=" TUP_FMT " cur=" TUP_FMT " end=%d skip=%d\n", (void*)iter, TUP_FMT_ARGS(pat), TUP_FMT_ARGS(value), iter->end, iter->skip_graphs); #endif ++((SordModel*)sord)->n_iters; return iter; }
/** Seek forward as necessary until `iter` points at a match, or the prefix no longer matches iter->pat. @return true iff iterator reached end of valid range. */ static inline bool sord_iter_seek_match_range(SordIter* iter) { if (iter->end) return true; do { const SordNode** key = (const SordNode**)zix_btree_get(iter->cur); if (sord_quad_match_inline(key, iter->pat)) return false; // Found match for (int i = 0; i < iter->n_prefix; ++i) { const int idx = orderings[iter->order][i]; if (!sord_id_match(key[idx], iter->pat[idx])) { iter->end = true; // Reached end of valid range return true; } } } while (!sord_iter_forward(iter)); return (iter->end = true); // Reached end }
bool sord_quad_match(const SordQuad x, const SordQuad y) { return sord_quad_match_inline(x, y); }