YAZ  4.2.57
rpn2cql.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 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 void wrbuf_vputs(const char *buf, void *client_data)
24 {
25  wrbuf_write((WRBUF) client_data, buf, strlen(buf));
26 }
27 
28 static const char *lookup_index_from_string_attr(Z_AttributeList *attributes)
29 {
30  int j;
31  int server_choice = 1;
32  for (j = 0; j < attributes->num_attributes; j++)
33  {
34  Z_AttributeElement *ae = attributes->attributes[j];
35  if (*ae->attributeType == 1) /* use attribute */
36  {
38  {
40  int i;
41  for (i = 0; i < ca->num_list; i++)
42  {
43  Z_StringOrNumeric *son = ca->list[i];
44  if (son->which == Z_StringOrNumeric_string)
45  return son->u.string;
46  }
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 just use a USE string attribute (bug #2978) */
116  if (!index)
117  index = lookup_index_from_string_attr(attributes);
118 
119  /* Attempt to fix bug #2978: Look for a relation attribute */
120  if (!relation)
121  relation = lookup_relation_index_from_attr(attributes);
122 
123  if (!index)
124  {
127  return -1;
128  }
129  /* for serverChoice we omit index+relation+structure */
130  if (strcmp(index, "cql.serverChoice"))
131  {
132  wrbuf_puts(w, index);
133  if (relation)
134  {
135  if (!strcmp(relation, "exact"))
136  relation = "==";
137  else if (!strcmp(relation, "eq"))
138  relation = "=";
139  else if (!strcmp(relation, "le"))
140  relation = "<=";
141  else if (!strcmp(relation, "ge"))
142  relation = ">=";
143  /* Missing mapping of not equal, phonetic, stem and relevance */
144  wrbuf_puts(w, relation);
145  }
146  else
147  wrbuf_puts(w, "=");
148 
149  if (structure)
150  {
151  if (strcmp(structure, "*"))
152  {
153  wrbuf_puts(w, "/");
154  wrbuf_puts(w, structure);
155  wrbuf_puts(w, " ");
156  }
157  }
158  }
159  return 0;
160 }
161 
163 {
164  int j;
165  for (j = 0; j < attributes->num_attributes; j++)
166  {
167  Z_AttributeElement *ae = attributes->attributes[j];
168  if (*ae->attributeType == 5) /* truncation attribute */
169  {
170  if (ae->which == Z_AttributeValue_numeric)
171  return *(ae->value.numeric);
172  }
173  }
174  /* No truncation specified */
175  return 0;
176 };
177 
179  void (*pr)(const char *buf, void *client_data),
180  void *client_data,
181  Z_Operand *q, WRBUF w)
182 {
183  int ret = 0;
184  if (q->which != Z_Operand_APT)
185  {
186  ret = -1;
188  }
189  else
190  {
192  Z_Term *term = apt->term;
193  const char *sterm = 0;
194  size_t lterm = 0;
195  Odr_int trunc = lookup_truncation(apt->attributes);
196  size_t i;
197 
198  wrbuf_rewind(w);
199  ret = rpn2cql_attr(ct, apt->attributes, w);
200 
201  switch (term->which)
202  {
203  case Z_Term_general:
204  lterm = term->u.general->len;
205  sterm = (const char *) term->u.general->buf;
206  break;
207  case Z_Term_numeric:
208  wrbuf_printf(w, ODR_INT_PRINTF, *term->u.numeric);
209  break;
211  sterm = term->u.characterString;
212  lterm = strlen(sterm);
213  break;
214  default:
216  return -1;
217  }
218 
219  if (trunc <= 3 || trunc == 100 || trunc == 102 || trunc == 104)
220  {
221  int quote_it = 0;
222  for (i = 0 ; i < lterm; i++)
223  if (strchr(" ()=></", sterm[i]))
224  {
225  quote_it = 1;
226  break;
227  }
228  if (lterm == 0)
229  quote_it = 1;
230  if (quote_it)
231  wrbuf_puts(w, "\"");
232  if (trunc == 2 || trunc == 3)
233  wrbuf_puts(w, "*");
234  for (i = 0; i < lterm; i++)
235  {
236  if (sterm[i] == '\\' && i < lterm - 1)
237  {
238  i++;
239  if (strchr("*?\"\\", sterm[i]))
240  wrbuf_putc(w, '\\');
241  wrbuf_putc(w, sterm[i]);
242  }
243  else if (trunc == 102 && sterm[i] == '.' && sterm[i+1] == '*')
244  {
245  wrbuf_putc(w, '*');
246  i++;
247  }
248  else if (trunc == 102 && sterm[i] == '.')
249  wrbuf_putc(w, '?');
250  else if (trunc == 104 && sterm[i] == '?')
251  wrbuf_putc(w, '*');
252  else if (trunc == 104 && sterm[i] == '#')
253  wrbuf_putc(w, '?');
254  else if (strchr("*?\"", sterm[i]))
255  {
256  wrbuf_putc(w, '\\');
257  wrbuf_putc(w, sterm[i]);
258  }
259  else
260  wrbuf_putc(w, sterm[i]);
261  }
262  if (trunc == 1 || trunc == 3)
263  wrbuf_puts(w, "*");
264  if (quote_it)
265  wrbuf_puts(w, "\"");
266  }
267  else
268  {
271  ret = -1;
272  }
273  if (ret == 0)
274  pr(wrbuf_cstr(w), client_data);
275  }
276  return ret;
277 }
278 
279 
281  void (*pr)(const char *buf, void *client_data),
282  void *client_data,
283  Z_RPNStructure *q, int nested,
284  WRBUF w)
285 {
286  if (q->which == Z_RPNStructure_simple)
287  return rpn2cql_simple(ct, pr, client_data, q->u.simple, w);
288  else
289  {
290  Z_Operator *op = q->u.complex->roperator;
291  Z_ProximityOperator *prox;
292  int r;
293 
294  if (nested)
295  pr("(", client_data);
296 
297  r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
298  if (r)
299  return r;
300  switch(op->which)
301  {
302  case Z_Operator_and:
303  pr(" and ", client_data);
304  break;
305  case Z_Operator_or:
306  pr(" or ", client_data);
307  break;
308  case Z_Operator_and_not:
309  pr(" not ", client_data);
310  break;
311  case Z_Operator_prox: {
312  pr(" prox", client_data);
313  prox = op->u.prox;
314  /* No way to express Odr_bool *exclusion -- ignore it */
315  if (prox->distance) {
316  char buf[21]; /* Enough for any 64-bit int */
317  char *op2name[6] = { "<", "<=", "=", ">=", ">","<>" };
318  pr("/distance", client_data);
319  if (!prox->relationType ||
323  "unrecognised proximity relationType");
324  return -1;
325  }
326  pr(op2name[*prox->relationType-1], client_data);
327  sprintf(buf, "%ld", (long) *prox->distance);
328  pr(buf, client_data);
329  }
330  if (prox->ordered) {
331  if (*prox->ordered) {
332  pr("/ordered", client_data);
333  } else {
334  pr("/unordered", client_data);
335  }
336  }
337  if (prox->which != Z_ProximityOperator_known ||
338  *prox->u.known != Z_ProxUnit_word) {
339  pr("/unit=", client_data);
340  pr(yaz_prox_unit_name(prox), client_data);
341  }
342  pr(" ", client_data);
343  break;
344  }
345  }
346  r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
347  if (nested)
348  pr(")", client_data);
349  return r;
350  }
351 }
352 
354  void (*pr)(const char *buf, void *client_data),
355  void *client_data,
356  Z_RPNQuery *q)
357 {
358  int r;
359  WRBUF w = wrbuf_alloc();
360  cql_transform_set_error(ct, 0, 0);
361  r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, w);
362  wrbuf_destroy(w);
363  return r;
364 }
365 
366 
368  WRBUF w,
369  Z_RPNQuery *q)
370 {
371  return cql_transform_rpn2cql_stream(ct, wrbuf_vputs, w, q);
372 }
373 
374 /*
375  * Local variables:
376  * c-basic-offset: 4
377  * c-file-style: "Stroustrup"
378  * indent-tabs-mode: nil
379  * End:
380  * vim: shiftwidth=4 tabstop=8 expandtab
381  */
382