YAZ  5.34.0
rpn2cql.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 <stdlib.h>
15 #include <string.h>
16 #include <yaz/rpn2cql.h>
17 #include <yaz/xmalloc.h>
18 #include <yaz/diagbib1.h>
19 #include <yaz/z-core.h>
20 #include <yaz/wrbuf.h>
21 #include <yaz/logrpn.h> /* For yaz_prox_unit_name() */
22 
23 static const char *lookup_index_from_string_attr(Z_AttributeList *attributes,
24  Odr_int *numeric_value)
25 {
26  int j;
27  int server_choice = 1;
28  for (j = 0; j < attributes->num_attributes; j++)
29  {
30  Z_AttributeElement *ae = attributes->attributes[j];
31  if (*ae->attributeType == 1) /* use attribute */
32  {
34  {
36  int i;
37  for (i = 0; i < ca->num_list; i++)
38  {
39  Z_StringOrNumeric *son = ca->list[i];
40  if (son->which == Z_StringOrNumeric_string)
41  return son->u.string;
42  }
43  }
44  else if (ae->which == Z_AttributeValue_numeric)
45  {
46  *numeric_value = *ae->value.numeric;
47  }
48  server_choice = 0; /* not serverChoice because we have use attr */
49  }
50  }
51  if (server_choice)
52  return "cql.serverChoice";
53  return 0;
54 }
55 
56 static const char *lookup_relation_index_from_attr(Z_AttributeList *attributes)
57 {
58  int j;
59  for (j = 0; j < attributes->num_attributes; j++)
60  {
61  Z_AttributeElement *ae = attributes->attributes[j];
62  if (*ae->attributeType == 2) /* relation attribute */
63  {
65  {
66  /* Only support for numeric relation */
67  Odr_int *relation = ae->value.numeric;
68  /* map this numeric to representation in CQL */
69  switch (*relation)
70  {
71  /* Unsure on whether this is the relation attribute constants? */
73  return "<";
75  return "<=";
77  return "=";
79  return ">=";
81  return ">";
83  return "<>";
84  case 100:
85  /* phonetic is not supported in CQL */
86  return 0;
87  case 101:
88  /* stem is not supported in CQL */
89  return 0;
90  case 102:
91  /* relevance is supported in CQL, but not implemented yet */
92  return 0;
93  default:
94  /* Invalid relation */
95  return 0;
96  }
97  }
98  else {
99  /* Can we have a complex relation value?
100  Should we implement something?
101  */
102  }
103  }
104  }
105  return "=";
106 }
107 
109  Z_AttributeList *attributes, WRBUF w)
110 {
111  const char *relation = cql_lookup_reverse(ct, "relation.", attributes);
112  const char *index = cql_lookup_reverse(ct, "index.", attributes);
113  const char *structure = cql_lookup_reverse(ct, "structure.", attributes);
114 
115  /* if transform (properties) do not match, we'll fall back
116  to string or report numeric attribute error */
117  if (!index)
118  {
119  Odr_int use_attribute = -1;
120  index = lookup_index_from_string_attr(attributes, &use_attribute);
121  if (!index)
122  {
123  wrbuf_rewind(w);
124  if (use_attribute != -1)
125  wrbuf_printf(w, ODR_INT_PRINTF, use_attribute);
127  }
128  }
129  if (!relation)
130  relation = lookup_relation_index_from_attr(attributes);
131 
132  if (!relation)
133  relation = "=";
134  else if (!strcmp(relation, "exact"))
135  relation = "==";
136  else if (!strcmp(relation, "eq"))
137  relation = "=";
138  else if (!strcmp(relation, "le"))
139  relation = "<=";
140  else if (!strcmp(relation, "ge"))
141  relation = ">=";
142 
143  if (strcmp(index, "cql.serverChoice") || strcmp(relation, "=")
144  || (structure && strcmp(structure, "*")))
145  {
146  wrbuf_puts(w, index);
147  wrbuf_puts(w, " ");
148  wrbuf_puts(w, relation);
149  wrbuf_puts(w, " ");
150 
151  if (structure && strcmp(structure, "*"))
152  {
153  wrbuf_puts(w, "/");
154  wrbuf_puts(w, structure);
155  wrbuf_puts(w, " ");
156  }
157  }
158  return 0;
159 }
160 
162 {
163  int j;
164  for (j = 0; j < attributes->num_attributes; j++)
165  {
166  Z_AttributeElement *ae = attributes->attributes[j];
167  if (*ae->attributeType == 5) /* truncation attribute */
168  {
169  if (ae->which == Z_AttributeValue_numeric)
170  return *(ae->value.numeric);
171  }
172  }
173  /* No truncation specified */
174  return 0;
175 }
176 
178  void (*pr)(const char *buf, void *client_data),
179  void *client_data,
180  Z_Operand *q, WRBUF w)
181 {
182  if (q->which != Z_Operand_APT)
183  {
184  wrbuf_rewind(w);
186  }
187  else
188  {
190  Z_Term *term = apt->term;
191  const char *sterm = 0;
192  size_t lterm = 0;
193  Odr_int trunc = lookup_truncation(apt->attributes);
194  size_t i;
195  int r;
196 
197  wrbuf_rewind(w);
198  r = rpn2cql_attr(ct, apt->attributes, w);
199  if (r)
200  return r;
201 
202  switch (term->which)
203  {
204  case Z_Term_general:
205  lterm = term->u.general->len;
206  sterm = (const char *) term->u.general->buf;
207  break;
208  case Z_Term_numeric:
209  wrbuf_printf(w, ODR_INT_PRINTF, *term->u.numeric);
210  break;
212  sterm = term->u.characterString;
213  lterm = strlen(sterm);
214  break;
215  default:
216  wrbuf_rewind(w);
217  wrbuf_printf(w, "%d", term->which);
219  }
220 
221  if (trunc <= 3 || trunc == 100 || trunc == 102 || trunc == 104)
222  {
223  int quote_it = 0;
224  for (i = 0 ; i < lterm; i++)
225  if (strchr(" ()=></", sterm[i]))
226  {
227  quote_it = 1;
228  break;
229  }
230  if (lterm == 0)
231  quote_it = 1;
232  if (quote_it)
233  wrbuf_puts(w, "\"");
234  if (trunc == 2 || trunc == 3)
235  wrbuf_puts(w, "*");
236  for (i = 0; i < lterm; i++)
237  {
238  if (sterm[i] == '\\' && i < lterm - 1)
239  {
240  i++;
241  if (strchr("*?\"\\", sterm[i]))
242  wrbuf_putc(w, '\\');
243  wrbuf_putc(w, sterm[i]);
244  }
245  else if (trunc == 102 && sterm[i] == '.' && sterm[i+1] == '*')
246  {
247  wrbuf_putc(w, '*');
248  i++;
249  }
250  else if (trunc == 102 && sterm[i] == '.')
251  wrbuf_putc(w, '?');
252  else if (trunc == 104 && sterm[i] == '?')
253  wrbuf_putc(w, '*');
254  else if (trunc == 104 && sterm[i] == '#')
255  wrbuf_putc(w, '?');
256  else if (strchr("*?\"", sterm[i]))
257  {
258  wrbuf_putc(w, '\\');
259  wrbuf_putc(w, sterm[i]);
260  }
261  else
262  wrbuf_putc(w, sterm[i]);
263  }
264  if (trunc == 1 || trunc == 3)
265  wrbuf_puts(w, "*");
266  if (quote_it)
267  wrbuf_puts(w, "\"");
268  }
269  else
270  {
271  wrbuf_rewind(w);
272  wrbuf_printf(w, ODR_INT_PRINTF, trunc);
274  }
275  pr(wrbuf_cstr(w), client_data);
276  }
277  return 0;
278 }
279 
280 
282  void (*pr)(const char *buf, void *client_data),
283  void *client_data,
284  Z_RPNStructure *q, int nested,
285  WRBUF w)
286 {
287  if (q->which == Z_RPNStructure_simple)
288  return rpn2cql_simple(ct, pr, client_data, q->u.simple, w);
289  else
290  {
291  Z_Operator *op = q->u.complex->roperator;
292  Z_ProximityOperator *prox;
293  int r;
294 
295  if (nested)
296  pr("(", client_data);
297 
298  r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
299  if (r)
300  return r;
301  switch (op->which)
302  {
303  case Z_Operator_and:
304  pr(" and ", client_data);
305  break;
306  case Z_Operator_or:
307  pr(" or ", client_data);
308  break;
309  case Z_Operator_and_not:
310  pr(" not ", client_data);
311  break;
312  case Z_Operator_prox: {
313  pr(" prox", client_data);
314  prox = op->u.prox;
315  /* No way to express Odr_bool *exclusion -- ignore it */
316  if (prox->distance) {
317  char buf[21]; /* Enough for any 64-bit int */
318  char *op2name[6] = { "<", "<=", "=", ">=", ">","<>" };
319  pr("/distance", client_data);
320  if (!prox->relationType ||
323  {
324  wrbuf_rewind(w);
325  return YAZ_BIB1_UNSUPP_SEARCH;
326  }
327  pr(op2name[*prox->relationType-1], client_data);
328  sprintf(buf, "%ld", (long) *prox->distance);
329  pr(buf, client_data);
330  }
331  if (prox->ordered) {
332  if (*prox->ordered) {
333  pr("/ordered", client_data);
334  } else {
335  pr("/unordered", client_data);
336  }
337  }
338  if (prox->which != Z_ProximityOperator_known ||
339  *prox->u.known != Z_ProxUnit_word) {
340  pr("/unit=", client_data);
341  pr(yaz_prox_unit_name(prox), client_data);
342  }
343  pr(" ", client_data);
344  break;
345  }
346  }
347  r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
348  if (nested)
349  pr(")", client_data);
350  return r;
351  }
352 }
353 
355  WRBUF addinfo,
356  void (*pr)(const char *buf, void *client_data),
357  void *client_data,
358  Z_RPNQuery *q)
359 {
360  /* addinfo (w) is used for both addinfo and house-keeping ! */
361  int r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, addinfo);
362  if (!r)
363  wrbuf_rewind(addinfo); /* no additional info if no error */
364  return r;
365 }
366 
367 
369  void (*pr)(const char *buf, void *client_data),
370  void *client_data,
371  Z_RPNQuery *q)
372 {
373  WRBUF w = wrbuf_alloc();
374  int r = cql_transform_rpn2cql_stream_r(ct, w, pr, client_data, q);
375  if (r)
376  cql_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
377  wrbuf_destroy(w);
378  return r;
379 }
380 
381 
383  WRBUF w,
384  Z_RPNQuery *q)
385 {
387 }
388 
389 /*
390  * Local variables:
391  * c-basic-offset: 4
392  * c-file-style: "Stroustrup"
393  * indent-tabs-mode: nil
394  * End:
395  * vim: shiftwidth=4 tabstop=8 expandtab
396  */
397 
void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo)
sets error and addinfo for transform
const char * cql_lookup_reverse(cql_transform_t ct, const char *category, Z_AttributeList *attributes)
find a pattern that has a subset of attributes
Definition: cqltransform.c:322
Diagnostics: Generated by csvtodiag.tcl from ./bib1.csv.
#define YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE
Definition: diagbib1.h:64
#define YAZ_BIB1_UNSUPP_USE_ATTRIBUTE
Definition: diagbib1.h:58
#define YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM
Definition: diagbib1.h:28
#define YAZ_BIB1_TERM_TYPE_UNSUPP
Definition: diagbib1.h:104
#define YAZ_BIB1_UNSUPP_SEARCH
Definition: diagbib1.h:13
const char * yaz_prox_unit_name(Z_ProximityOperator *op)
Definition: logrpn.c:253
Header for Z39.50 Query Printing.
#define ODR_INT_PRINTF
Definition: odr.h:49
nmem_int_t Odr_int
Definition: odr.h:47
int cql_transform_rpn2cql_stream_r(cql_transform_t ct, WRBUF addinfo, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q)
transforms RPN query to CQL output stream (re-entrant)
Definition: rpn2cql.c:354
static int rpn2cql_attr(cql_transform_t ct, Z_AttributeList *attributes, WRBUF w)
Definition: rpn2cql.c:108
static int rpn2cql_simple(cql_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_Operand *q, WRBUF w)
Definition: rpn2cql.c:177
int cql_transform_rpn2cql_stream(cql_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q)
transforms RPN query to CQL output stream (NOT re-entrant)
Definition: rpn2cql.c:368
static const char * lookup_relation_index_from_attr(Z_AttributeList *attributes)
Definition: rpn2cql.c:56
int cql_transform_rpn2cql_wrbuf(cql_transform_t ct, WRBUF w, Z_RPNQuery *q)
transforms RPN query to CQL WRBUF (NOT re-entrant)
Definition: rpn2cql.c:382
static Odr_int lookup_truncation(Z_AttributeList *attributes)
Definition: rpn2cql.c:161
static const char * lookup_index_from_string_attr(Z_AttributeList *attributes, Odr_int *numeric_value)
Definition: rpn2cql.c:23
static int rpn2cql_structure(cql_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNStructure *q, int nested, WRBUF w)
Definition: rpn2cql.c:281
Header for RPN to CQL tranform.
union Z_AttributeElement::@50 value
Odr_int * attributeType
Definition: z-core.h:581
Z_ComplexAttribute * complex
Definition: z-core.h:585
Odr_int * numeric
Definition: z-core.h:584
int num_attributes
Definition: z-core.h:532
Z_AttributeElement ** attributes
Definition: z-core.h:533
Z_AttributeList * attributes
Definition: z-core.h:522
Z_StringOrNumeric ** list
Definition: z-core.h:574
Z_RPNStructure * s2
Definition: z-core.h:495
Z_Operator * roperator
Definition: z-core.h:496
Z_RPNStructure * s1
Definition: z-core.h:494
union Z_Operand::@47 u
int which
Definition: z-core.h:510
Z_AttributesPlusTerm * attributesPlusTerm
Definition: z-core.h:512
union Z_Operator::@49 u
int which
Definition: z-core.h:559
Z_ProximityOperator * prox
Definition: z-core.h:564
Odr_bool * ordered
Definition: z-core.h:594
Odr_int * distance
Definition: z-core.h:593
Z_ProxUnit * known
Definition: z-core.h:604
Odr_int * relationType
Definition: z-core.h:601
union Z_ProximityOperator::@51 u
Z_RPNStructure * RPNStructure
Definition: z-core.h:490
Z_Complex * complex
Definition: z-core.h:503
union Z_RPNStructure::@46 u
Z_Operand * simple
Definition: z-core.h:502
union Z_StringOrNumeric::@72 u
Z_InternationalString * string
Definition: z-core.h:1321
Definition: z-core.h:536
Odr_oct * general
Definition: z-core.h:539
union Z_Term::@48 u
Z_InternationalString * characterString
Definition: z-core.h:541
int which
Definition: z-core.h:537
Odr_int * numeric
Definition: z-core.h:540
int len
Definition: odr.h:102
char * buf
Definition: odr.h:101
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
Header for WRBUF (growing buffer)
#define wrbuf_putc(b, c)
Definition: wrbuf.h:268
#define wrbuf_len(b)
Definition: wrbuf.h:250
Header for memory handling functions.
ASN.1 Module Z39-50-APDU-1995.
#define Z_AttributeValue_numeric
Definition: z-core.h:586
#define Z_Operator_and_not
Definition: z-core.h:567
#define Z_Operator_or
Definition: z-core.h:566
#define Z_Term_characterString
Definition: z-core.h:549
#define Z_ProximityOperator_Prox_lessThanOrEqual
Definition: z-core.h:596
#define Z_Operand_APT
Definition: z-core.h:515
#define Z_ProximityOperator_known
Definition: z-core.h:606
#define Z_AttributeValue_complex
Definition: z-core.h:587
#define Z_Term_general
Definition: z-core.h:547
#define Z_StringOrNumeric_string
Definition: z-core.h:1323
#define Z_Operator_prox
Definition: z-core.h:568
#define Z_Operator_and
Definition: z-core.h:565
#define Z_ProximityOperator_Prox_lessThan
Definition: z-core.h:595
#define Z_Term_numeric
Definition: z-core.h:548
#define Z_RPNStructure_simple
Definition: z-core.h:504
#define Z_ProximityOperator_Prox_equal
Definition: z-core.h:597
#define Z_ProximityOperator_Prox_greaterThan
Definition: z-core.h:599
#define Z_ProximityOperator_Prox_greaterThanOrEqual
Definition: z-core.h:598
#define Z_ProxUnit_word
Definition: z-core.h:612
#define Z_ProximityOperator_Prox_notEqual
Definition: z-core.h:600