YAZ  5.34.0
rpn2solr.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/rpn2solr.h>
17 #include <yaz/xmalloc.h>
18 #include <yaz/diagbib1.h>
19 #include <yaz/z-core.h>
20 #include <yaz/wrbuf.h>
21 
22 static const char *lookup_index_from_string_attr(Z_AttributeList *attributes)
23 {
24  int j;
25  int server_choice = 1;
26  for (j = 0; j < attributes->num_attributes; j++)
27  {
28  Z_AttributeElement *ae = attributes->attributes[j];
29  if (*ae->attributeType == 1) /* use attribute */
30  {
32  {
34  int i;
35  for (i = 0; i < ca->num_list; i++)
36  {
37  Z_StringOrNumeric *son = ca->list[i];
38  if (son->which == Z_StringOrNumeric_string)
39  return son->u.string;
40  }
41  }
42  server_choice = 0; /* not serverChoice because we have use attr */
43  }
44  }
45  if (server_choice)
46  return "cql.serverChoice";
47  return 0;
48 }
49 
50 static const char *lookup_relation_index_from_attr(Z_AttributeList *attributes)
51 {
52  int j;
53  for (j = 0; j < attributes->num_attributes; j++)
54  {
55  Z_AttributeElement *ae = attributes->attributes[j];
56  if (*ae->attributeType == 2) /* relation attribute */
57  {
59  {
60  /* Only support for numeric relation */
61  Odr_int *relation = ae->value.numeric;
62  /* map this numeric to representation in SOLR */
63  switch (*relation)
64  {
65  /* Unsure on whether this is the relation attribute constants? */
67  return "<";
69  return "le";
71  return ":";
73  return "ge";
75  return ">";
77  return 0;
78  case 100:
79  /* phonetic is not implemented */
80  return 0;
81  case 101:
82  /* stem is not not implemented */
83  return 0;
84  case 102:
85  /* relevance is supported in SOLR, but not implemented yet */
86  return 0;
87  default:
88  /* Invalid relation */
89  return 0;
90  }
91  }
92  else {
93  /* Can we have a complex relation value?
94  Should we implement something?
95  */
96  }
97  }
98  }
99  return ":";
100 }
101 
103  Z_AttributesPlusTerm **p_apt1,
104  Z_AttributesPlusTerm **p_apt2)
105 {
106  Z_Operator *op = q->roperator;
107  if (op->which == Z_Operator_and &&
108  q->s1->which == Z_RPNStructure_simple &&
109  q->s2->which == Z_RPNStructure_simple &&
110  q->s1->u.simple->which == Z_Operand_APT &&
111  q->s2->u.simple->which == Z_Operand_APT)
112  {
115  const char *i1 = solr_lookup_reverse(ct, "index.", apt1->attributes);
116  const char *i2 = solr_lookup_reverse(ct, "index.", apt2->attributes);
117  const char *rel1 = solr_lookup_reverse(ct, "relation.",
118  apt1->attributes);
119  const char *rel2 = solr_lookup_reverse(ct, "relation.",
120  apt2->attributes);
121  if (!rel1)
123  if (!rel2)
125  if (!i1)
127  if (!i2)
129  if (i1 && i2 && !strcmp(i1, i2) && rel1 && rel2)
130  {
131  if ((rel1[0] == '>' || rel1[0] == 'g') &&
132  (rel2[0] == '<' || rel2[0] == 'l'))
133  {
134  *p_apt1 = apt1;
135  *p_apt2 = apt2;
136  return 1;
137  }
138  if ((rel2[0] == '>' || rel2[0] == 'g') &&
139  (rel1[0] == '<' || rel1[0] == 'l'))
140  {
141  *p_apt1 = apt2;
142  *p_apt2 = apt1;
143  return 1;
144  }
145  }
146  }
147  return 0;
148 }
149 
151  Z_AttributeList *attributes, WRBUF w)
152 {
153  const char *index = solr_lookup_reverse(ct, "index.", attributes);
154  const char *structure = solr_lookup_reverse(ct, "structure.", attributes);
155 
156  /* if no real match, try string attribute */
157  if (!index)
158  index = lookup_index_from_string_attr(attributes);
159  if (!index)
161  /* for serverChoice we omit index+relation+structure */
162  if (strcmp(index, "cql.serverChoice"))
163  {
164  wrbuf_puts(w, index);
165  wrbuf_puts(w, ":");
166  if (structure)
167  {
168  if (strcmp(structure, "*"))
169  {
170  wrbuf_puts(w, "/");
171  wrbuf_puts(w, structure);
172  wrbuf_puts(w, " ");
173  }
174  }
175  }
176  return 0;
177 }
178 
180 {
181  int j;
182  Z_AttributeList *attributes = apt->attributes;
183  for (j = 0; j < attributes->num_attributes; j++)
184  {
185  Z_AttributeElement *ae = attributes->attributes[j];
186  if (*ae->attributeType == 5) /* truncation attribute */
187  {
188  if (ae->which == Z_AttributeValue_numeric)
189  {
190  return *(ae->value.numeric);
191  }
192  else if (ae->which == Z_AttributeValue_complex) {
193  ;
194  /* Complex: Shouldn't happen */
195  }
196  }
197  }
198  /* No truncation given */
199  return 0;
200 }
201 
202 #define SOLR_SPECIAL "+-&|!(){}[]^\"~*?:\\"
203 
204 static int emit_term(solr_transform_t ct, WRBUF w, Z_Term *term, Odr_int trunc)
205 {
206  size_t lterm = 0;
207  const char *sterm = 0;
208  switch (term->which)
209  {
210  case Z_Term_general:
211  lterm = term->u.general->len;
212  sterm = (const char *) term->u.general->buf;
213  break;
214  case Z_Term_numeric:
215  wrbuf_printf(w, ODR_INT_PRINTF, *term->u.numeric);
216  break;
218  sterm = term->u.characterString;
219  lterm = strlen(sterm);
220  break;
221  default:
223  }
224 
225  if (sterm)
226  {
227  size_t i;
228  int must_quote = 0;
229 
230  if (lterm == 0)
231  must_quote = 1;
232  else
233  {
234  for (i = 0 ; i < lterm; i++)
235  if (sterm[i] == ' ')
236  must_quote = 1;
237  }
238  if (must_quote)
239  wrbuf_puts(w, "\"");
240  if (trunc == 2 || trunc == 3)
241  wrbuf_puts(w, "*");
242  for (i = 0 ; i < lterm; i++)
243  {
244  if (sterm[i] == '\\' && i < lterm - 1)
245  {
246  i++;
247  if (strchr(SOLR_SPECIAL, sterm[i]))
248  wrbuf_putc(w, '\\');
249  wrbuf_putc(w, sterm[i]);
250  }
251  else if (sterm[i] == '?' && trunc == 104)
252  {
253  wrbuf_putc(w, '*');
254  }
255  else if (sterm[i] == '#' && trunc == 104)
256  {
257  wrbuf_putc(w, '?');
258  }
259  else if (strchr(SOLR_SPECIAL, sterm[i]))
260  {
261  wrbuf_putc(w, '\\');
262  wrbuf_putc(w, sterm[i]);
263  }
264  else
265  wrbuf_putc(w, sterm[i]);
266  }
267  if (trunc == 1 || trunc == 3)
268  wrbuf_puts(w, "*");
269  if (must_quote)
270  wrbuf_puts(w, "\"");
271  }
272  return 0;
273 }
274 
276  void (*pr)(const char *buf, void *client_data),
277  void *client_data,
278  Z_AttributesPlusTerm *apt, WRBUF w,
279  Z_AttributesPlusTerm *apt2)
280  {
281  int ret = 0;
282  Z_Term *term = apt->term;
283  Odr_int trunc = get_truncation(apt);
284  const char *relation2 = 0;
285  const char *relation1 = solr_lookup_reverse(ct, "relation.",
286  apt->attributes);
287  /* Attempt to fix bug #2978: Look for a relation attribute */
288  if (!relation1)
290  if (!relation1)
291  {
293  }
294  if (apt2)
295  {
296  relation2 = solr_lookup_reverse(ct, "relation.",
297  apt2->attributes);
298  if (!relation2)
299  relation2 = lookup_relation_index_from_attr(apt2->attributes);
300  }
301  wrbuf_rewind(w);
302  ret = rpn2solr_attr(ct, apt->attributes, w);
303  if (ret)
304  return ret;
305  if ((trunc >= 0 && trunc <= 3) || trunc == 100 || trunc == 104)
306  ;
307  else
308  {
310  }
311 
312  if (!relation1)
313  ret = emit_term(ct, w, term, trunc);
314  else if (relation1[0] == '<' || relation1[0] == 'l')
315  {
316  wrbuf_puts(w, "[* TO ");
317  ret = emit_term(ct, w, term, trunc);
318  if (!strcmp(relation1, "le") || !strcmp(relation1, "<="))
319  wrbuf_puts(w, "]");
320  else
321  wrbuf_puts(w, "}");
322  }
323  else if (relation1[0] == '>' || relation1[0] == 'g')
324  {
325  if (!strcmp(relation1, ">=") || !strcmp(relation1, "ge"))
326  wrbuf_puts(w, "[");
327  else
328  wrbuf_puts(w, "{");
329  ret = emit_term(ct, w, term, trunc);
330  wrbuf_puts(w, " TO ");
331  if (apt2)
332  {
333  emit_term(ct, w, apt2->term, 0);
334  if (!relation2 || !strcmp(relation2, "<=") ||
335  !strcmp(relation2, "le"))
336  wrbuf_puts(w, "]");
337  else
338  wrbuf_puts(w, "}");
339  }
340  else
341  wrbuf_puts(w, "*]");
342  }
343  else
344  ret = emit_term(ct, w, term, trunc);
345  if (ret == 0)
346  pr(wrbuf_cstr(w), client_data);
347  return ret;
348  }
349 
350 
352  void (*pr)(const char *buf, void *client_data),
353  void *client_data,
354  Z_RPNStructure *q, int nested,
355  WRBUF w)
356 {
357  if (q->which == Z_RPNStructure_simple)
358  {
359  if (q->u.simple->which != Z_Operand_APT)
361  else
362  return rpn2solr_simple(ct, pr, client_data,
363  q->u.simple->u.attributesPlusTerm, w, 0);
364  }
365  else
366  {
367  Z_Operator *op = q->u.complex->roperator;
368  Z_AttributesPlusTerm *apt1, *apt2;
369  int r;
370 
371  if (check_range(ct, q->u.complex, &apt1, &apt2))
372  return rpn2solr_simple(ct, pr, client_data, apt1, w, apt2);
373  if (nested)
374  pr("(", client_data);
375 
376  r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
377  if (r)
378  return r;
379  switch (op->which)
380  {
381  case Z_Operator_and:
382  pr(" AND ", client_data);
383  break;
384  case Z_Operator_or:
385  pr(" OR ", client_data);
386  break;
387  case Z_Operator_and_not:
388  pr(" AND NOT ", client_data);
389  break;
390  case Z_Operator_prox:
391  return YAZ_BIB1_UNSUPP_SEARCH;
392  }
393  r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
394  if (nested)
395  pr(")", client_data);
396  return r;
397  }
398 }
399 
401  WRBUF addinfo,
402  void (*pr)(const char *buf, void *client_data),
403  void *client_data,
404  Z_RPNQuery *q)
405 {
406  int r = rpn2solr_structure(ct, pr, client_data, q->RPNStructure,
407  /* nested*/ 0, addinfo);
408  if (!r)
409  wrbuf_rewind(addinfo);
410  return r;
411 }
412 
414  void (*pr)(const char *buf, void *client_data),
415  void *client_data,
416  Z_RPNQuery *q)
417 {
418  WRBUF w = wrbuf_alloc();
419  int r = solr_transform_rpn2solr_stream_r(ct, w, pr, client_data, q);
420  if (r)
421  solr_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
422  wrbuf_destroy(w);
423  return r;
424 }
425 
427  WRBUF w,
428  Z_RPNQuery *q)
429 {
431 }
432 
433 /*
434  * Local variables:
435  * c-basic-offset: 4
436  * c-file-style: "Stroustrup"
437  * indent-tabs-mode: nil
438  * End:
439  * vim: shiftwidth=4 tabstop=8 expandtab
440  */
441 
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_UNSUPP_RELATION_ATTRIBUTE
Definition: diagbib1.h:61
#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
#define ODR_INT_PRINTF
Definition: odr.h:49
nmem_int_t Odr_int
Definition: odr.h:47
static int check_range(solr_transform_t ct, Z_Complex *q, Z_AttributesPlusTerm **p_apt1, Z_AttributesPlusTerm **p_apt2)
Definition: rpn2solr.c:102
int solr_transform_rpn2solr_wrbuf(solr_transform_t ct, WRBUF w, Z_RPNQuery *q)
transforms RPN query to SOLR WRBUF
Definition: rpn2solr.c:426
static int rpn2solr_simple(solr_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_AttributesPlusTerm *apt, WRBUF w, Z_AttributesPlusTerm *apt2)
Definition: rpn2solr.c:275
#define SOLR_SPECIAL
Definition: rpn2solr.c:202
static const char * lookup_relation_index_from_attr(Z_AttributeList *attributes)
Definition: rpn2solr.c:50
static int rpn2solr_structure(solr_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNStructure *q, int nested, WRBUF w)
Definition: rpn2solr.c:351
static int emit_term(solr_transform_t ct, WRBUF w, Z_Term *term, Odr_int trunc)
Definition: rpn2solr.c:204
static const char * lookup_index_from_string_attr(Z_AttributeList *attributes)
Definition: rpn2solr.c:22
int solr_transform_rpn2solr_stream_r(solr_transform_t ct, WRBUF addinfo, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q)
transforms RPN query to SOLR output stream (re-entrant)
Definition: rpn2solr.c:400
static Odr_int get_truncation(Z_AttributesPlusTerm *apt)
Definition: rpn2solr.c:179
static int rpn2solr_attr(solr_transform_t ct, Z_AttributeList *attributes, WRBUF w)
Definition: rpn2solr.c:150
int solr_transform_rpn2solr_stream(solr_transform_t ct, void(*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q)
transforms RPN query to SOLR output stream (NOT re-entrant)
Definition: rpn2solr.c:413
Header for RPN to SOLR tranform.
const char * solr_lookup_reverse(solr_transform_t ct, const char *category, Z_AttributeList *attributes)
find a pattern that has a subset of attributes
Definition: solrtransform.c:57
void solr_transform_set_error(solr_transform_t ct, int error, const char *addinfo)
sets error and addinfo for transform
Definition: solrtransform.c:51
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
int which
Definition: z-core.h:559
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_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_ProximityOperator_Prox_notEqual
Definition: z-core.h:600