1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
7 * \brief Implements ZOOM C query interface.
18 #include <yaz/yaz-util.h>
19 #include <yaz/xmalloc.h>
21 #include <yaz/pquery.h>
24 #include <yaz/sortspec.h>
26 #define SORT_STRATEGY_Z3950 0
27 #define SORT_STRATEGY_TYPE7 1
28 #define SORT_STRATEGY_CQL 2
29 #define SORT_STRATEGY_SRU11 3
30 #define SORT_STRATEGY_EMBED 4
31 #define SORT_STRATEGY_SOLR 5
36 Z_SortKeySpecList *sort_spec;
43 WRBUF sru11_sort_spec;
46 static int generate(ZOOM_query s)
52 wrbuf_rewind(s->full_query);
53 wrbuf_puts(s->full_query, s->query_string);
54 odr_reset(s->odr_query);
56 if (s->sort_spec && (s->sort_strategy == SORT_STRATEGY_SRU11 || s->sort_strategy == SORT_STRATEGY_SOLR))
59 wrbuf_rewind(s->sru11_sort_spec);
61 switch (s->sort_strategy)
63 case SORT_STRATEGY_SRU11:
64 r = yaz_sort_spec_to_srw_sortkeys(s->sort_spec, s->sru11_sort_spec);
66 case SORT_STRATEGY_SOLR:
67 r = yaz_sort_spec_to_solr_sortkeys(s->sort_spec, s->sru11_sort_spec);
73 switch (s->query_type)
75 case Z_Query_type_1: /* RPN */
77 (s->sort_strategy == SORT_STRATEGY_TYPE7 ||
78 s->sort_strategy == SORT_STRATEGY_EMBED))
80 int r = yaz_sort_spec_to_type7(s->sort_spec, s->full_query);
84 s->z_query = (Z_Query *) odr_malloc(s->odr_query,
86 s->z_query->which = Z_Query_type_1;
87 s->z_query->u.type_1 =
88 p_query_rpn(s->odr_query, wrbuf_cstr(s->full_query));
89 if (!s->z_query->u.type_1)
95 case Z_Query_type_104: /* CQL */
97 (s->sort_strategy == SORT_STRATEGY_CQL ||
98 s->sort_strategy == SORT_STRATEGY_EMBED))
100 int r = yaz_sort_spec_to_cql(s->sort_spec, s->full_query);
104 ext = (Z_External *) odr_malloc(s->odr_query, sizeof(*ext));
105 ext->direct_reference = odr_oiddup(s->odr_query,
106 yaz_oid_userinfo_cql);
107 ext->indirect_reference = 0;
109 ext->which = Z_External_CQL;
110 ext->u.cql = odr_strdup(s->odr_query, wrbuf_cstr(s->full_query));
112 s->z_query = (Z_Query *) odr_malloc(s->odr_query, sizeof(*s->z_query));
113 s->z_query->which = Z_Query_type_104;
114 s->z_query->u.type_104 = ext;
122 const char *ZOOM_query_get_sru11(ZOOM_query s)
124 if (wrbuf_len(s->sru11_sort_spec))
125 return wrbuf_cstr(s->sru11_sort_spec);
129 Z_Query *ZOOM_query_get_Z_Query(ZOOM_query s)
134 Z_SortKeySpecList *ZOOM_query_get_sortspec(ZOOM_query s)
136 return s->sort_strategy == SORT_STRATEGY_Z3950 ? s->sort_spec : 0;
139 static void cql2pqf_wrbuf_puts(const char *buf, void *client_data)
141 WRBUF wrbuf = (WRBUF) client_data;
142 wrbuf_puts(wrbuf, buf);
145 const char *ZOOM_query_get_query_string(ZOOM_query s)
147 return wrbuf_cstr(s->full_query);
150 void ZOOM_query_get_hash(ZOOM_query s, WRBUF w)
152 wrbuf_printf(w, "%d;", s->query_type);
154 wrbuf_puts(w, s->query_string);
155 wrbuf_printf(w, ";%d;", s->sort_strategy);
157 yaz_sort_spec_to_type7(s->sort_spec, w);
161 * Returns an xmalloc()d string containing RPN that corresponds to the
162 * CQL passed in. On error, sets the Connection object's error state
163 * and returns a null pointer.
164 * ### We could cache CQL parser and/or transformer in Connection.
166 static char *cql2pqf(ZOOM_connection c, const char *cql)
171 cql_transform_t trans;
174 parser = cql_parser_create();
175 if ((error = cql_parser_string(parser, cql)) != 0) {
176 cql_parser_destroy(parser);
177 ZOOM_set_error(c, ZOOM_ERROR_CQL_PARSE, cql);
181 cqlfile = ZOOM_connection_option_get(c, "cqlfile");
184 ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file");
186 else if ((trans = cql_transform_open_fname(cqlfile)) == 0)
189 sprintf(buf, "can't open CQL transform file '%.200s': %.200s",
190 cqlfile, strerror(errno));
191 ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
195 WRBUF wrbuf_result = wrbuf_alloc();
196 error = cql_transform(trans, cql_parser_result(parser),
197 cql2pqf_wrbuf_puts, wrbuf_result);
201 error = cql_transform_error(trans, &addinfo);
202 sprintf(buf, "%.200s (addinfo=%.200s)",
203 cql_strerror(error), addinfo);
204 ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf);
208 result = xstrdup(wrbuf_cstr(wrbuf_result));
210 cql_transform_close(trans);
211 wrbuf_destroy(wrbuf_result);
213 cql_parser_destroy(parser);
219 ZOOM_query_create(void)
221 ZOOM_query s = (ZOOM_query) xmalloc(sizeof(*s));
226 s->odr_query = odr_createmem(ODR_ENCODE);
227 s->odr_sort_spec = odr_createmem(ODR_ENCODE);
229 s->full_query = wrbuf_alloc();
230 s->sort_strategy = SORT_STRATEGY_Z3950;
231 s->sru11_sort_spec = wrbuf_alloc();
236 ZOOM_query_destroy(ZOOM_query s)
242 if (s->refcount == 0)
244 odr_destroy(s->odr_query);
245 odr_destroy(s->odr_sort_spec);
246 xfree(s->query_string);
247 wrbuf_destroy(s->full_query);
248 wrbuf_destroy(s->sru11_sort_spec);
254 ZOOM_query_addref(ZOOM_query s)
261 ZOOM_query_prefix(ZOOM_query s, const char *str)
263 xfree(s->query_string);
264 s->query_string = xstrdup(str);
265 s->query_type = Z_Query_type_1;
270 ZOOM_query_cql(ZOOM_query s, const char *str)
272 xfree(s->query_string);
273 s->query_string = xstrdup(str);
274 s->query_type = Z_Query_type_104;
279 * Translate the CQL string client-side into RPN which is passed to
280 * the server. This is useful for server's that don't themselves
281 * support CQL, for which ZOOM_query_cql() is useless. `conn' is used
282 * only as a place to stash diagnostics if compilation fails; if this
283 * information is not needed, a null pointer may be used.
286 ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
290 ZOOM_connection freeme = 0;
293 conn = freeme = ZOOM_connection_create(0);
295 rpn = cql2pqf(conn, str);
297 ZOOM_connection_destroy(freeme);
301 ret = ZOOM_query_prefix(s, rpn);
307 * Analogous in every way to ZOOM_query_cql2rpn(), except that there
308 * is no analogous ZOOM_query_ccl() that just sends uninterpreted CCL
309 * to the server, as the YAZ GFS doesn't know how to handle this.
312 ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config,
313 int *ccl_error, const char **error_string,
317 struct ccl_rpn_node *rpn;
318 CCL_bibset bibset = ccl_qual_mk();
321 ccl_qual_buf(bibset, config);
323 rpn = ccl_find_str(bibset, str, ccl_error, error_pos);
326 *error_string = ccl_err_msg(*ccl_error);
331 WRBUF wr = wrbuf_alloc();
334 ret = ZOOM_query_prefix(s, wrbuf_cstr(wr));
337 ccl_qual_rm(&bibset);
342 ZOOM_query_sortby(ZOOM_query s, const char *criteria)
344 return ZOOM_query_sortby2(s, "z3950", criteria);
348 ZOOM_query_sortby2(ZOOM_query s, const char *strategy, const char *criteria)
350 if (!strcmp(strategy, "z3950"))
352 s->sort_strategy = SORT_STRATEGY_Z3950;
354 else if (!strcmp(strategy, "type7"))
356 s->sort_strategy = SORT_STRATEGY_TYPE7;
358 else if (!strcmp(strategy, "cql"))
360 s->sort_strategy = SORT_STRATEGY_CQL;
362 else if (!strcmp(strategy, "sru11"))
364 s->sort_strategy = SORT_STRATEGY_SRU11;
366 else if (!strcmp(strategy, "solr"))
368 s->sort_strategy = SORT_STRATEGY_SOLR;
370 else if (!strcmp(strategy, "embed"))
372 s->sort_strategy = SORT_STRATEGY_EMBED;
377 odr_reset(s->odr_sort_spec);
378 s->sort_spec = yaz_sort_spec(s->odr_sort_spec, criteria);
387 * c-file-style: "Stroustrup"
388 * indent-tabs-mode: nil
390 * vim: shiftwidth=4 tabstop=8 expandtab