static int32_t S_find_upper_bound(RangeCompiler *self, SortCache *sort_cache) { RangeQuery *parent = (RangeQuery*)self->parent; Obj *upper_term = parent->upper_term; int32_t retval = I32_MAX; if (upper_term) { int32_t hi_ord = SortCache_Find(sort_cache, upper_term); if (hi_ord < 0) { // The supplied term is lower than all terms in the field. retval = -1; } else { Obj *value = SortCache_Make_Blank(sort_cache); Obj *hi_found = SortCache_Value(sort_cache, hi_ord, value); bool_t exact_match = hi_found == NULL ? false : Obj_Equals(upper_term, (Obj*)hi_found); retval = hi_ord; if (exact_match && !parent->include_upper) { retval--; } DECREF(value); } } return retval; }
static int32_t S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache) { RangeQuery *parent = (RangeQuery*)self->parent; Obj *lower_term = parent->lower_term; int32_t lower_bound = 0; if (lower_term) { int32_t low_ord = SortCache_Find(sort_cache, lower_term); if (low_ord < 0) { // The supplied term is lower than all terms in the field. lower_bound = 0; } else { Obj *value = SortCache_Make_Blank(sort_cache); Obj *low_found = SortCache_Value(sort_cache, low_ord, value); bool_t exact_match = low_found == NULL ? false : Obj_Equals(lower_term, low_found); lower_bound = low_ord; if (!exact_match || !parent->include_lower) { lower_bound++; } DECREF(value); } } return lower_bound; }
void SortColl_collect(SortCollector *self, int32_t doc_id) { SortCollectorIVARS *const ivars = SortColl_IVARS(self); // Add to the total number of hits. ivars->total_hits++; // Collect this hit if it's competitive. if (SI_competitive(ivars, doc_id)) { MatchDoc *const match_doc = ivars->bumped; MatchDocIVARS *const match_doc_ivars = MatchDoc_IVARS(match_doc); match_doc_ivars->doc_id = doc_id + ivars->base; if (ivars->need_score && match_doc_ivars->score == F32_NEGINF) { match_doc_ivars->score = Matcher_Score(ivars->matcher); } // Fetch values so that cross-segment sorting can work. if (ivars->need_values) { VArray *values = match_doc_ivars->values; for (uint32_t i = 0, max = ivars->num_rules; i < max; i++) { SortCache *cache = ivars->sort_caches[i]; Obj *old_val = (Obj*)VA_Delete(values, i); if (cache) { int32_t ord = SortCache_Ordinal(cache, doc_id); Obj *blank = old_val ? old_val : SortCache_Make_Blank(cache); Obj *val = SortCache_Value(cache, ord, blank); if (val) { VA_Store(values, i, (Obj*)val); } else { DECREF(blank); } } } } // Insert the new MatchDoc. ivars->bumped = (MatchDoc*)HitQ_Jostle(ivars->hit_q, (Obj*)match_doc); if (ivars->bumped) { if (ivars->bumped == match_doc) { /* The queue is full, and we have established a threshold for * this segment as to what sort of document is definitely not * acceptable. Turn off AUTO_ACCEPT and start actually * testing whether hits are competitive. */ ivars->bubble_score = match_doc_ivars->score; ivars->bubble_doc = doc_id; ivars->actions = ivars->derived_actions; } // Recycle. MatchDoc_IVARS(ivars->bumped)->score = ivars->need_score ? F32_NEGINF : F32_NAN; } else { // The queue isn't full yet, so create a fresh MatchDoc. VArray *values = ivars->need_values ? VA_new(ivars->num_rules) : NULL; float fake_score = ivars->need_score ? F32_NEGINF : F32_NAN; ivars->bumped = MatchDoc_new(INT32_MAX, fake_score, values); DECREF(values); } } }