Add re-entrant CQL/Solr/RPN functions
[yaz-moved-to-github.git] / include / yaz / cql.h
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data.
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Index Data nor the names of its contributors
13  *       may be used to endorse or promote products derived from this
14  *       software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /** \file cql.h
29     \brief Header with public definitions about CQL.
30 */
31
32 #ifndef CQL_H_INCLUDED
33 #define CQL_H_INCLUDED
34 #include <stdio.h>
35 #include <yaz/nmem.h>
36 #include <yaz/wrbuf.h>
37
38 YAZ_BEGIN_CDECL
39
40 /** \brief CQL parser handle (opaque pointer) */
41 typedef struct cql_parser *CQL_parser;
42
43 /** \brief creates a CQL parser.
44     \returns CCL parser
45
46     Returns CQL parser or NULL if parser could not be created.
47  */
48 YAZ_EXPORT
49 CQL_parser cql_parser_create(void);
50
51 /** \brief destroys a CQL parser.
52     \param cp CQL parser
53
54     This function does nothing if NULL if received.
55  */
56 YAZ_EXPORT
57 void cql_parser_destroy(CQL_parser cp);
58
59 /** \brief parses a CQL query (string)
60     \param cp CQL parser
61     \param str CQL string
62     \retval 0 success
63     \retval !=0 failure
64  */
65 YAZ_EXPORT
66 int cql_parser_string(CQL_parser cp, const char *str);
67
68 /** \brief parses CQL query (query stream)
69     \param cp CQL parser
70     \param getbyte function which reads one character from stream
71     \param ungetbyte function which unreads one character from stream
72     \param client_data data to be passed to stream functions
73     \retval 0 success
74     \retval !=0 failure
75
76     This function is similar to cql_parser_string but takes a
77     functions to read each query character from a stream.
78
79     The functions pointers getbytes, ungetbyte are similar to
80     that known from stdios getc, ungetc.
81 */
82 YAZ_EXPORT
83 int cql_parser_stream(CQL_parser cp,
84                       int (*getbyte)(void *client_data),
85                       void (*ungetbyte)(int b, void *client_data),
86                       void *client_data);
87
88 /** \brief parses CQL query (from FILE)
89     \param cp CQL parser
90     \param f file where query is read from
91     \retval 0 success
92     \retval !=0 failure
93
94     This function is similar to cql_parser_string but reads from
95     stdio FILE handle instead.
96 */
97 YAZ_EXPORT
98 int cql_parser_stdio(CQL_parser cp, FILE *f);
99
100 /** \brief configures strict mode
101     \param cp CQL parser
102     \param mode 1=enable strict mode, 0=disable strict mode
103
104     This function is similar to cql_parser_string but reads from
105     stdio FILE handle instead.
106 */
107 YAZ_EXPORT
108 void cql_parser_strict(CQL_parser cp, int mode);
109
110 /** \brief Node type: search term */
111 #define CQL_NODE_ST 1
112 /** \brief Node type: boolean */
113 #define CQL_NODE_BOOL 2
114 /** \brief Node type: sortby single spec */
115 #define CQL_NODE_SORT 3
116
117 /** \brief CQL parse tree (node)
118  */
119 struct cql_node {
120     /** node type */
121     int which;
122     union {
123         /** which == CQL_NODE_ST */
124         struct {
125             /** CQL index */
126             char *index;
127             /** CQL index URI or NULL if no URI */
128             char *index_uri;
129             /** Search term */
130             char *term;
131             /** relation */
132             char *relation;
133             /** relation URL or NULL if no relation URI) */
134             char *relation_uri;
135             /** relation modifiers */
136             struct cql_node *modifiers;
137             /** term list */
138             struct cql_node *extra_terms;
139         } st;
140         /** which == CQL_NODE_BOOL */
141         struct {
142             /** operator name "and", "or", ... */
143             char *value;
144             /** left operand */
145             struct cql_node *left;
146             /** right operand */
147             struct cql_node *right;
148             /** modifiers (NULL for no list) */
149             struct cql_node *modifiers;
150         } boolean;
151         /** which == CQL_NODE_SORT */
152         struct {
153             char *index;
154             /** next spec */
155             struct cql_node *next;
156             /** modifiers (NULL for no list) */
157             struct cql_node *modifiers;
158             /** search node */
159             struct cql_node *search;
160         } sort;
161     } u;
162 };
163
164 /** \brief Private structure that describes the CQL properties (profile)
165  */
166 struct cql_properties;
167
168 /** \brief Structure used by cql_buf_write_handler
169  */
170 struct cql_buf_write_info {
171     int max;
172     int off;
173     char *buf;
174 };
175
176 /** \brief Handler for cql_buf_write_info
177  */
178 YAZ_EXPORT
179 void cql_buf_write_handler(const char *b, void *client_data);
180
181 /** \brief Prints a CQL node and all sub nodes.
182     Hence this function prints the parse tree which is as returned by
183     cql_parser_result.
184 */
185 YAZ_EXPORT
186 void cql_node_print(struct cql_node *cn);
187
188 /** \brief creates a search clause node (st). */
189 YAZ_EXPORT
190 struct cql_node *cql_node_mk_sc(NMEM nmem, const char *index,
191                                 const char *relation, const char *term);
192
193 /** \brief applies a prefix+uri to "unresolved" index and relation URIs.
194     "unresolved" URIs are those nodes where member index_uri / relation_uri
195     is NULL.
196 */
197 YAZ_EXPORT
198 struct cql_node *cql_apply_prefix(NMEM nmem, struct cql_node *cn,
199                                   const char *prefix, const char *uri);
200
201 /** \brief creates a boolean node. */
202 YAZ_EXPORT
203 struct cql_node *cql_node_mk_boolean(NMEM nmem, const char *op);
204
205 /** \brief creates a sort single spec node. */
206 YAZ_EXPORT
207 struct cql_node *cql_node_mk_sort(NMEM nmem, const char *index,
208     struct cql_node *modifiers);
209
210 /** \brief destroys a node and its children. */
211 YAZ_EXPORT
212 void cql_node_destroy(struct cql_node *cn);
213
214 /** duplicates a node (returns a copy of supplied node) . */
215 YAZ_EXPORT
216 struct cql_node *cql_node_dup (NMEM nmem, struct cql_node *cp);
217
218 /** \brief returns the parse tree of the most recently parsed CQL query.
219     \param cp CQL parser
220     \returns CQL node or NULL for failure
221 */
222 YAZ_EXPORT
223 struct cql_node *cql_parser_result(CQL_parser cp);
224
225 /** \brief returns the sortby tree of the most recently parsed CQL query.
226     \param cp CQL parser
227     \returns CQL node or NULL for failure
228 */
229 YAZ_EXPORT
230 struct cql_node *cql_parser_sort_result(CQL_parser cp);
231
232 /** \brief converts CQL tree to XCQL and writes to user-defined stream
233     \param cn CQL node (tree)
234     \param pr print function
235     \param client_data data to be passed to pr function
236  */
237 YAZ_EXPORT
238 void cql_to_xml(struct cql_node *cn,
239                 void (*pr)(const char *buf, void *client_data),
240                 void *client_data);
241 /** \brief converts CQL tree to XCQL and writes to file
242     \param cn CQL node (tree)
243     \param f file handle
244  */
245 YAZ_EXPORT
246 void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
247
248 /** \brief converts CQL tree to XCQL and writes result to buffer
249     \param cn CQL node (tree)
250     \param out buffer
251     \param max size of buffer (max chars to write)
252     \returns length of resulting buffer
253  */
254 YAZ_EXPORT
255 int cql_to_xml_buf(struct cql_node *cn, char *out, int max);
256
257 /** \brief converts CQL tree to CCL and writes to user-defined stream
258     \param cn CQL node (tree)
259     \param pr print function
260     \param client_data data to be passed to pr function
261  */
262 YAZ_EXPORT
263 int cql_to_ccl(struct cql_node *cn,
264                void (*pr)(const char *buf, void *client_data),
265                void *client_data);
266
267 /** \brief converts CQL tree to CCL and writes to file
268     \param cn CQL node (tree)
269     \param f file handle
270  */
271 YAZ_EXPORT
272 void cql_to_ccl_stdio(struct cql_node *cn, FILE *f);
273
274 /** \brief converts CQL tree to CCL and writes result to buffer
275     \param cn CQL node (tree)
276     \param out buffer
277     \param max size of buffer (max chars to write)
278     \retval 0 OK
279     \retval -1 conversion error
280     \retval -2 buffer too small (truncated)
281  */
282 YAZ_EXPORT
283 int cql_to_ccl_buf(struct cql_node *cn, char *out, int max);
284
285 /** \brief stream handle for file (used by cql_to_xml_stdio) */
286 YAZ_EXPORT
287 void cql_fputs(const char *buf, void *client_data);
288
289 /** \brief CQL transform handle.
290     The transform describes how to convert from CQL to PQF (Type-1 AKA RPN).
291 */
292 typedef struct cql_transform_t_ *cql_transform_t;
293
294 /** \brief creates a CQL transform handle
295     \returns transform handle or NULL for failure
296 */
297 YAZ_EXPORT
298 cql_transform_t cql_transform_create(void);
299
300 /** \brief creates a CQL transform handle from am opened file handle
301     \param f file where transformation spec is read
302     \returns transform handle or NULL for failure
303
304     The transformation spec is read from a FILE handle which is assumed
305     opened for reading.
306 */
307 YAZ_EXPORT
308 cql_transform_t cql_transform_open_FILE (FILE *f);
309
310 /** \brief creates a CQL transform handle from a file
311     \param fname name of where transformation spec is read
312     \returns transform handle or NULL for failure
313 */
314 YAZ_EXPORT
315 cql_transform_t cql_transform_open_fname(const char *fname);
316
317
318 /** \brief defines CQL transform pattern
319     \param ct CQL transform handle
320     \param pattern pattern string
321     \param value pattern value
322     \returns 0 for succes; -1 for failure
323 */
324 YAZ_EXPORT
325 int cql_transform_define_pattern(cql_transform_t ct, const char *pattern,
326                                  const char *value);
327
328
329
330 /** \brief destroys a CQL transform handle
331     \param ct CQL transform handle
332  */
333 YAZ_EXPORT
334 void cql_transform_close(cql_transform_t ct);
335
336 /** \brief tranforms PQF given a CQL tree (NOT re-entrant)
337     \param ct CQL transform handle
338     \param cn CQL node tree
339     \param pr print function
340     \param client_data data to be passed to pr
341     \retval 0 success
342     \retval != 0 error
343
344     The result is written to a user-defined stream.
345 */
346 YAZ_EXPORT
347 int cql_transform(cql_transform_t ct,
348                   struct cql_node *cn,
349                   void (*pr)(const char *buf, void *client_data),
350                   void *client_data);
351
352 /** \brief tranforms PQF given a CQL tree (re-entrant)
353     \param ct CQL transform handle
354     \param cn CQL node tree
355     \param addinfo additional information (if error)
356     \param pr print function
357     \param client_data data to be passed to pr
358     \retval 0 success
359     \retval != 0 error code
360
361     The result is written to a user-defined stream.
362 */
363 int cql_transform_r(cql_transform_t ct, struct cql_node *cn,
364                     WRBUF addinfo,
365                     void (*pr)(const char *buf, void *client_data),
366                     void *client_data);
367
368 /** \brief transforms PQF given a CQL tree from FILE (not re-entrant)
369     \param ct CQL transform handle
370     \param cn CQL tree
371     \param f FILE where output is written
372     \retval 0 success
373     \retval !=0 failure (error code)
374
375     The result is written to a file specified by FILE handle (which must
376     be opened for writing.
377 */
378 YAZ_EXPORT
379 int cql_transform_FILE(cql_transform_t ct,
380                        struct cql_node *cn, FILE *f);
381
382 /** \brief transforms PQF given a CQL tree from buffer (not re-entrant)
383     \param ct CQL transform handle
384     \param cn CQL tree
385     \param out buffer for output
386     \param max maximum bytes for output (size of buffer)
387     \retval 0 success
388     \retval !=0 failure (error code)
389  */
390 YAZ_EXPORT
391 int cql_transform_buf(cql_transform_t ct,
392                       struct cql_node *cn, char *out, int max);
393
394 /** \brief returns additional information for last transform
395     \param ct CQL transform handle
396     \param addinfo additional info (result)
397     \returns error code
398  */
399 YAZ_EXPORT
400 int cql_transform_error(cql_transform_t ct, const char **addinfo);
401
402 /** \brief sets error and addinfo for transform
403     \param ct CQL transform handle
404     \param error error code
405     \param addinfo additional info
406  */
407 YAZ_EXPORT
408 void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo);
409
410 /** \brief returns the CQL message corresponding to a given error code.
411     \param code error code
412     \returns text message
413 */
414 YAZ_EXPORT
415 const char *cql_strerror(int code);
416
417 /** \brief returns the standard CQL context set URI.
418     \returns CQL URI string
419 */
420 YAZ_EXPORT
421 const char *cql_uri(void);
422
423 /** \brief compares two CQL strings (ala strcmp)
424     \param s1 string 1
425     \param s2 string 2
426     \returns comparison value
427     Compares two CQL strings (for relations, operators, etc)
428     (unfortunately defined as case-insensitive unlike XML etc)
429 */
430 YAZ_EXPORT
431 int cql_strcmp(const char *s1, const char *s2);
432
433 /** \brief compares two CQL strings (ala strncmp)
434     \param s1 string 1
435     \param s2 string 2
436     \param n size
437     \returns comparison value
438     Compares two CQL strings at most n bytes
439     (unfortunately defined as case-insensitive unlike XML etc)
440  */
441 YAZ_EXPORT
442 int cql_strncmp(const char *s1, const char *s2, size_t n);
443
444 /** \brief converts CQL sortby to sortkeys (ala versions 1.1)
445     \param cn CQL tree
446     \param pr print function
447     \param client_data data to be passed to pr function
448
449     This will take CQL_NODE_SORT entries and conver them to
450
451     path,schema,ascending,caseSensitive,missingValue
452     items..
453
454     One for each sort keys. Where
455
456     path is string index for sorting
457
458     schema is schema for sort index
459
460     ascending is a boolean (0=false, 1=true). Default is true.
461
462     caseSensitive is a boolean. Default is false.
463
464     missingValue is a string and one of 'abort', 'highValue', 'lowValue',
465     or 'omit'. Default is 'highValue'.
466
467     See also
468     http://www.loc.gov/standards/sru/sru1-1archive/search-retrieve-operation.html#sort
469 */
470 YAZ_EXPORT
471 int cql_sortby_to_sortkeys(struct cql_node *cn,
472                            void (*pr)(const char *buf, void *client_data),
473                            void *client_data);
474
475 /** \brief converts CQL sortby to sortkeys ..
476     \param cn CQL tree
477     \param out result buffer
478     \param max size of buffer (allocated)
479     \retval 0 OK
480     \retval -1 ERROR
481 */
482 YAZ_EXPORT
483 int cql_sortby_to_sortkeys_buf(struct cql_node *cn, char *out, int max);
484
485 YAZ_END_CDECL
486
487 #endif
488 /* CQL_H_INCLUDED */
489 /*
490  * Local variables:
491  * c-basic-offset: 4
492  * c-file-style: "Stroustrup"
493  * indent-tabs-mode: nil
494  * End:
495  * vim: shiftwidth=4 tabstop=8 expandtab
496  */
497