YAZ  5.23.1
zoom-query.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <assert.h>
14 #include <string.h>
15 #include <errno.h>
16 #include "zoom-p.h"
17 
18 #include <yaz/yaz-util.h>
19 #include <yaz/xmalloc.h>
20 #include <yaz/log.h>
21 #include <yaz/pquery.h>
22 #include <yaz/cql.h>
23 #include <yaz/ccl.h>
24 #include <yaz/sortspec.h>
25 
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
32 
33 struct ZOOM_query_p {
37  int refcount;
41  char *query_string;
44 };
45 
46 static int generate(ZOOM_query s)
47 {
48  if (s->query_string)
49  {
50  Z_External *ext;
51 
54  odr_reset(s->odr_query);
55 
57  {
58  int r = 0;
60 
61  switch (s->sort_strategy)
62  {
65  break;
66  case SORT_STRATEGY_SOLR:
68  break;
69  }
70  if (r)
71  return r;
72  }
73  switch (s->query_type)
74  {
75  case Z_Query_type_1: /* RPN */
76  if (s->sort_spec &&
79  {
81  if (r)
82  return r;
83  }
84  s->z_query = (Z_Query *) odr_malloc(s->odr_query,
85  sizeof(*s->z_query));
87  s->z_query->u.type_1 =
89  if (!s->z_query->u.type_1)
90  {
91  s->z_query = 0;
92  return -1;
93  }
94  break;
95  case Z_Query_type_104: /* CQL */
96  if (s->sort_spec &&
99  {
100  int r = yaz_sort_spec_to_cql(s->sort_spec, s->full_query);
101  if (r)
102  return r;
103  }
104  ext = (Z_External *) odr_malloc(s->odr_query, sizeof(*ext));
107  ext->indirect_reference = 0;
108  ext->descriptor = 0;
109  ext->which = Z_External_CQL;
110  ext->u.cql = odr_strdup(s->odr_query, wrbuf_cstr(s->full_query));
111 
112  s->z_query = (Z_Query *) odr_malloc(s->odr_query, sizeof(*s->z_query));
114  s->z_query->u.type_104 = ext;
115 
116  break;
117  }
118  }
119  return 0;
120 }
121 
123 {
124  if (wrbuf_len(s->sru11_sort_spec))
125  return wrbuf_cstr(s->sru11_sort_spec);
126  return 0;
127 }
128 
130 {
131  return s->z_query;
132 }
133 
135 {
136  return s->sort_strategy == SORT_STRATEGY_Z3950 ? s->sort_spec : 0;
137 }
138 
140 {
141  return wrbuf_cstr(s->full_query);
142 }
143 
145 {
146  wrbuf_printf(w, "%d;", s->query_type);
147  if (s->query_string)
148  wrbuf_puts(w, s->query_string);
149  wrbuf_printf(w, ";%d;", s->sort_strategy);
150  if (s->sort_spec)
152 }
153 
154 /*
155  * Returns an xmalloc()d string containing RPN that corresponds to the
156  * CQL passed in. On error, sets the Connection object's error state
157  * and returns a null pointer.
158  * ### We could cache CQL parser and/or transformer in Connection.
159  */
160 static char *cql2pqf(ZOOM_connection c, const char *cql)
161 {
162  CQL_parser parser;
163  int error;
164  const char *cqlfile;
165  cql_transform_t trans;
166  char *result = 0;
167 
168  parser = cql_parser_create();
169  if ((error = cql_parser_string(parser, cql)) != 0) {
170  cql_parser_destroy(parser);
172  return 0;
173  }
174 
175  cqlfile = ZOOM_connection_option_get(c, "cqlfile");
176  if (cqlfile == 0)
177  {
178  ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file");
179  }
180  else if ((trans = cql_transform_open_fname(cqlfile)) == 0)
181  {
182  char buf[512];
183  sprintf(buf, "can't open CQL transform file '%.200s': %.200s",
184  cqlfile, strerror(errno));
186  }
187  else
188  {
189  WRBUF wrbuf_result = wrbuf_alloc();
190  error = cql_transform(trans, cql_parser_result(parser),
191  wrbuf_vp_puts, wrbuf_result);
192  if (error != 0) {
193  char buf[512];
194  const char *addinfo;
195  error = cql_transform_error(trans, &addinfo);
196  sprintf(buf, "%.200s (addinfo=%.200s)",
197  cql_strerror(error), addinfo);
199  }
200  else
201  {
202  result = xstrdup(wrbuf_cstr(wrbuf_result));
203  }
204  cql_transform_close(trans);
205  wrbuf_destroy(wrbuf_result);
206  }
207  cql_parser_destroy(parser);
208  return result;
209 }
210 
211 
214 {
215  ZOOM_query s = (ZOOM_query) xmalloc(sizeof(*s));
216 
217  s->refcount = 1;
218  s->z_query = 0;
219  s->sort_spec = 0;
222  s->query_string = 0;
223  s->full_query = wrbuf_alloc();
226  return s;
227 }
228 
229 ZOOM_API(void)
231 {
232  if (!s)
233  return;
234 
235  (s->refcount)--;
236  if (s->refcount == 0)
237  {
240  xfree(s->query_string);
243  xfree(s);
244  }
245 }
246 
247 ZOOM_API(void)
249 {
250  s->refcount++;
251 }
252 
253 
254 ZOOM_API(int)
255  ZOOM_query_prefix(ZOOM_query s, const char *str)
256 {
257  xfree(s->query_string);
258  s->query_string = xstrdup(str);
260  return generate(s);
261 }
262 
263 ZOOM_API(int)
264  ZOOM_query_cql(ZOOM_query s, const char *str)
265 {
266  xfree(s->query_string);
267  s->query_string = xstrdup(str);
269  return generate(s);
270 }
271 
272 /*
273  * Translate the CQL string client-side into RPN which is passed to
274  * the server. This is useful for server's that don't themselves
275  * support CQL, for which ZOOM_query_cql() is useless. `conn' is used
276  * only as a place to stash diagnostics if compilation fails; if this
277  * information is not needed, a null pointer may be used.
278  */
279 ZOOM_API(int)
281 {
282  char *rpn;
283  int ret;
284  ZOOM_connection freeme = 0;
285 
286  if (conn == 0)
287  conn = freeme = ZOOM_connection_create(0);
288 
289  rpn = cql2pqf(conn, str);
290  if (freeme != 0)
291  ZOOM_connection_destroy(freeme);
292  if (rpn == 0)
293  return -1;
294 
295  ret = ZOOM_query_prefix(s, rpn);
296  xfree(rpn);
297  return ret;
298 }
299 
300 /*
301  * Analogous in every way to ZOOM_query_cql2rpn(), except that there
302  * is no analogous ZOOM_query_ccl() that just sends uninterpreted CCL
303  * to the server, as the YAZ GFS doesn't know how to handle this.
304  */
305 ZOOM_API(int)
306  ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config,
307  int *ccl_error, const char **error_string,
308  int *error_pos)
309 {
310  int ret;
311  struct ccl_rpn_node *rpn;
312  CCL_bibset bibset = ccl_qual_mk();
313 
314  if (config)
315  ccl_qual_buf(bibset, config);
316 
317  rpn = ccl_find_str(bibset, str, ccl_error, error_pos);
318  if (!rpn)
319  {
320  *error_string = ccl_err_msg(*ccl_error);
321  ret = -1;
322  }
323  else
324  {
325  WRBUF wr = wrbuf_alloc();
326  ccl_pquery(wr, rpn);
327  ccl_rpn_delete(rpn);
328  ret = ZOOM_query_prefix(s, wrbuf_cstr(wr));
329  wrbuf_destroy(wr);
330  }
331  ccl_qual_rm(&bibset);
332  return ret;
333 }
334 
335 ZOOM_API(int)
336  ZOOM_query_sortby(ZOOM_query s, const char *criteria)
337 {
338  return ZOOM_query_sortby2(s, "z3950", criteria);
339 }
340 
341 ZOOM_API(int)
342 ZOOM_query_sortby2(ZOOM_query s, const char *strategy, const char *criteria)
343 {
344  if (!strcmp(strategy, "z3950"))
345  {
347  }
348  else if (!strcmp(strategy, "type7"))
349  {
351  }
352  else if (!strcmp(strategy, "cql"))
353  {
355  }
356  else if (!strcmp(strategy, "sru11"))
357  {
359  }
360  else if (!strcmp(strategy, "solr"))
361  {
363  }
364  else if (!strcmp(strategy, "embed"))
365  {
367  }
368  else
369  return -1;
370 
372  s->sort_spec = yaz_sort_spec(s->odr_sort_spec, criteria);
373  if (!s->sort_spec)
374  return -2;
375  return generate(s);
376 }
377 
378 /*
379  * Local variables:
380  * c-basic-offset: 4
381  * c-file-style: "Stroustrup"
382  * indent-tabs-mode: nil
383  * End:
384  * vim: shiftwidth=4 tabstop=8 expandtab
385  */
386 
int query_type
Definition: zoom-query.c:40
Z_Query * ZOOM_query_get_Z_Query(ZOOM_query s)
Definition: zoom-query.c:129
char * query_string
Definition: zoom-query.c:41
Header for SortSpec parsing.
static int generate(ZOOM_query s)
Definition: zoom-query.c:46
char * odr_strdup(ODR o, const char *str)
Definition: odr_mem.c:36
Header for errno utilities.
WRBUF sru11_sort_spec
Definition: zoom-query.c:43
ZOOM_query_prefix(ZOOM_query s, const char *str)
Definition: zoom-query.c:255
#define Z_Query_type_1
Definition: z-core.h:479
#define Z_External_CQL
Definition: prt-ext.h:93
#define ODR_ENCODE
Definition: odr.h:96
void cql_parser_destroy(CQL_parser cp)
destroys a CQL parser.
Definition: cql.c:1986
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition: wrbuf.c:281
Internal header for ZOOM implementation.
Odr_oid * direct_reference
Definition: prt-ext.h:60
ZOOM_connection_destroy(ZOOM_connection c)
Definition: zoom-c.c:605
const Odr_oid yaz_oid_userinfo_cql[]
Definition: oid_std.c:143
Header for PQF parsing.
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition: wrbuf.c:89
Header for common YAZ utilities.
int cql_transform_error(cql_transform_t ct, const char **addinfo)
returns additional information for last transform
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition: xmalloc.h:55
const char * ccl_err_msg(int ccl_errno)
Definition: cclerrms.c:36
RPN tree structure node.
Definition: ccl.h:128
string buffer
Definition: wrbuf.h:42
#define SORT_STRATEGY_SOLR
Definition: zoom-query.c:31
#define SORT_STRATEGY_SRU11
Definition: zoom-query.c:29
struct ccl_rpn_node * ccl_find_str(CCL_bibset bibset, const char *str, int *error, int *pos)
parse CCL find string using CCL profile return RPN tree
Definition: cclfind.c:1310
Z_External * type_104
Definition: z-core.h:477
CCL_bibset ccl_qual_mk(void)
creates Bibset
Definition: cclqual.c:210
#define Z_Query_type_104
Definition: z-core.h:484
ZOOM_query_sortby2(ZOOM_query s, const char *strategy, const char *criteria)
Definition: zoom-query.c:342
const char * ZOOM_query_get_query_string(ZOOM_query s)
Definition: zoom-query.c:139
void * odr_malloc(ODR o, size_t size)
Definition: odr_mem.c:31
Z_RPNQuery * type_1
Definition: z-core.h:472
#define SORT_STRATEGY_EMBED
Definition: zoom-query.c:30
Z_SortKeySpecList * yaz_sort_spec(ODR out, const char *arg)
parse sort spec string
Definition: sortspec.c:23
void ccl_pquery(WRBUF w, struct ccl_rpn_node *p)
Definition: cclptree.c:135
union Z_External::@30 u
int which
Definition: prt-ext.h:63
Z_SortKeySpecList * sort_spec
Definition: zoom-query.c:36
cql_transform_t cql_transform_open_fname(const char *fname)
creates a CQL transform handle from a file
Definition: cqltransform.c:276
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition: wrbuf.c:47
#define SORT_STRATEGY_TYPE7
Definition: zoom-query.c:27
ZOOM_connection_option_get(ZOOM_connection c, const char *key)
Definition: zoom-c.c:1770
ZOOM_query_sortby(ZOOM_query s, const char *criteria)
Definition: zoom-query.c:336
Header with public definitions about CQL.
void cql_transform_close(cql_transform_t ct)
destroys a CQL transform handle
Definition: cqltransform.c:256
void odr_reset(ODR o)
Definition: odr.c:226
ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
Definition: zoom-query.c:280
int which
Definition: z-core.h:469
ZOOM_connection_create(ZOOM_options options)
Definition: zoom-c.c:237
#define xfree(x)
utility macro which calls xfree_f
Definition: xmalloc.h:53
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition: wrbuf.c:178
int sort_strategy
Definition: zoom-query.c:35
ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config, int *ccl_error, const char **error_string, int *error_pos)
Definition: zoom-query.c:306
#define SORT_STRATEGY_Z3950
Definition: zoom-query.c:26
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition: wrbuf.c:38
void ccl_rpn_delete(struct ccl_rpn_node *rpn)
Definition: cclfind.c:141
char * descriptor
Definition: prt-ext.h:62
union Z_Query::@48 u
void wrbuf_vp_puts(const char *buf, void *client_data)
appends C-string to WRBUF - void pointer variant
Definition: wrbuf.c:94
#define ZOOM_API(x)
Definition: zoom.h:42
Z_Query * z_query
Definition: zoom-query.c:34
static char * cql2pqf(ZOOM_connection c, const char *cql)
Definition: zoom-query.c:160
ZOOM_query_cql(ZOOM_query s, const char *str)
Definition: zoom-query.c:264
Odr_int * indirect_reference
Definition: prt-ext.h:61
int cql_transform(cql_transform_t ct, struct cql_node *cn, void(*pr)(const char *buf, void *client_data), void *client_data)
tranforms PQF given a CQL tree (NOT re-entrant)
Definition: cqltransform.c:987
int yaz_sort_spec_to_srw_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:237
void odr_destroy(ODR o)
Definition: odr.c:253
#define ZOOM_ERROR_CQL_PARSE
Definition: zoom.h:139
Definition: odr.h:124
const char * ZOOM_query_get_sru11(ZOOM_query s)
Definition: zoom-query.c:122
int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf)
Definition: sortspec.c:190
ODR odr_sort_spec
Definition: zoom-query.c:38
#define ZOOM_ERROR_CQL_TRANSFORM
Definition: zoom.h:140
struct ZOOM_query_p * ZOOM_query
Definition: zoom.h:51
WRBUF full_query
Definition: zoom-query.c:42
#define xmalloc(x)
utility macro which calls malloc_f
Definition: xmalloc.h:49
Odr_oid * odr_oiddup(ODR odr, const Odr_oid *o)
Definition: odr_util.c:60
Z_SortKeySpecList * ZOOM_query_get_sortspec(ZOOM_query s)
Definition: zoom-query.c:134
ZOOM_query_destroy(ZOOM_query s)
Definition: zoom-query.c:230
Header for memory handling functions.
#define SORT_STRATEGY_CQL
Definition: zoom-query.c:28
void ccl_qual_buf(CCL_bibset bibset, const char *buf)
Definition: cclqfile.c:261
structure for all known EXTERNALs
Definition: prt-ext.h:58
void ZOOM_query_get_hash(ZOOM_query s, WRBUF w)
Definition: zoom-query.c:144
#define wrbuf_len(b)
Definition: wrbuf.h:250
void ZOOM_set_error(ZOOM_connection c, int error, const char *addinfo)
Definition: zoom-c.c:98
struct cql_node * cql_parser_result(CQL_parser cp)
returns the parse tree of the most recently parsed CQL query.
Definition: cql.c:1993
ODR odr_createmem(int direction)
Definition: odr.c:200
Z_InternationalString * cql
Definition: prt-ext.h:138
ZOOM_query_addref(ZOOM_query s)
Definition: zoom-query.c:248
Logging utility.
int cql_parser_string(CQL_parser cp, const char *str)
parses a CQL query (string)
Definition: cqlstring.c:35
int yaz_sort_spec_to_solr_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:297
ZOOM_query_create(void)
Definition: zoom-query.c:213
CQL_parser cql_parser_create(void)
creates a CQL parser.
Definition: cql.c:1971
Header with public definitions for CCL.
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition: wrbuf.c:25
const char * cql_strerror(int code)
returns the CQL message corresponding to a given error code.
Definition: cqlstrer.c:20
int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:135
Z_RPNQuery * p_query_rpn(ODR o, const char *qbuf)
Definition: pquery.c:699
void ccl_qual_rm(CCL_bibset *b)
destroys Bibset
Definition: cclqual.c:224