1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2012 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SortSpec parsing.
16 #include <yaz/matchstr.h>
18 #include <yaz/z-core.h>
19 #include <yaz/sortspec.h>
20 #include <yaz/oid_db.h>
21 #include <yaz/wrbuf.h>
23 Z_SortKeySpecList *yaz_sort_spec(ODR out, const char *arg)
25 char sort_string_buf[64], sort_flags[64];
26 Z_SortKeySpecList *sksl = (Z_SortKeySpecList *)
27 odr_malloc(out, sizeof(*sksl));
31 sksl->specs = (Z_SortKeySpec **)odr_malloc(out, sizeof(sksl->specs) * 20);
33 while ((sscanf(arg, "%63s %63s%n", sort_string_buf,
34 sort_flags, &off)) == 2 && off > 1)
37 char *sort_string_sep;
38 char *sort_string = sort_string_buf;
39 Z_SortKeySpec *sks = (Z_SortKeySpec *) odr_malloc(out, sizeof(*sks));
40 Z_SortKey *sk = (Z_SortKey *) odr_malloc(out, sizeof(*sk));
43 sksl->specs[sksl->num_specs++] = sks;
44 sks->sortElement = (Z_SortElement *)
45 odr_malloc(out, sizeof(*sks->sortElement));
46 sks->sortElement->which = Z_SortElement_generic;
47 sks->sortElement->u.generic = sk;
49 if ((sort_string_sep = strchr(sort_string, '=')))
52 sk->which = Z_SortKey_sortAttributes;
53 sk->u.sortAttributes = (Z_SortAttributes *)
54 odr_malloc(out, sizeof(*sk->u.sortAttributes));
55 sk->u.sortAttributes->id = odr_oiddup(out, yaz_oid_attset_bib_1);
56 sk->u.sortAttributes->list = (Z_AttributeList *)
57 odr_malloc(out, sizeof(*sk->u.sortAttributes->list));
58 sk->u.sortAttributes->list->attributes = (Z_AttributeElement **)
60 sizeof(*sk->u.sortAttributes->list->attributes));
61 while (i < 10 && sort_string && sort_string_sep)
63 Z_AttributeElement *el = (Z_AttributeElement *)
64 odr_malloc(out, sizeof(*el));
65 sk->u.sortAttributes->list->attributes[i] = el;
67 el->attributeType = odr_intdup(out, atoi(sort_string));
68 el->which = Z_AttributeValue_numeric;
70 odr_intdup(out, odr_atoi(sort_string_sep + 1));
72 sort_string = strchr(sort_string, ',');
76 sort_string_sep = strchr(sort_string, '=');
79 sk->u.sortAttributes->list->num_attributes = i;
83 sk->which = Z_SortKey_sortField;
84 sk->u.sortField = odr_strdup (out, sort_string);
86 sks->sortRelation = odr_intdup(out, Z_SortKeySpec_ascending);
87 sks->caseSensitivity = odr_intdup(out, Z_SortKeySpec_caseInsensitive);
89 sks->which = Z_SortKeySpec_null;
90 sks->u.null = odr_nullval ();
92 for (i = 0; sort_flags[i]; i++)
94 switch (sort_flags[i])
99 *sks->sortRelation = Z_SortKeySpec_descending;
104 *sks->sortRelation = Z_SortKeySpec_ascending;
108 *sks->caseSensitivity = Z_SortKeySpec_caseInsensitive;
112 *sks->caseSensitivity = Z_SortKeySpec_caseSensitive;
115 sks->which = Z_SortKeySpec_abort;
116 sks->u.abort = odr_nullval();
119 sks->which = Z_SortKeySpec_missingValueData;
120 sks->u.missingValueData = (Odr_oct*)
121 odr_malloc(out, sizeof(Odr_oct));
123 sks->u.missingValueData->len = strlen(sort_flags+i);
124 sks->u.missingValueData->size = sks->u.missingValueData->len;
125 sks->u.missingValueData->buf = (unsigned char*)
126 odr_strdup(out, sort_flags+i);
127 i += strlen(sort_flags+i) - 1;
132 if (!sksl->num_specs)
137 int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w)
140 for (i = 0; i < sksl->num_specs; i++)
142 Z_SortKeySpec *sks = sksl->specs[i];
145 if (sks->sortElement->which != Z_SortElement_generic)
148 sk = sks->sortElement->u.generic;
152 wrbuf_puts(w, " SORTBY ");
153 if (sk->which == Z_SortKey_sortAttributes)
155 else if (sk->which == Z_SortKey_sortField)
156 wrbuf_puts(w, sk->u.sortField);
157 switch (*sks->sortRelation)
159 case Z_SortKeySpec_ascending:
160 wrbuf_puts(w, "/ascending");
162 case Z_SortKeySpec_descending:
163 wrbuf_puts(w, "/descending");
166 switch (*sks->caseSensitivity)
168 case Z_SortKeySpec_caseSensitive:
169 wrbuf_puts(w, "/respectCase");
171 case Z_SortKeySpec_caseInsensitive:
172 wrbuf_puts(w, "/ignoreCase");
177 case Z_SortKeySpec_null:
179 case Z_SortKeySpec_abort:
180 wrbuf_puts(w, "/missingFail");
182 case Z_SortKeySpec_missingValueData:
183 wrbuf_puts(w, "/missingValue=");
184 wrbuf_write(w, (const char *) sks->u.missingValueData->buf,
185 sks->u.missingValueData->len);
192 int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf)
195 for (i = 0; i < sksl->num_specs; i++)
197 Z_SortKeySpec *sks = sksl->specs[i];
200 if (sks->sortElement->which != Z_SortElement_generic)
203 sk = sks->sortElement->u.generic;
205 wrbuf_insert(pqf, 0, "@or ", 4);
207 if (sk->which == Z_SortKey_sortAttributes)
210 for (j = 0; j < sk->u.sortAttributes->list->num_attributes; j++)
212 Z_AttributeElement *el =
213 sk->u.sortAttributes->list->attributes[j];
214 if (el->which != Z_AttributeValue_numeric)
216 wrbuf_printf(pqf, " @attr " ODR_INT_PRINTF "=" ODR_INT_PRINTF,
217 *el->attributeType, *el->value.numeric);
220 else if (sk->which == Z_SortKey_sortField)
222 wrbuf_puts(pqf, " @attr 1=");
223 wrbuf_puts(pqf, sk->u.sortField);
225 switch (*sks->sortRelation)
227 case Z_SortKeySpec_ascending:
228 wrbuf_puts(pqf, " @attr 7=1 ");
230 case Z_SortKeySpec_descending:
231 wrbuf_puts(pqf, " @attr 7=2 ");
234 wrbuf_printf(pqf, "%d", i);
239 int yaz_sort_spec_to_srw_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
242 for (i = 0; i < sksl->num_specs; i++)
244 Z_SortKeySpec *sks = sksl->specs[i];
247 if (sks->sortElement->which != Z_SortElement_generic)
250 sk = sks->sortElement->u.generic;
255 if (sk->which == Z_SortKey_sortAttributes)
257 else if (sk->which == Z_SortKey_sortField)
259 wrbuf_puts(w, sk->u.sortField);
261 wrbuf_puts(w, ",,"); /* path is absent */
262 switch (*sks->sortRelation)
264 case Z_SortKeySpec_ascending:
267 case Z_SortKeySpec_descending:
272 switch (*sks->caseSensitivity)
274 case Z_SortKeySpec_caseSensitive:
277 case Z_SortKeySpec_caseInsensitive:
284 case Z_SortKeySpec_null:
285 wrbuf_puts(w, "highValue");
287 case Z_SortKeySpec_abort:
288 wrbuf_puts(w, "abort");
290 case Z_SortKeySpec_missingValueData:
291 wrbuf_write(w, (const char *) sks->u.missingValueData->buf,
292 sks->u.missingValueData->len);
299 int yaz_sort_spec_to_solr_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
302 for (i = 0; i < sksl->num_specs; i++)
304 Z_SortKeySpec *sks = sksl->specs[i];
307 if (sks->sortElement->which != Z_SortElement_generic)
310 sk = sks->sortElement->u.generic;
315 if (sk->which == Z_SortKey_sortAttributes)
317 else if (sk->which == Z_SortKey_sortField)
319 wrbuf_puts(w, sk->u.sortField);
321 switch (*sks->sortRelation)
323 case Z_SortKeySpec_ascending:
324 wrbuf_puts(w, " asc");
326 case Z_SortKeySpec_descending:
327 wrbuf_puts(w, " desc");
335 int yaz_srw_sortkeys_to_sort_spec(const char *srw_sortkeys, WRBUF w)
337 /* sru sortkey layout: path,schema,ascending,caseSensitive,missingValue */
338 /* see cql_sortby_to_sortkeys of YAZ. */
340 int num_sortspec = 0;
342 NMEM nmem = nmem_create();
345 nmem_strsplit_blank(nmem, srw_sortkeys, &sortspec, &num_sortspec);
346 if (num_sortspec > 0)
348 for (i = 0; i < num_sortspec; i++)
353 int case_sensitive = 0;
354 const char *missing = 0;
355 nmem_strsplitx(nmem, ",", sortspec[i], &arg, &num_arg, 0);
357 if (num_arg > 2 && arg[2][0])
358 ascending = atoi(arg[2]);
359 if (num_arg > 3 && arg[3][0])
360 case_sensitive = atoi(arg[3]);
361 if (num_arg > 4 && arg[4][0])
367 wrbuf_puts(w, arg[0]); /* field */
370 wrbuf_puts(w, ascending ? "a" : "d");
371 wrbuf_puts(w, case_sensitive ? "s" : "i");
374 if (!strcmp(missing, "omit")) {
377 else if (!strcmp(missing, "abort"))
379 else if (!strcmp(missing, "lowValue")) {
382 else if (!strcmp(missing, "highValue")) {
388 wrbuf_puts(w, missing);
397 int yaz_solr_sortkeys_to_sort_spec(const char *solr_sortkeys, WRBUF w)
399 /* Solr sortkey layout: field order[, field order] */
400 /* see cql_sortby_to_sortkeys of YAZ. */
402 int num_sortspec = 0;
404 NMEM nmem = nmem_create();
407 nmem_strsplit(nmem, ",", solr_sortkeys, &sortspec, &num_sortspec);
408 if (num_sortspec > 0)
410 for (i = 0; i < num_sortspec; i++)
415 int case_sensitive = 0;
416 nmem_strsplitx(nmem, " ", sortspec[i], &arg, &num_arg, 0);
421 if (yaz_matchstr(arg[1], "asc") &&
422 yaz_matchstr(arg[1], "desc"))
426 order = tolower(arg[1][0]);
431 wrbuf_puts(w, arg[0]); /* field */
434 wrbuf_putc(w, order);
435 // Always in-sensitive
436 wrbuf_puts(w, case_sensitive ? "s" : "i");
447 * c-file-style: "Stroustrup"
448 * indent-tabs-mode: nil
450 * vim: shiftwidth=4 tabstop=8 expandtab