YAZ 5.35.1
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
23static 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];
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
56static 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 {
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;
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:
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{
288 return rpn2cql_simple(ct, pr, client_data, q->u.simple, w);
289 else
290 {
291 Z_Operator *op = q->u.complex->roperator;
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;
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);
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
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
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
static const char * lookup_relation_index_from_attr(Z_AttributeList *attributes)
Definition rpn2cql.c:56
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
static const char * lookup_index_from_string_attr(Z_AttributeList *attributes, Odr_int *numeric_value)
Definition rpn2cql.c:23
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
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 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
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
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition wrbuf.c:299
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:189
void wrbuf_vp_puts(const char *buf, void *client_data)
appends C-string to WRBUF - void pointer variant
Definition wrbuf.c:94
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:287
#define wrbuf_len(b)
Definition wrbuf.h:269
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