+ if (sks->which == Z_SortKeySpec_missingValueData)
+ {
+ zebra_setError(zh, YAZ_BIB1_UNSUPP_MISSING_DATA_ACTION, 0);
+ return ZEBRA_FAIL;
+ }
+ if (*sks->sortRelation == Z_SortKeySpec_ascending)
+ sort_criteria[i].relation = 'A';
+ else if (*sks->sortRelation == Z_SortKeySpec_descending)
+ sort_criteria[i].relation = 'D';
+ else
+ {
+ zebra_setError(zh, YAZ_BIB1_ILLEGAL_SORT_RELATION, 0);
+ return ZEBRA_FAIL;
+ }
+ if (sks->sortElement->which == Z_SortElement_databaseSpecific)
+ {
+ zebra_setError(zh, YAZ_BIB1_DATABASE_SPECIFIC_SORT_UNSUPP, 0);
+ return ZEBRA_FAIL;
+ }
+ else if (sks->sortElement->which != Z_SortElement_generic)
+ {
+ zebra_setError(zh, YAZ_BIB1_SORT_ILLEGAL_SORT, 0);
+ return ZEBRA_FAIL;
+ }
+ sk = sks->sortElement->u.generic;
+ switch (sk->which)
+ {
+ case Z_SortKey_sortField:
+ yaz_log(log_level_sort, "key %d is of type sortField",
+ i+1);
+ sort_criteria[i].numerical = 0;
+ sort_criteria[i].ord =
+ zebraExplain_lookup_attr_str(zh->reg->zei,
+ zinfo_index_category_sort,
+ -1, sk->u.sortField);
+ if (sks->which != Z_SortKeySpec_null
+ && sort_criteria[i].ord == -1)
+ {
+ zebra_setError(zh,
+ YAZ_BIB1_CANNOT_SORT_ACCORDING_TO_SEQUENCE, 0);
+ return ZEBRA_FAIL;
+ }
+ break;
+ case Z_SortKey_elementSpec:
+ yaz_log(log_level_sort, "key %d is of type elementSpec",
+ i+1);
+ zebra_setError(zh, YAZ_BIB1_CANNOT_SORT_ACCORDING_TO_SEQUENCE, 0);
+ return ZEBRA_FAIL;
+ case Z_SortKey_sortAttributes:
+ yaz_log(log_level_sort, "key %d is of type sortAttributes", i+1);
+ res = zebra_sort_get_ord(zh, sk->u.sortAttributes,
+
+ &sort_criteria[i].ord,
+ &sort_criteria[i].numerical);
+ if (sks->which != Z_SortKeySpec_null && res != ZEBRA_OK)
+ return ZEBRA_FAIL;
+ break;
+ }
+ if (zebraExplain_lookup_ord(zh->reg->zei, sort_criteria[i].ord,
+ &sort_criteria[i].index_type,
+ 0, 0))
+ {
+ zebra_setError(zh, YAZ_BIB1_CANNOT_SORT_ACCORDING_TO_SEQUENCE, 0);
+ return ZEBRA_FAIL;
+ }
+ }
+ /* allocate space for each cmpare buf + one extra for tmp comparison */
+ for (i = 0; i<num_criteria; i++)
+ {
+ cmp_buf[i] = xmalloc(sset->sort_info->max_entries
+ * SORT_IDX_ENTRYSIZE);
+ tmp_cmp_buf[i] = xmalloc(SORT_IDX_ENTRYSIZE);
+ }
+ rfd = rset_open (rset, RSETF_READ);
+ while (rset_read (rfd, &key, &termid))
+ {
+ zint this_sys = key.mem[sysno_mem_index];
+ if (log_level_searchhits)
+ key_logdump_txt(log_level_searchhits, &key, termid->name);
+ kno++;
+ if (this_sys != psysno)
+ {
+ (sset->hits)++;
+ psysno = this_sys;
+ resultSetInsertSort(zh, sset,
+ sort_criteria, num_criteria, psysno, cmp_buf,
+ tmp_cmp_buf);
+ }
+ }
+ rset_close (rfd);
+
+ for (i = 0; i<num_criteria; i++)
+ {
+ xfree(cmp_buf[i]);
+ xfree(tmp_cmp_buf[i]);
+ }
+
+ yaz_log(log_level_sort, ZINT_FORMAT " keys, " ZINT_FORMAT " sysnos, sort",
+ kno, sset->hits);
+ for (i = 0; i < numTerms; i++)
+ yaz_log(log_level_sort, "term=\"%s\" type=%s count=" ZINT_FORMAT,
+ terms[i]->name, terms[i]->flags, terms[i]->rset->hits_count);
+ *sort_status = Z_SortResponse_success;
+ return ZEBRA_OK;
+}
+
+RSET resultSetRef(ZebraHandle zh, const char *resultSetId)
+{
+ ZebraSet s;
+
+ if ((s = resultSetGet (zh, resultSetId)))
+ return s->rset;
+ return NULL;
+}
+
+ZEBRA_RES resultSetRank(ZebraHandle zh, ZebraSet zebraSet,
+ RSET rset, NMEM nmem)
+{
+ struct it_key key;
+ TERMID termid;
+ TERMID *terms;
+ zint kno = 0;
+ int numTerms = 0;
+ int n = 0;
+ int i;
+ ZebraRankClass rank_class;
+ struct zset_sort_info *sort_info;
+ const char *rank_handler_name = res_get_def(zh->res, "rank", "rank-1");
+ size_t sysno_mem_index = 0;
+
+ if (zh->m_staticrank)
+ sysno_mem_index = 1;
+
+ if (!log_level_set)
+ loglevels();
+ sort_info = zebraSet->sort_info;
+ sort_info->num_entries = 0;
+ zebraSet->hits = 0;
+ rset_getterms(rset, 0, 0, &n);
+ terms = (TERMID *) nmem_malloc(nmem, sizeof(*terms)*n);
+ rset_getterms(rset, terms, n, &numTerms);
+
+
+ rank_class = zebraRankLookup(zh, rank_handler_name);
+ if (!rank_class)
+ {
+ yaz_log(YLOG_WARN, "No such rank handler: %s", rank_handler_name);
+ zebra_setError(zh, YAZ_BIB1_UNSUPP_SEARCH, "Cannot find rank handler");
+ return ZEBRA_FAIL;
+ }
+ else
+ {
+ RSFD rfd = rset_open(rset, RSETF_READ);
+ struct rank_control *rc = rank_class->control;
+ int score;
+ zint count = 0;
+
+ void *handle =
+ (*rc->begin) (zh->reg, rank_class->class_handle, rset, nmem,
+ terms, numTerms);
+ zint psysno = 0; /* previous doc id / sys no */
+ zint pstaticrank = 0; /* previous static rank */
+ int stop_flag = 0;
+ while (rset_read(rfd, &key, &termid))