+
+struct sortKey {
+ int relation;
+ int attrUse;
+};
+
+void resultSetInsertSort (ZServerInfo *zi, ZServerSet *sset,
+ struct sortKey *criteria, int num_criteria,
+ int sysno)
+{
+ struct zset_sort_entry this_entry;
+ struct zset_sort_entry *new_entry = NULL;
+ struct zset_sort_info *sort_info = sset->sort_info;
+ int i, j;
+
+ sortIdx_sysno (zi->sortIdx, sysno);
+ for (i = 0; i<num_criteria; i++)
+ {
+ sortIdx_type (zi->sortIdx, criteria[i].attrUse);
+ sortIdx_read (zi->sortIdx, this_entry.buf[i]);
+ }
+ i = sort_info->num_entries;
+ while (--i >= 0)
+ {
+ int rel = 0;
+ for (j = 0; j<num_criteria; j++)
+ {
+ rel = memcmp (this_entry.buf[j], sort_info->entries[i]->buf[j],
+ SORT_IDX_ENTRYSIZE);
+ if (rel)
+ break;
+ }
+ if (rel)
+ {
+ if (criteria[j].relation == 'D')
+ if (rel > 0)
+ break;
+ if (criteria[j].relation == 'A')
+ if (rel < 0)
+ break;
+ }
+ }
+ j = sort_info->max_entries-1;
+ if (i == j)
+ return;
+ ++i;
+ new_entry = sort_info->entries[j];
+ while (j != i)
+ {
+ sort_info->entries[j] = sort_info->entries[j-1];
+ --j;
+ }
+ sort_info->entries[j] = new_entry;
+ assert (new_entry);
+ if (sort_info->num_entries != sort_info->max_entries)
+ (sort_info->num_entries)++;
+ for (i = 0; i<num_criteria; i++)
+ memcpy (new_entry->buf[i], this_entry.buf[i], SORT_IDX_ENTRYSIZE);
+ new_entry->sysno = sysno;
+}
+
+int resultSetSort (ZServerInfo *zi, bend_sort_rr *rr)
+{
+ ZServerSet *sset;
+ RSET rset;
+ int i, psysno = 0;
+ struct it_key key;
+ struct sortKey sort_criteria[3];
+ int num_criteria;
+ RSFD rfd;
+
+ if (rr->num_input_setnames == 0)
+ {
+ rr->errcode = 208;
+ return 0;
+ }
+ if (rr->num_input_setnames > 1)
+ {
+ rr->errcode = 230;
+ return 0;
+ }
+ sset = resultSetGet (zi, rr->input_setnames[0]);
+ if (!sset)
+ {
+ rr->errcode = 30;
+ rr->errstring = rr->input_setnames[0];
+ return 0;
+ }
+ if (!(rset = sset->rset))
+ {
+ rr->errcode = 30;
+ rr->errstring = rr->input_setnames[0];
+ return 0;
+ }
+ num_criteria = rr->sort_sequence->num_specs;
+ if (num_criteria > 3)
+ num_criteria = 3;
+ for (i = 0; i < num_criteria; i++)
+ {
+ Z_SortKeySpec *sks = rr->sort_sequence->specs[i];
+ Z_SortKey *sk;
+
+ if (*sks->sortRelation == Z_SortRelation_ascending)
+ sort_criteria[i].relation = 'A';
+ else if (*sks->sortRelation == Z_SortRelation_descending)
+ sort_criteria[i].relation = 'D';
+ else
+ {
+ rr->errcode = 214;
+ return 0;
+ }
+ if (sks->sortElement->which == Z_SortElement_databaseSpecific)
+ {
+ rr->errcode = 210;
+ return 0;
+ }
+ else if (sks->sortElement->which != Z_SortElement_generic)
+ {
+ rr->errcode = 237;
+ return 0;
+ }
+ sk = sks->sortElement->u.generic;
+ switch (sk->which)
+ {
+ case Z_SortKey_sortField:
+ logf (LOG_DEBUG, "Sort: key %d is of type sortField", i+1);
+ rr->errcode = 207;
+ return 0;
+ case Z_SortKey_elementSpec:
+ logf (LOG_DEBUG, "Sort: key %d is of type elementSpec", i+1);
+ return 0;
+ case Z_SortKey_sortAttributes:
+ logf (LOG_DEBUG, "Sort: key %d is of type sortAttributes", i+1);
+ sort_criteria[i].attrUse =
+ zebra_maps_sort (zi->zebra_maps, sk->u.sortAttributes);
+ logf (LOG_DEBUG, "use value = %d", sort_criteria[i].attrUse);
+ if (sort_criteria[i].attrUse == -1)
+ {
+ rr->errcode = 116;
+ return 0;
+ }
+ if (sortIdx_type (zi->sortIdx, sort_criteria[i].attrUse))
+ {
+ rr->errcode = 207;
+ return 0;
+ }
+ break;
+ }
+ }
+ if (strcmp (rr->output_setname, rr->input_setnames[0]))
+ {
+ rset = rset_dup (rset);
+ sset = resultSetAdd (zi, rr->output_setname, 1, rset);
+ }
+ resultSetSortReset (&sset->sort_info);
+
+ sset->sort_info = xmalloc (sizeof(*sset->sort_info));
+ sset->sort_info->max_entries = 10;
+ sset->sort_info->num_entries = 0;
+ sset->sort_info->entries = xmalloc (sizeof(*sset->sort_info->entries) *
+ sset->sort_info->max_entries);
+ for (i = 0; i<sset->sort_info->max_entries; i++)
+ sset->sort_info->entries[i] =
+ xmalloc (sizeof(*sset->sort_info->entries[i]));
+
+
+ rfd = rset_open (rset, RSETF_READ|RSETF_SORT_SYSNO);
+ while (rset_read (rset, rfd, &key))
+ {
+ if (key.sysno != psysno)
+ {
+ psysno = key.sysno;
+ resultSetInsertSort (zi, sset,
+ sort_criteria, num_criteria, psysno);
+ }
+ }
+ rset_close (rset, rfd);
+
+ rr->errcode = 0;
+ rr->sort_status = Z_SortStatus_success;
+
+ return 0;
+}
+