YAZ 5.37.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#include <yaz/snprintf.h>
23
24static const char *lookup_index_from_string_attr(Z_AttributeList *attributes,
25 Odr_int *numeric_value)
26{
27 int j;
28 int server_choice = 1;
29 for (j = 0; j < attributes->num_attributes; j++)
30 {
31 Z_AttributeElement *ae = attributes->attributes[j];
32 if (*ae->attributeType == 1) /* use attribute */
33 {
35 {
37 int i;
38 for (i = 0; i < ca->num_list; i++)
39 {
40 Z_StringOrNumeric *son = ca->list[i];
42 return son->u.string;
43 }
44 }
45 else if (ae->which == Z_AttributeValue_numeric)
46 {
47 *numeric_value = *ae->value.numeric;
48 }
49 server_choice = 0; /* not serverChoice because we have use attr */
50 }
51 }
52 if (server_choice)
53 return "cql.serverChoice";
54 return 0;
55}
56
57static const char *lookup_relation_index_from_attr(Z_AttributeList *attributes)
58{
59 int j;
60 for (j = 0; j < attributes->num_attributes; j++)
61 {
62 Z_AttributeElement *ae = attributes->attributes[j];
63 if (*ae->attributeType == 2) /* relation attribute */
64 {
66 {
67 /* Only support for numeric relation */
68 Odr_int *relation = ae->value.numeric;
69 /* map this numeric to representation in CQL */
70 switch (*relation)
71 {
72 /* Unsure on whether this is the relation attribute constants? */
74 return "<";
76 return "<=";
78 return "=";
80 return ">=";
82 return ">";
84 return "<>";
85 case 100:
86 /* phonetic is not supported in CQL */
87 return 0;
88 case 101:
89 /* stem is not supported in CQL */
90 return 0;
91 case 102:
92 /* relevance is supported in CQL, but not implemented yet */
93 return 0;
94 default:
95 /* Invalid relation */
96 return 0;
97 }
98 }
99 else {
100 /* Can we have a complex relation value?
101 Should we implement something?
102 */
103 }
104 }
105 }
106 return "=";
107}
108
110 Z_AttributeList *attributes, WRBUF w)
111{
112 const char *relation = cql_lookup_reverse(ct, "relation.", attributes);
113 const char *index = cql_lookup_reverse(ct, "index.", attributes);
114 const char *structure = cql_lookup_reverse(ct, "structure.", attributes);
115
116 /* if transform (properties) do not match, we'll fall back
117 to string or report numeric attribute error */
118 if (!index)
119 {
120 Odr_int use_attribute = -1;
121 index = lookup_index_from_string_attr(attributes, &use_attribute);
122 if (!index)
123 {
124 wrbuf_rewind(w);
125 if (use_attribute != -1)
126 wrbuf_printf(w, ODR_INT_PRINTF, use_attribute);
128 }
129 }
130 if (!relation)
131 relation = lookup_relation_index_from_attr(attributes);
132
133 if (!relation)
134 relation = "=";
135 else 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
144 if (strcmp(index, "cql.serverChoice") || strcmp(relation, "=")
145 || (structure && strcmp(structure, "*")))
146 {
147 wrbuf_puts(w, index);
148 wrbuf_puts(w, " ");
149 wrbuf_puts(w, relation);
150 wrbuf_puts(w, " ");
151
152 if (structure && strcmp(structure, "*"))
153 {
154 wrbuf_puts(w, "/");
155 wrbuf_puts(w, structure);
156 wrbuf_puts(w, " ");
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 {
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 if (q->which != Z_Operand_APT)
184 {
185 wrbuf_rewind(w);
187 }
188 else
189 {
191 Z_Term *term = apt->term;
192 const char *sterm = 0;
193 size_t lterm = 0;
195 size_t i;
196 int r;
197
198 wrbuf_rewind(w);
199 r = rpn2cql_attr(ct, apt->attributes, w);
200 if (r)
201 return r;
202
203 switch (term->which)
204 {
205 case Z_Term_general:
206 lterm = term->u.general->len;
207 sterm = (const char *) term->u.general->buf;
208 break;
209 case Z_Term_numeric:
211 break;
213 sterm = term->u.characterString;
214 lterm = strlen(sterm);
215 break;
216 default:
217 wrbuf_rewind(w);
218 wrbuf_printf(w, "%d", term->which);
220 }
221
222 if (trunc <= 3 || trunc == 100 || trunc == 102 || trunc == 104)
223 {
224 int quote_it = 0;
225 for (i = 0 ; i < lterm; i++)
226 if (strchr(" ()=></", sterm[i]))
227 {
228 quote_it = 1;
229 break;
230 }
231 if (lterm == 0)
232 quote_it = 1;
233 if (quote_it)
234 wrbuf_puts(w, "\"");
235 if (trunc == 2 || trunc == 3)
236 wrbuf_puts(w, "*");
237 for (i = 0; i < lterm; i++)
238 {
239 if (sterm[i] == '\\' && i < lterm - 1)
240 {
241 i++;
242 if (strchr("*?\"\\", sterm[i]))
243 wrbuf_putc(w, '\\');
244 wrbuf_putc(w, sterm[i]);
245 }
246 else if (trunc == 102 && sterm[i] == '.' && sterm[i+1] == '*')
247 {
248 wrbuf_putc(w, '*');
249 i++;
250 }
251 else if (trunc == 102 && sterm[i] == '.')
252 wrbuf_putc(w, '?');
253 else if (trunc == 104 && sterm[i] == '?')
254 wrbuf_putc(w, '*');
255 else if (trunc == 104 && sterm[i] == '#')
256 wrbuf_putc(w, '?');
257 else if (strchr("*?\"", sterm[i]))
258 {
259 wrbuf_putc(w, '\\');
260 wrbuf_putc(w, sterm[i]);
261 }
262 else
263 wrbuf_putc(w, sterm[i]);
264 }
265 if (trunc == 1 || trunc == 3)
266 wrbuf_puts(w, "*");
267 if (quote_it)
268 wrbuf_puts(w, "\"");
269 }
270 else
271 {
272 wrbuf_rewind(w);
273 wrbuf_printf(w, ODR_INT_PRINTF, trunc);
275 }
276 pr(wrbuf_cstr(w), client_data);
277 }
278 return 0;
279}
280
281
283 void (*pr)(const char *buf, void *client_data),
284 void *client_data,
285 Z_RPNStructure *q, int nested,
286 WRBUF w)
287{
289 return rpn2cql_simple(ct, pr, client_data, q->u.simple, w);
290 else
291 {
292 Z_Operator *op = q->u.complex->roperator;
294 int r;
295
296 if (nested)
297 pr("(", client_data);
298
299 r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1, w);
300 if (r)
301 return r;
302 switch (op->which)
303 {
304 case Z_Operator_and:
305 pr(" and ", client_data);
306 break;
307 case Z_Operator_or:
308 pr(" or ", client_data);
309 break;
311 pr(" not ", client_data);
312 break;
313 case Z_Operator_prox: {
314 pr(" prox", client_data);
315 prox = op->u.prox;
316 /* No way to express Odr_bool *exclusion -- ignore it */
317 if (prox->distance) {
318 char buf[21]; /* Enough for any 64-bit int */
319 char *op2name[6] = { "<", "<=", "=", ">=", ">","<>" };
320 pr("/distance", client_data);
321 if (!prox->relationType ||
324 {
325 wrbuf_rewind(w);
327 }
328 pr(op2name[*prox->relationType-1], client_data);
329 yaz_snprintf(buf, sizeof buf, "%ld", (long) *prox->distance);
330 pr(buf, client_data);
331 }
332 if (prox->ordered) {
333 if (*prox->ordered) {
334 pr("/ordered", client_data);
335 } else {
336 pr("/unordered", client_data);
337 }
338 }
339 if (prox->which != Z_ProximityOperator_known ||
340 *prox->u.known != Z_ProxUnit_word) {
341 pr("/unit=", client_data);
342 pr(yaz_prox_unit_name(prox), client_data);
343 }
344 pr(" ", client_data);
345 break;
346 }
347 }
348 r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s2, 1, w);
349 if (nested)
350 pr(")", client_data);
351 return r;
352 }
353}
354
356 WRBUF addinfo,
357 void (*pr)(const char *buf, void *client_data),
358 void *client_data,
359 Z_RPNQuery *q)
360{
361 /* addinfo (w) is used for both addinfo and house-keeping ! */
362 int r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, addinfo);
363 if (!r)
364 wrbuf_rewind(addinfo); /* no additional info if no error */
365 return r;
366}
367
368
370 void (*pr)(const char *buf, void *client_data),
371 void *client_data,
372 Z_RPNQuery *q)
373{
374 WRBUF w = wrbuf_alloc();
375 int r = cql_transform_rpn2cql_stream_r(ct, w, pr, client_data, q);
376 if (r)
377 cql_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
378 wrbuf_destroy(w);
379 return r;
380}
381
382
389
390/*
391 * Local variables:
392 * c-basic-offset: 4
393 * c-file-style: "Stroustrup"
394 * indent-tabs-mode: nil
395 * End:
396 * vim: shiftwidth=4 tabstop=8 expandtab
397 */
398
struct cql_transform_t_ * cql_transform_t
CQL transform handle. The transform describes how to convert from CQL to PQF (Type-1 AKA RPN).
Definition cql.h:292
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:254
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:57
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:355
static int rpn2cql_attr(cql_transform_t ct, Z_AttributeList *attributes, WRBUF w)
Definition rpn2cql.c:109
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:178
static const char * lookup_index_from_string_attr(Z_AttributeList *attributes, Odr_int *numeric_value)
Definition rpn2cql.c:24
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:369
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:383
static Odr_int lookup_truncation(Z_AttributeList *attributes)
Definition rpn2cql.c:162
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:282
Header for RPN to CQL tranform.
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Definition snprintf.c:31
Header for config file reading utilities.
Odr_int * attributeType
Definition z-core.h:581
Z_ComplexAttribute * complex
Definition z-core.h:585
Odr_int * numeric
Definition z-core.h:584
union Z_AttributeElement::@260252174261265367116362007076255375270002041323 value
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
int which
Definition z-core.h:510
Z_AttributesPlusTerm * attributesPlusTerm
Definition z-core.h:512
union Z_Operand::@072322006164213251104156071070134267373322123052 u
int which
Definition z-core.h:559
Z_ProximityOperator * prox
Definition z-core.h:564
union Z_Operator::@171225215357037113014354143242105145344254361002 u
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::@031336250334025346341060256205106006053041305237 u
Z_RPNStructure * RPNStructure
Definition z-core.h:490
Z_Complex * complex
Definition z-core.h:503
union Z_RPNStructure::@272042053041255367154306203353273370010236313243 u
Z_Operand * simple
Definition z-core.h:502
union Z_StringOrNumeric::@255321135104110073015132067151226017215302214211 u
Z_InternationalString * string
Definition z-core.h:1321
union Z_Term::@023217361022206241314262227377164117366363003164 u
Odr_oct * general
Definition z-core.h:539
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
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
struct wrbuf * WRBUF
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