YAZ  5.34.0
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  {
238  odr_destroy(s->odr_query);
239  odr_destroy(s->odr_sort_spec);
240  xfree(s->query_string);
241  wrbuf_destroy(s->full_query);
242  wrbuf_destroy(s->sru11_sort_spec);
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);
259  s->query_type = Z_Query_type_1;
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);
268  s->query_type = Z_Query_type_104;
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  {
346  s->sort_strategy = SORT_STRATEGY_Z3950;
347  }
348  else if (!strcmp(strategy, "type7"))
349  {
350  s->sort_strategy = SORT_STRATEGY_TYPE7;
351  }
352  else if (!strcmp(strategy, "cql"))
353  {
354  s->sort_strategy = SORT_STRATEGY_CQL;
355  }
356  else if (!strcmp(strategy, "sru11"))
357  {
358  s->sort_strategy = SORT_STRATEGY_SRU11;
359  }
360  else if (!strcmp(strategy, "solr"))
361  {
362  s->sort_strategy = SORT_STRATEGY_SOLR;
363  }
364  else if (!strcmp(strategy, "embed"))
365  {
366  s->sort_strategy = SORT_STRATEGY_EMBED;
367  }
368  else
369  return -1;
370 
371  odr_reset(s->odr_sort_spec);
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 
Header with public definitions for CCL.
const char * ccl_err_msg(int ccl_errno)
Definition: cclerrms.c:36
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
void ccl_rpn_delete(struct ccl_rpn_node *rpn)
Definition: cclfind.c:141
void ccl_pquery(WRBUF w, struct ccl_rpn_node *p)
Definition: cclptree.c:135
void ccl_qual_buf(CCL_bibset bibset, const char *buf)
Definition: cclqfile.c:261
CCL_bibset ccl_qual_mk(void)
creates Bibset
Definition: cclqual.c:210
void ccl_qual_rm(CCL_bibset *b)
destroys Bibset
Definition: cclqual.c:224
struct cql_node * cql_parser_result(CQL_parser cp)
returns the parse tree of the most recently parsed CQL query.
Definition: cql.c:1902
void cql_parser_destroy(CQL_parser cp)
destroys a CQL parser.
Definition: cql.c:1895
CQL_parser cql_parser_create(void)
creates a CQL parser.
Definition: cql.c:1880
Header with public definitions about CQL.
const char * cql_strerror(int code)
returns the CQL message corresponding to a given error code.
Definition: cqlstrer.c:16
int cql_parser_string(CQL_parser cp, const char *str)
parses a CQL query (string)
Definition: cqlstring.c:35
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
cql_transform_t cql_transform_open_fname(const char *fname)
creates a CQL transform handle from a file
Definition: cqltransform.c:276
void cql_transform_close(cql_transform_t ct)
destroys a CQL transform handle
Definition: cqltransform.c:256
int cql_transform_error(cql_transform_t ct, const char **addinfo)
returns additional information for last transform
Header for errno utilities.
Logging utility.
ODR odr_createmem(int direction)
Definition: odr.c:200
void odr_destroy(ODR o)
Definition: odr.c:253
void odr_reset(ODR o)
Definition: odr.c:226
#define ODR_ENCODE
Definition: odr.h:96
char * odr_strdup(ODR o, const char *str)
Definition: odr_mem.c:36
void * odr_malloc(ODR o, size_t size)
Definition: odr_mem.c:31
Odr_oid * odr_oiddup(ODR odr, const Odr_oid *o)
Definition: odr_util.c:60
const Odr_oid yaz_oid_userinfo_cql[]
Definition: oid_std.c:143
Z_RPNQuery * p_query_rpn(ODR o, const char *qbuf)
Definition: pquery.c:699
Header for PQF parsing.
#define Z_External_CQL
Definition: prt-ext.h:93
int yaz_sort_spec_to_type7(Z_SortKeySpecList *sksl, WRBUF pqf)
Definition: sortspec.c:190
int yaz_sort_spec_to_solr_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:297
int yaz_sort_spec_to_srw_sortkeys(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:237
int yaz_sort_spec_to_cql(Z_SortKeySpecList *sksl, WRBUF w)
Definition: sortspec.c:135
Z_SortKeySpecList * yaz_sort_spec(ODR out, const char *arg)
parse sort spec string
Definition: sortspec.c:23
Header for SortSpec parsing.
WRBUF sru11_sort_spec
Definition: zoom-query.c:43
WRBUF full_query
Definition: zoom-query.c:42
Z_SortKeySpecList * sort_spec
Definition: zoom-query.c:36
int query_type
Definition: zoom-query.c:40
ODR odr_sort_spec
Definition: zoom-query.c:38
int sort_strategy
Definition: zoom-query.c:35
Z_Query * z_query
Definition: zoom-query.c:34
char * query_string
Definition: zoom-query.c:41
structure for all known EXTERNALs
Definition: prt-ext.h:59
Odr_int * indirect_reference
Definition: prt-ext.h:61
Z_InternationalString * cql
Definition: prt-ext.h:138
int which
Definition: prt-ext.h:63
union Z_External::@27 u
Odr_oid * direct_reference
Definition: prt-ext.h:60
char * descriptor
Definition: prt-ext.h:62
Z_External * type_104
Definition: z-core.h:477
Z_RPNQuery * type_1
Definition: z-core.h:472
int which
Definition: z-core.h:469
union Z_Query::@45 u
RPN tree structure node.
Definition: ccl.h:128
Definition: odr.h:125
string buffer
Definition: wrbuf.h:43
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition: wrbuf.c:38
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition: wrbuf.c:47
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition: wrbuf.c:25
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition: wrbuf.c:178
void wrbuf_vp_puts(const char *buf, void *client_data)
appends C-string to WRBUF - void pointer variant
Definition: wrbuf.c:94
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition: wrbuf.c:281
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition: wrbuf.c:89
#define wrbuf_len(b)
Definition: wrbuf.h:250
Header for memory handling functions.
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition: xmalloc.h:55
#define xfree(x)
utility macro which calls xfree_f
Definition: xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition: xmalloc.h:49
Header for common YAZ utilities.
#define Z_Query_type_1
Definition: z-core.h:479
#define Z_Query_type_104
Definition: z-core.h:484
void ZOOM_set_error(ZOOM_connection c, int error, const char *addinfo)
Definition: zoom-c.c:98
Internal header for ZOOM implementation.
ZOOM_query_destroy(ZOOM_query s)
Definition: zoom-query.c:230
#define SORT_STRATEGY_EMBED
Definition: zoom-query.c:30
ZOOM_query_cql(ZOOM_query s, const char *str)
Definition: zoom-query.c:264
ZOOM_query_prefix(ZOOM_query s, const char *str)
Definition: zoom-query.c:255
#define SORT_STRATEGY_SOLR
Definition: zoom-query.c:31
static int generate(ZOOM_query s)
Definition: zoom-query.c:46
#define SORT_STRATEGY_Z3950
Definition: zoom-query.c:26
#define SORT_STRATEGY_TYPE7
Definition: zoom-query.c:27
#define SORT_STRATEGY_CQL
Definition: zoom-query.c:28
ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn)
Definition: zoom-query.c:280
ZOOM_query_create(void)
Definition: zoom-query.c:213
const char * ZOOM_query_get_query_string(ZOOM_query s)
Definition: zoom-query.c:139
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
Z_SortKeySpecList * ZOOM_query_get_sortspec(ZOOM_query s)
Definition: zoom-query.c:134
static char * cql2pqf(ZOOM_connection c, const char *cql)
Definition: zoom-query.c:160
Z_Query * ZOOM_query_get_Z_Query(ZOOM_query s)
Definition: zoom-query.c:129
void ZOOM_query_get_hash(ZOOM_query s, WRBUF w)
Definition: zoom-query.c:144
ZOOM_query_addref(ZOOM_query s)
Definition: zoom-query.c:248
const char * ZOOM_query_get_sru11(ZOOM_query s)
Definition: zoom-query.c:122
ZOOM_query_sortby(ZOOM_query s, const char *criteria)
Definition: zoom-query.c:336
ZOOM_query_sortby2(ZOOM_query s, const char *strategy, const char *criteria)
Definition: zoom-query.c:342
#define SORT_STRATEGY_SRU11
Definition: zoom-query.c:29
ZOOM_connection_destroy(ZOOM_connection c)
Definition: zoom-c.c:605
#define ZOOM_ERROR_CQL_PARSE
Definition: zoom.h:139
#define ZOOM_ERROR_CQL_TRANSFORM
Definition: zoom.h:140
ZOOM_connection_option_get(ZOOM_connection c, const char *key)
Definition: zoom-c.c:1770
ZOOM_connection_create(ZOOM_options options)
Definition: zoom-c.c:237
struct ZOOM_query_p * ZOOM_query
Definition: zoom.h:51
#define ZOOM_API(x)
Definition: zoom.h:42