From: Adam Dickmeiss Date: Thu, 10 Apr 2014 13:47:13 +0000 (+0200) Subject: Merge branch 'yaz-756' X-Git-Tag: v5.1.0~10 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=0d6f3ee9720647761ff74414a46828c0b9711ac0;hp=5564216deccb49e138f665e223c81fe6c1edd79d Merge branch 'yaz-756' --- diff --git a/include/yaz/cql.h b/include/yaz/cql.h index 2dacfad..f1cdd78 100644 --- a/include/yaz/cql.h +++ b/include/yaz/cql.h @@ -33,6 +33,7 @@ #define CQL_H_INCLUDED #include #include +#include YAZ_BEGIN_CDECL @@ -332,7 +333,7 @@ int cql_transform_define_pattern(cql_transform_t ct, const char *pattern, YAZ_EXPORT void cql_transform_close(cql_transform_t ct); -/** \brief tranforms PQF given a CQL tree +/** \brief tranforms PQF given a CQL tree (NOT re-entrant) \param ct CQL transform handle \param cn CQL node tree \param pr print function @@ -348,7 +349,23 @@ int cql_transform(cql_transform_t ct, void (*pr)(const char *buf, void *client_data), void *client_data); -/** \brief transforms PQF given a CQL tree (from FILE) +/** \brief tranforms PQF given a CQL tree (re-entrant) + \param ct CQL transform handle + \param cn CQL node tree + \param addinfo additional information (if error) + \param pr print function + \param client_data data to be passed to pr + \retval 0 success + \retval != 0 error code + + The result is written to a user-defined stream. +*/ +int cql_transform_r(cql_transform_t ct, struct cql_node *cn, + WRBUF addinfo, + void (*pr)(const char *buf, void *client_data), + void *client_data); + +/** \brief transforms PQF given a CQL tree from FILE (not re-entrant) \param ct CQL transform handle \param cn CQL tree \param f FILE where output is written @@ -362,7 +379,7 @@ YAZ_EXPORT int cql_transform_FILE(cql_transform_t ct, struct cql_node *cn, FILE *f); -/** \brief transforms PQF given a CQL tree (from FILE) +/** \brief transforms PQF given a CQL tree from buffer (not re-entrant) \param ct CQL transform handle \param cn CQL tree \param out buffer for output diff --git a/include/yaz/rpn2cql.h b/include/yaz/rpn2cql.h index 3c6691f..a7afd0b 100644 --- a/include/yaz/rpn2cql.h +++ b/include/yaz/rpn2cql.h @@ -37,7 +37,25 @@ YAZ_BEGIN_CDECL -/** \brief transforms RPN query to CQL output stream +/** \brief transforms RPN query to CQL output stream (re-entrant) + \param ct CQL transform handle + \param addinfo for additional error info + \param pr print function + \param client_data opaque data to be passed to print handler + \param q RPN Query + \retval 0 success + \retval !=0 failure (error code) + */ +YAZ_EXPORT +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); + + +/** \brief transforms RPN query to CQL output stream (NOT re-entrant) \param ct CQL transform handle \param pr print function \param client_data opaque data to be passed to print handler @@ -52,7 +70,7 @@ int cql_transform_rpn2cql_stream(cql_transform_t ct, Z_RPNQuery *q); -/** \brief transforms RPN query to CQL WRBUF +/** \brief transforms RPN query to CQL WRBUF (NOT re-entrant) \param ct CQL transform handle \param w WRBUF handle for result \param q RPN Query @@ -60,9 +78,7 @@ int cql_transform_rpn2cql_stream(cql_transform_t ct, \retval !=0 failure (error code) */ YAZ_EXPORT -int cql_transform_rpn2cql_wrbuf(cql_transform_t ct, - WRBUF w, - Z_RPNQuery *q); +int cql_transform_rpn2cql_wrbuf(cql_transform_t ct, WRBUF w, Z_RPNQuery *q); /** \brief find a pattern that has a subset of attributes \param ct CQL transform handle diff --git a/include/yaz/rpn2solr.h b/include/yaz/rpn2solr.h index 42f1004..630137e 100644 --- a/include/yaz/rpn2solr.h +++ b/include/yaz/rpn2solr.h @@ -37,7 +37,23 @@ YAZ_BEGIN_CDECL -/** \brief transforms RPN query to SOLR output stream +/** \brief transforms RPN query to SOLR output stream (re-entrant) + \param ct SOLR transform handle + \param addinfo additional info on error + \param pr print function + \param client_data opaque data to be passed to print handler + \param q RPN Query + \retval 0 success + \retval !=0 failure (error code) + */ +YAZ_EXPORT +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); + +/** \brief transforms RPN query to SOLR output stream (NOT re-entrant) \param ct SOLR transform handle \param pr print function \param client_data opaque data to be passed to print handler diff --git a/include/yaz/solr.h b/include/yaz/solr.h index fc6d632..7cd7b4b 100644 --- a/include/yaz/solr.h +++ b/include/yaz/solr.h @@ -36,196 +36,10 @@ YAZ_BEGIN_CDECL -/** \brief SOLR parser handle (opaque pointer) */ -typedef struct solr_parser *SOLR_parser; - -/** \brief creates a SOLR parser. - \returns CCL parser - - Returns SOLR parser or NULL if parser could not be created. - */ -YAZ_EXPORT -SOLR_parser solr_parser_create(void); - -/** \brief destroys a SOLR parser. - \param cp SOLR parser - - This function does nothing if NULL if received. - */ -YAZ_EXPORT -void solr_parser_destroy(SOLR_parser cp); - -/** \brief parses a SOLR query (string) - \param cp SOLR parser - \param str SOLR string - \retval 0 success - \retval !=0 failure - */ -YAZ_EXPORT -int solr_parser_string(SOLR_parser cp, const char *str); - -/** \brief parses SOLR query (query stream) - \param cp SOLR parser - \param getbyte function which reads one character from stream - \param ungetbyte function which unreads one character from stream - \param client_data data to be passed to stream functions - \retval 0 success - \retval !=0 failure - - This function is similar to solr_parser_string but takes a - functions to read each query character from a stream. - - The functions pointers getbytes, ungetbyte are similar to - that known from stdios getc, ungetc. -*/ -YAZ_EXPORT -int solr_parser_stream(SOLR_parser cp, - int (*getbyte)(void *client_data), - void (*ungetbyte)(int b, void *client_data), - void *client_data); - -/** \brief parses SOLR query (from FILE) - \param cp SOLR parser - \param f file where query is read from - \retval 0 success - \retval !=0 failure - - This function is similar to solr_parser_string but reads from - stdio FILE handle instead. -*/ -YAZ_EXPORT -int solr_parser_stdio(SOLR_parser cp, FILE *f); - -/** \brief Node type: search term */ -#define SOLR_NODE_ST 1 -/** \brief Node type: boolean */ -#define SOLR_NODE_BOOL 2 -/** \brief SOLR parse tree (node) - */ -struct solr_node { - /** node type */ - int which; - union { - /** which == SOLR_NODE_ST */ - struct { - /** SOLR index */ - char *index; - /** SOLR index URI or NULL if no URI */ - char *index_uri; - /** Search term */ - char *term; - /** relation */ - char *relation; - /** relation URL or NULL if no relation URI) */ - char *relation_uri; - /** relation modifiers */ - struct solr_node *modifiers; - /** term list */ - struct solr_node *extra_terms; - } st; - /** which == SOLR_NODE_BOOL */ - struct { - /** operator name "and", "or", ... */ - char *value; - /** left operand */ - struct solr_node *left; - /** right operand */ - struct solr_node *right; - /** modifiers (NULL for no list) */ - struct solr_node *modifiers; - } boolean; - } u; -}; - -/** \brief Private structure that describes the SOLR properties (profile) - */ -struct solr_properties; - -/** \brief Structure used by solr_buf_write_handler - */ -struct solr_buf_write_info { - int max; - int off; - char *buf; -}; - -/** \brief Handler for solr_buf_write_info - */ -YAZ_EXPORT -void solr_buf_write_handler(const char *b, void *client_data); - -/** \brief Prints a SOLR node and all sub nodes. - Hence this function prints the parse tree which is as returned by - solr_parser_result. -*/ -YAZ_EXPORT -void solr_node_print(struct solr_node *cn); - -/** \brief creates a search clause node (st). */ -YAZ_EXPORT -struct solr_node *solr_node_mk_sc(NMEM nmem, const char *index, - const char *relation, const char *term); - -/** \brief applies a prefix+uri to "unresolved" index and relation URIs. - "unresolved" URIs are those nodes where member index_uri / relation_uri - is NULL. -*/ -YAZ_EXPORT -struct solr_node *solr_apply_prefix(NMEM nmem, struct solr_node *cn, - const char *prefix, const char *uri); - -/** \brief creates a boolean node. */ -YAZ_EXPORT -struct solr_node *solr_node_mk_boolean(NMEM nmem, const char *op); - -/** \brief destroys a node and its children. */ -YAZ_EXPORT -void solr_node_destroy(struct solr_node *cn); - -/** duplicates a node (returns a copy of supplied node) . */ -YAZ_EXPORT -struct solr_node *solr_node_dup (NMEM nmem, struct solr_node *cp); - -/** \brief returns the parse tree of the most recently parsed SOLR query. - \param cp SOLR parser - \returns SOLR node or NULL for failure -*/ -YAZ_EXPORT -struct solr_node *solr_parser_result(SOLR_parser cp); - -/** \brief converts SOLR tree to XSOLR and writes to user-defined stream - \param cn SOLR node (tree) - \param pr print function - \param client_data data to be passed to pr function - */ -YAZ_EXPORT -void solr_to_xml(struct solr_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data); -/** \brief converts SOLR tree to XSOLR and writes to file - \param cn SOLR node (tree) - \param f file handle - */ -YAZ_EXPORT -void solr_to_xml_stdio(struct solr_node *cn, FILE *f); - -/** \brief converts SOLR tree to XSOLR and writes result to buffer - \param cn SOLR node (tree) - \param out buffer - \param max size of buffer (max chars to write) - \returns length of resulting buffer - */ -YAZ_EXPORT -int solr_to_xml_buf(struct solr_node *cn, char *out, int max); - -/** \brief stream handle for file (used by solr_to_xml_stdio) */ -YAZ_EXPORT -void solr_fputs(const char *buf, void *client_data); - /** \brief SOLR transform handle. The transform describes how to convert from SOLR to PQF (Type-1 AKA RPN). */ -typedef struct solr_transform_t_ *solr_transform_t; +typedef struct cql_transform_t_ *solr_transform_t; /** \brief creates a SOLR transform handle \returns transform handle or NULL for failure @@ -241,7 +55,7 @@ solr_transform_t solr_transform_create(void); opened for reading. */ YAZ_EXPORT -solr_transform_t solr_transform_open_FILE (FILE *f); +solr_transform_t solr_transform_open_FILE(FILE *f); /** \brief creates a SOLR transform handle from a file \param fname name of where transformation spec is read @@ -261,56 +75,12 @@ YAZ_EXPORT int solr_transform_define_pattern(solr_transform_t ct, const char *pattern, const char *value); - - /** \brief destroys a SOLR transform handle \param ct SOLR transform handle */ YAZ_EXPORT void solr_transform_close(solr_transform_t ct); -/** \brief tranforms PQF given a SOLR tree - \param ct SOLR transform handle - \param cn SOLR node tree - \param pr print function - \param client_data data to be passed to pr - \retval 0 success - \retval != 0 error - - The result is written to a user-defined stream. -*/ -YAZ_EXPORT -int solr_transform(solr_transform_t ct, - struct solr_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data); - -/** \brief transforms PQF given a SOLR tree (from FILE) - \param ct SOLR transform handle - \param cn SOLR tree - \param f FILE where output is written - \retval 0 success - \retval !=0 failure (error code) - - The result is written to a file specified by FILE handle (which must - be opened for writing. -*/ -YAZ_EXPORT -int solr_transform_FILE(solr_transform_t ct, - struct solr_node *cn, FILE *f); - -/** \brief transforms PQF given a SOLR tree (from FILE) - \param ct SOLR transform handle - \param cn SOLR tree - \param out buffer for output - \param max maximum bytes for output (size of buffer) - \retval 0 success - \retval !=0 failure (error code) - */ -YAZ_EXPORT -int solr_transform_buf(solr_transform_t ct, - struct solr_node *cn, char *out, int max); - /** \brief returns additional information for last transform \param ct SOLR transform handle \param addinfo additional info (result) @@ -327,40 +97,6 @@ int solr_transform_error(solr_transform_t ct, const char **addinfo); YAZ_EXPORT void solr_transform_set_error(solr_transform_t ct, int error, const char *addinfo); -/** \brief returns the SOLR message corresponding to a given error code. - \param code error code - \returns text message -*/ -YAZ_EXPORT -const char *solr_strerror(int code); - -/** \brief returns the standard SOLR context set URI. - \returns SOLR URI string -*/ -YAZ_EXPORT -const char *solr_uri(void); - -/** \brief compares two SOLR strings (ala strcmp) - \param s1 string 1 - \param s2 string 2 - \returns comparison value - Compares two SOLR strings (for relations, operators, etc) - (unfortunately defined as case-insensitive unlike XML etc) -*/ -YAZ_EXPORT -int solr_strcmp(const char *s1, const char *s2); - -/** \brief compares two SOLR strings (ala strncmp) - \param s1 string 1 - \param s2 string 2 - \param n size - \returns comparison value - Compares two SOLR strings at most n bytes - (unfortunately defined as case-insensitive unlike XML etc) - */ -YAZ_EXPORT -int solr_strncmp(const char *s1, const char *s2, size_t n); - YAZ_END_CDECL #endif diff --git a/src/cqltransform.c b/src/cqltransform.c index 18c8b67..ff42293 100644 --- a/src/cqltransform.c +++ b/src/cqltransform.c @@ -44,8 +44,7 @@ struct cql_transform_t_ { struct cql_prop_entry *entry; yaz_tok_cfg_t tok_cfg; int error; - char *addinfo; - WRBUF w; + WRBUF addinfo; NMEM nmem; }; @@ -54,9 +53,8 @@ cql_transform_t cql_transform_create(void) { cql_transform_t ct = (cql_transform_t) xmalloc(sizeof(*ct)); ct->tok_cfg = yaz_tok_cfg_create(); - ct->w = wrbuf_alloc(); ct->error = 0; - ct->addinfo = 0; + ct->addinfo = wrbuf_alloc(); ct->entry = 0; ct->nmem = nmem_create(); return ct; @@ -70,6 +68,8 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, Z_AttributeElement *ae[20]; int ret = 0; /* 0=OK, != 0 FAIL */ int t; + WRBUF w = wrbuf_alloc(); + t = yaz_tok_move(tp); while (t == YAZ_TOK_STRING && ae_num < 20) @@ -83,7 +83,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem)); elem->attributeSet = 0; ae[ae_num] = elem; - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, yaz_tok_parse_string(tp)); wrbuf_puts(type_str, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); if (t == YAZ_TOK_EOF) @@ -95,8 +95,8 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, } if (t == YAZ_TOK_STRING) { - wrbuf_puts(ct->w, " "); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, " "); + wrbuf_puts(w, yaz_tok_parse_string(tp)); set_str = type_str; elem->attributeSet = @@ -159,10 +159,10 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, ca->num_semanticAction = 0; ca->semanticAction = 0; } - wrbuf_puts(ct->w, "="); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, "="); + wrbuf_puts(w, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); - wrbuf_puts(ct->w, " "); + wrbuf_puts(w, " "); ae_num++; } if (ret == 0) /* OK? */ @@ -172,7 +172,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, pp = &(*pp)->next; *pp = (struct cql_prop_entry *) xmalloc(sizeof(**pp)); (*pp)->pattern = xstrdup(pattern); - (*pp)->value = xstrdup(wrbuf_cstr(ct->w)); + (*pp)->value = xstrdup(wrbuf_cstr(w)); (*pp)->attr_list.num_attributes = ae_num; if (ae_num == 0) @@ -197,6 +197,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, odr_destroy(pr); } } + wrbuf_destroy(w); return ret; } @@ -222,7 +223,6 @@ cql_transform_t cql_transform_open_FILE(FILE *f) { yaz_tok_parse_t tp = yaz_tok_parse_buf(ct->tok_cfg, line); int t; - wrbuf_rewind(ct->w); t = yaz_tok_move(tp); if (t == YAZ_TOK_STRING) { @@ -267,9 +267,8 @@ void cql_transform_close(cql_transform_t ct) xfree(pe); pe = pe_next; } - xfree(ct->addinfo); + wrbuf_destroy(ct->addinfo); yaz_tok_cfg_destroy(ct->tok_cfg); - wrbuf_destroy(ct->w); nmem_destroy(ct->nmem); xfree(ct); } @@ -383,7 +382,7 @@ static const char *cql_lookup_property(cql_transform_t ct, return 0; } -int cql_pr_attr_uri(cql_transform_t ct, const char *category, +int cql_pr_attr_uri(cql_transform_t ct, WRBUF addinfo, const char *category, const char *uri, const char *val, const char *default_val, void (*pr)(const char *buf, void *client_data), void *client_data, @@ -459,27 +458,23 @@ int cql_pr_attr_uri(cql_transform_t ct, const char *category, while (*cp0 == ' ') cp0++; } - return 1; + return 0; } /* error ... */ - if (errcode && !ct->error) - { - ct->error = errcode; - if (val) - ct->addinfo = xstrdup(val); - else - ct->addinfo = 0; - } - return 0; + if (errcode == 0) + return 1; /* signal error, but do not set addinfo */ + if (val) + wrbuf_puts(addinfo, val); + return errcode; } -int cql_pr_attr(cql_transform_t ct, const char *category, +int cql_pr_attr(cql_transform_t ct, WRBUF addinfo, const char *category, const char *val, const char *default_val, void (*pr)(const char *buf, void *client_data), void *client_data, int errcode) { - return cql_pr_attr_uri(ct, category, 0 /* uri */, + return cql_pr_attr_uri(ct, addinfo, category, 0 /* uri */, val, default_val, pr, client_data, errcode); } @@ -496,6 +491,7 @@ static void cql_pr_int(int val, static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods, + WRBUF addinfo, void (*pr)(const char *buf, void *client_data), void *client_data) { @@ -527,9 +523,8 @@ static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods, proxrel = 6; else { - ct->error = YAZ_SRW_UNSUPP_PROX_RELATION; - ct->addinfo = xstrdup(relation); - return 0; + wrbuf_puts(addinfo, relation); + return YAZ_SRW_UNSUPP_PROX_RELATION; } } else if (!strcmp(name, "ordered")) @@ -548,16 +543,14 @@ static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods, unit = 8; else { - ct->error = YAZ_SRW_UNSUPP_PROX_UNIT; - ct->addinfo = xstrdup(term); - return 0; + wrbuf_puts(addinfo, term); + return YAZ_SRW_UNSUPP_PROX_UNIT; } } else { - ct->error = YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; - ct->addinfo = xstrdup(name); - return 0; + wrbuf_puts(addinfo, name); + return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; } mods = mods->u.st.modifiers; } @@ -572,7 +565,7 @@ static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods, (*pr)("k ", client_data); cql_pr_int(unit, pr, client_data); - return 1; + return 0; } /* ### checks for CQL relation-name rather than Type-1 attribute */ @@ -586,13 +579,13 @@ static int has_modifier(struct cql_node *cn, const char *name) { return 0; } -static void emit_term(cql_transform_t ct, - struct cql_node *cn, - const char *term, int length, - void (*pr)(const char *buf, void *client_data), - void *client_data) +static int emit_term(cql_transform_t ct, + struct cql_node *cn, WRBUF addinfo, + const char *term, int length, + void (*pr)(const char *buf, void *client_data), + void *client_data) { - int i; + int i, r; const char *ns = cn->u.st.index_uri; int z3958_mode = 0; int process_term = 1; @@ -604,8 +597,10 @@ static void emit_term(cql_transform_t ct, else if (cql_lookup_property(ct, "truncation", 0, "cql")) { process_term = 0; - cql_pr_attr(ct, "truncation", "cql", 0, - pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); + r = cql_pr_attr(ct, addinfo, "truncation", "cql", 0, + pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); + if (r) + return r; } assert(cn->which == CQL_NODE_ST); @@ -643,70 +638,92 @@ static void emit_term(cql_transform_t ct, } if (anchor == 3) { - cql_pr_attr(ct, "position", "firstAndLast", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + r = cql_pr_attr(ct, addinfo, "position", "firstAndLast", 0, + pr, client_data, + YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + if (r) + return r; term++; length -= 2; } else if (anchor == 1) { - cql_pr_attr(ct, "position", "first", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + r = cql_pr_attr(ct, addinfo, "position", "first", 0, + pr, client_data, + YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + if (r) + return r; term++; length--; } else if (anchor == 2) { - cql_pr_attr(ct, "position", "last", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + r = cql_pr_attr(ct, addinfo, "position", "last", 0, + pr, client_data, + YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + if (r) + return r; length--; } else { - cql_pr_attr(ct, "position", "any", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + r = cql_pr_attr(ct, addinfo, "position", "any", 0, + pr, client_data, + YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); + if (r) + return r; } if (z3958_mode == 0) { - if (trunc == 3 && cql_pr_attr(ct, "truncation", + if (trunc == 3 && !cql_pr_attr(ct, addinfo, "truncation", "both", 0, pr, client_data, 0)) { term++; length -= 2; } - else if (trunc == 1 && cql_pr_attr(ct, "truncation", + else if (trunc == 1 && !cql_pr_attr(ct, addinfo, "truncation", "left", 0, pr, client_data, 0)) { term++; length--; } - else if (trunc == 2 && cql_pr_attr(ct, "truncation", "right", 0, - pr, client_data, 0)) + else if (trunc == 2 && !cql_pr_attr(ct, addinfo, "truncation", + "right", 0, pr, client_data, 0)) { length--; } else if (trunc) z3958_mode = 1; else - cql_pr_attr(ct, "truncation", "none", 0, + cql_pr_attr(ct, addinfo, "truncation", "none", 0, pr, client_data, 0); } if (z3958_mode) - cql_pr_attr(ct, "truncation", "z3958", 0, - pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); + { + r = cql_pr_attr(ct, addinfo, "truncation", "z3958", 0, + pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); + if (r) + return r; + } } - if (ns) { - cql_pr_attr_uri(ct, "index", ns, - cn->u.st.index, "serverChoice", - pr, client_data, YAZ_SRW_UNSUPP_INDEX); + if (ns) + { + r = cql_pr_attr_uri(ct, addinfo, "index", ns, + cn->u.st.index, "serverChoice", + pr, client_data, YAZ_SRW_UNSUPP_INDEX); + if (r) + return r; } if (cn->u.st.modifiers) { struct cql_node *mod = cn->u.st.modifiers; for (; mod; mod = mod->u.st.modifiers) { - cql_pr_attr(ct, "relationModifier", mod->u.st.index, 0, - pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER); + r = cql_pr_attr(ct, addinfo, + "relationModifier", mod->u.st.index, 0, + pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER); + if (r) + return r; } } (*pr)("\"", client_data); @@ -757,24 +774,26 @@ static void emit_term(cql_transform_t ct, } } (*pr)("\" ", client_data); + return 0; } -static void emit_terms(cql_transform_t ct, - struct cql_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data, - const char *op) +static int emit_terms(cql_transform_t ct, struct cql_node *cn, + WRBUF addinfo, + void (*pr)(const char *buf, void *client_data), + void *client_data, + const char *op) { struct cql_node *ne = cn->u.st.extra_terms; + int r; if (ne) { (*pr)("@", client_data); (*pr)(op, client_data); (*pr)(" ", client_data); } - emit_term(ct, cn, cn->u.st.term, strlen(cn->u.st.term), - pr, client_data); - for (; ne; ne = ne->u.st.extra_terms) + r = emit_term(ct, cn, addinfo, cn->u.st.term, strlen(cn->u.st.term), + pr, client_data); + for (; !r && ne; ne = ne->u.st.extra_terms) { if (ne->u.st.extra_terms) { @@ -782,22 +801,24 @@ static void emit_terms(cql_transform_t ct, (*pr)(op, client_data); (*pr)(" ", client_data); } - emit_term(ct, cn, ne->u.st.term, strlen(ne->u.st.term), - pr, client_data); + r = emit_term(ct, cn, addinfo, ne->u.st.term, strlen(ne->u.st.term), + pr, client_data); } + return r; } -static void emit_wordlist(cql_transform_t ct, - struct cql_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data, - const char *op) +static int emit_wordlist(cql_transform_t ct, struct cql_node *cn, + WRBUF addinfo, + void (*pr)(const char *buf, void *client_data), + void *client_data, + const char *op) { + int r = 0; const char *cp0 = cn->u.st.term; const char *cp1; const char *last_term = 0; int last_length = 0; - while(cp0) + while (!r && cp0) { while (*cp0 == ' ') cp0++; @@ -807,7 +828,8 @@ static void emit_wordlist(cql_transform_t ct, (*pr)("@", client_data); (*pr)(op, client_data); (*pr)(" ", client_data); - emit_term(ct, cn, last_term, last_length, pr, client_data); + r = emit_term(ct, cn, addinfo, last_term, last_length, + pr, client_data); } last_term = cp0; if (cp1) @@ -816,20 +838,22 @@ static void emit_wordlist(cql_transform_t ct, last_length = strlen(cp0); cp0 = cp1; } - if (last_term) - emit_term(ct, cn, last_term, last_length, pr, client_data); + if (!r && last_term) + r = emit_term(ct, cn, addinfo, last_term, last_length, pr, client_data); + return r; } -void cql_transform_r(cql_transform_t ct, - struct cql_node *cn, +static int emit_node(cql_transform_t ct, struct cql_node *cn, + WRBUF addinfo, void (*pr)(const char *buf, void *client_data), void *client_data) { const char *ns; + int r = 0; struct cql_node *mods; if (!cn) - return; + return 0; switch (cn->which) { case CQL_NODE_ST: @@ -842,28 +866,29 @@ void cql_transform_r(cql_transform_t ct, (*pr)("@set \"", client_data); (*pr)(cn->u.st.term, client_data); (*pr)("\" ", client_data); - return ; + return 0; } } else { - if (!ct->error) - { - ct->error = YAZ_SRW_UNSUPP_CONTEXT_SET; - ct->addinfo = 0; - } - } - cql_pr_attr(ct, "always", 0, 0, pr, client_data, 0); - cql_pr_attr(ct, "relation", cn->u.st.relation, 0, pr, client_data, - YAZ_SRW_UNSUPP_RELATION); - cql_pr_attr(ct, "structure", cn->u.st.relation, 0, - pr, client_data, YAZ_SRW_UNSUPP_COMBI_OF_RELATION_AND_TERM); + return YAZ_SRW_UNSUPP_CONTEXT_SET; + } + cql_pr_attr(ct, addinfo, "always", 0, 0, pr, client_data, 0); + r = cql_pr_attr(ct, addinfo, "relation", cn->u.st.relation, 0, + pr, client_data, YAZ_SRW_UNSUPP_RELATION); + if (r) + return r; + r = cql_pr_attr(ct, addinfo, "structure", cn->u.st.relation, 0, + pr, client_data, + YAZ_SRW_UNSUPP_COMBI_OF_RELATION_AND_TERM); + if (r) + return r; if (cn->u.st.relation && !cql_strcmp(cn->u.st.relation, "all")) - emit_wordlist(ct, cn, pr, client_data, "and"); + r = emit_wordlist(ct, cn, addinfo, pr, client_data, "and"); else if (cn->u.st.relation && !cql_strcmp(cn->u.st.relation, "any")) - emit_wordlist(ct, cn, pr, client_data, "or"); + r = emit_wordlist(ct, cn, addinfo, pr, client_data, "or"); else - emit_terms(ct, cn, pr, client_data, "and"); + r = emit_terms(ct, cn, addinfo, pr, client_data, "and"); break; case CQL_NODE_BOOL: (*pr)("@", client_data); @@ -872,39 +897,42 @@ void cql_transform_r(cql_transform_t ct, mods = cn->u.boolean.modifiers; if (!strcmp(cn->u.boolean.value, "prox")) { - if (!cql_pr_prox(ct, mods, pr, client_data)) - return; + r = cql_pr_prox(ct, mods, addinfo, pr, client_data); + if (r) + return r; } else if (mods) { /* Boolean modifiers other than on proximity not supported */ - ct->error = YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; - ct->addinfo = xstrdup(mods->u.st.index); - return; + wrbuf_puts(addinfo, mods->u.st.index); + return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; } - cql_transform_r(ct, cn->u.boolean.left, pr, client_data); - cql_transform_r(ct, cn->u.boolean.right, pr, client_data); + r = emit_node(ct, cn->u.boolean.left, addinfo, pr, client_data); + if (r) + return r; + r = emit_node(ct, cn->u.boolean.right, addinfo, pr, client_data); + if (r) + return r; break; case CQL_NODE_SORT: - cql_transform_r(ct, cn->u.sort.search, pr, client_data); + r = emit_node(ct, cn->u.sort.search, addinfo, pr, client_data); break; default: fprintf(stderr, "Fatal: impossible CQL node-type %d\n", cn->which); abort(); } + return r; } -int cql_transform(cql_transform_t ct, struct cql_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data) +int cql_transform_r(cql_transform_t ct, struct cql_node *cn, + WRBUF addinfo, + void (*pr)(const char *buf, void *client_data), + void *client_data) { struct cql_prop_entry *e; NMEM nmem = nmem_create(); - - ct->error = 0; - xfree(ct->addinfo); - ct->addinfo = 0; + int r; for (e = ct->entry; e ; e = e->next) { @@ -913,11 +941,21 @@ int cql_transform(cql_transform_t ct, struct cql_node *cn, else if (!cql_strcmp(e->pattern, "set")) cql_apply_prefix(nmem, cn, 0, e->value); } - cql_transform_r(ct, cn, pr, client_data); + r = emit_node(ct, cn, addinfo, pr, client_data); nmem_destroy(nmem); - return ct->error; + return r; } +int cql_transform(cql_transform_t ct, struct cql_node *cn, + void (*pr)(const char *buf, void *client_data), + void *client_data) +{ + WRBUF addinfo = wrbuf_alloc(); + int r = cql_transform_r(ct, cn, addinfo, pr, client_data); + cql_transform_set_error(ct, r, wrbuf_cstr(addinfo)); + wrbuf_destroy(addinfo); + return r; +} int cql_transform_FILE(cql_transform_t ct, struct cql_node *cn, FILE *f) { @@ -939,9 +977,8 @@ int cql_transform_buf(cql_transform_t ct, struct cql_node *cn, SRW diagnostic is deprecated, but it's so perfect for our purposes that it would be stupid not to use it. */ char numbuf[30]; - ct->error = YAZ_SRW_TOO_MANY_CHARS_IN_QUERY; sprintf(numbuf, "%ld", (long) info.max); - ct->addinfo = xstrdup(numbuf); + cql_transform_set_error(ct, YAZ_SRW_TOO_MANY_CHARS_IN_QUERY, numbuf); return -1; } if (info.off >= 0) @@ -951,14 +988,15 @@ int cql_transform_buf(cql_transform_t ct, struct cql_node *cn, int cql_transform_error(cql_transform_t ct, const char **addinfo) { - *addinfo = ct->addinfo; + *addinfo = wrbuf_len(ct->addinfo) ? wrbuf_cstr(ct->addinfo) : 0; return ct->error; } void cql_transform_set_error(cql_transform_t ct, int error, const char *addinfo) { - xfree(ct->addinfo); - ct->addinfo = addinfo ? xstrdup(addinfo) : 0; + wrbuf_rewind(ct->addinfo); + if (addinfo) + wrbuf_puts(ct->addinfo, addinfo); ct->error = error; } diff --git a/src/rpn2cql.c b/src/rpn2cql.c index fb1c6fb..842d1a9 100644 --- a/src/rpn2cql.c +++ b/src/rpn2cql.c @@ -20,11 +20,6 @@ #include #include /* For yaz_prox_unit_name() */ -static void wrbuf_vputs(const char *buf, void *client_data) -{ - wrbuf_write((WRBUF) client_data, buf, strlen(buf)); -} - static const char *lookup_index_from_string_attr(Z_AttributeList *attributes) { int j; @@ -122,9 +117,8 @@ static int rpn2cql_attr(cql_transform_t ct, if (!index) { - cql_transform_set_error(ct, - YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, 0); - return -1; + wrbuf_rewind(w); + return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE; } /* for serverChoice we omit index+relation+structure */ if (strcmp(index, "cql.serverChoice")) @@ -180,11 +174,10 @@ static int rpn2cql_simple(cql_transform_t ct, void *client_data, Z_Operand *q, WRBUF w) { - int ret = 0; if (q->which != Z_Operand_APT) { - ret = -1; - cql_transform_set_error(ct, YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM, 0); + wrbuf_rewind(w); + return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM; } else { @@ -194,9 +187,12 @@ static int rpn2cql_simple(cql_transform_t ct, size_t lterm = 0; Odr_int trunc = lookup_truncation(apt->attributes); size_t i; + int r; wrbuf_rewind(w); - ret = rpn2cql_attr(ct, apt->attributes, w); + r = rpn2cql_attr(ct, apt->attributes, w); + if (r) + return r; switch (term->which) { @@ -212,8 +208,9 @@ static int rpn2cql_simple(cql_transform_t ct, lterm = strlen(sterm); break; default: - cql_transform_set_error(ct, YAZ_BIB1_TERM_TYPE_UNSUPP, 0); - return -1; + wrbuf_rewind(w); + wrbuf_printf(w, "%d", term->which); + return YAZ_BIB1_TERM_TYPE_UNSUPP; } if (trunc <= 3 || trunc == 100 || trunc == 102 || trunc == 104) @@ -266,14 +263,13 @@ static int rpn2cql_simple(cql_transform_t ct, } else { - cql_transform_set_error( - ct, YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE, 0); - ret = -1; + wrbuf_rewind(w); + wrbuf_printf(w, ODR_INT_PRINTF, trunc); + return YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE; } - if (ret == 0) - pr(wrbuf_cstr(w), client_data); + pr(wrbuf_cstr(w), client_data); } - return ret; + return 0; } @@ -297,7 +293,7 @@ static int rpn2cql_structure(cql_transform_t ct, r = rpn2cql_structure(ct, pr, client_data, q->u.complex->s1, 1, w); if (r) return r; - switch(op->which) + switch (op->which) { case Z_Operator_and: pr(" and ", client_data); @@ -318,10 +314,10 @@ static int rpn2cql_structure(cql_transform_t ct, pr("/distance", client_data); if (!prox->relationType || *prox->relationType < Z_ProximityOperator_Prox_lessThan || - *prox->relationType > Z_ProximityOperator_Prox_notEqual) { - cql_transform_set_error(ct, YAZ_BIB1_UNSUPP_SEARCH, - "unrecognised proximity relationType"); - return -1; + *prox->relationType > Z_ProximityOperator_Prox_notEqual) + { + wrbuf_rewind(w); + return YAZ_BIB1_UNSUPP_SEARCH; } pr(op2name[*prox->relationType-1], client_data); sprintf(buf, "%ld", (long) *prox->distance); @@ -350,15 +346,29 @@ static int rpn2cql_structure(cql_transform_t ct, } } +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) +{ + /* addinfo (w) is used for both addinfo and house-keeping ! */ + int r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, addinfo); + if (!r) + wrbuf_rewind(addinfo); /* no additional info if no error */ + return r; +} + + int cql_transform_rpn2cql_stream(cql_transform_t ct, void (*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q) { - int r; WRBUF w = wrbuf_alloc(); - cql_transform_set_error(ct, 0, 0); - r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, w); + int r = cql_transform_rpn2cql_stream_r(ct, w, pr, client_data, q); + if (r) + cql_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0); wrbuf_destroy(w); return r; } @@ -368,7 +378,7 @@ int cql_transform_rpn2cql_wrbuf(cql_transform_t ct, WRBUF w, Z_RPNQuery *q) { - return cql_transform_rpn2cql_stream(ct, wrbuf_vputs, w, q); + return cql_transform_rpn2cql_stream(ct, wrbuf_vp_puts, w, q); } /* diff --git a/src/rpn2solr.c b/src/rpn2solr.c index c9143c7..f790ea2 100644 --- a/src/rpn2solr.c +++ b/src/rpn2solr.c @@ -19,11 +19,6 @@ #include #include -static void wrbuf_vputs(const char *buf, void *client_data) -{ - wrbuf_write((WRBUF) client_data, buf, strlen(buf)); -} - static const char *lookup_index_from_string_attr(Z_AttributeList *attributes) { int j; @@ -158,15 +153,11 @@ static int rpn2solr_attr(solr_transform_t ct, const char *index = solr_lookup_reverse(ct, "index.", attributes); const char *structure = solr_lookup_reverse(ct, "structure.", attributes); - /* if transform (properties) do not match, we'll just use a USE string attribute (bug #2978) */ + /* if no real match, try string attribute */ if (!index) index = lookup_index_from_string_attr(attributes); if (!index) - { - solr_transform_set_error(ct, - YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, 0); - return -1; - } + return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE; /* for serverChoice we omit index+relation+structure */ if (strcmp(index, "cql.serverChoice")) { @@ -229,8 +220,7 @@ static int emit_term(solr_transform_t ct, WRBUF w, Z_Term *term, Odr_int trunc) lterm = strlen(sterm); break; default: - solr_transform_set_error(ct, YAZ_BIB1_TERM_TYPE_UNSUPP, 0); - return -1; + return YAZ_BIB1_TERM_TYPE_UNSUPP; } if (sterm) @@ -295,8 +285,7 @@ static int rpn2solr_simple(solr_transform_t ct, relation1 = lookup_relation_index_from_attr(apt->attributes); if (!relation1) { - solr_transform_set_error(ct, YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE, 0); - return -1; + return YAZ_BIB1_UNSUPP_RELATION_ATTRIBUTE; } if (apt2) { @@ -313,8 +302,7 @@ static int rpn2solr_simple(solr_transform_t ct, ; else { - solr_transform_set_error(ct, YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE, 0); - return -1; + return YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE; } if (!relation1) @@ -358,18 +346,14 @@ static int rpn2solr_simple(solr_transform_t ct, static int rpn2solr_structure(solr_transform_t ct, void (*pr)(const char *buf, void *client_data), - void *client_data, + void *client_data, Z_RPNStructure *q, int nested, WRBUF w) { if (q->which == Z_RPNStructure_simple) { if (q->u.simple->which != Z_Operand_APT) - { - solr_transform_set_error( - ct, YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM, 0); - return -1; - } + return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM; else return rpn2solr_simple(ct, pr, client_data, q->u.simple->u.attributesPlusTerm, w, 0); @@ -388,20 +372,19 @@ static int rpn2solr_structure(solr_transform_t ct, r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s1, 1, w); if (r) return r; - switch(op->which) + switch (op->which) { - case Z_Operator_and: + case Z_Operator_and: pr(" AND ", client_data); break; - case Z_Operator_or: + case Z_Operator_or: pr(" OR ", client_data); break; - case Z_Operator_and_not: + case Z_Operator_and_not: pr(" AND NOT ", client_data); break; - case Z_Operator_prox: - solr_transform_set_error(ct, YAZ_BIB1_UNSUPP_SEARCH, 0); - return -1; + case Z_Operator_prox: + return YAZ_BIB1_UNSUPP_SEARCH; } r = rpn2solr_structure(ct, pr, client_data, q->u.complex->s2, 1, w); if (nested) @@ -410,25 +393,37 @@ static int rpn2solr_structure(solr_transform_t ct, } } +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) +{ + int r = rpn2solr_structure(ct, pr, client_data, q->RPNStructure, + /* nested*/ 0, addinfo); + if (!r) + wrbuf_rewind(addinfo); + return r; +} + int solr_transform_rpn2solr_stream(solr_transform_t ct, void (*pr)(const char *buf, void *client_data), void *client_data, Z_RPNQuery *q) { - int r; WRBUF w = wrbuf_alloc(); - solr_transform_set_error(ct, 0, 0); - r = rpn2solr_structure(ct, pr, client_data, q->RPNStructure, 0, w); + int r = solr_transform_rpn2solr_stream_r(ct, w, pr, client_data, q); + if (r) + solr_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0); wrbuf_destroy(w); return r; } - int solr_transform_rpn2solr_wrbuf(solr_transform_t ct, WRBUF w, Z_RPNQuery *q) { - return solr_transform_rpn2solr_stream(ct, wrbuf_vputs, w, q); + return solr_transform_rpn2solr_stream(ct, wrbuf_vp_puts, w, q); } /* diff --git a/src/solrtransform.c b/src/solrtransform.c index 09cfc09..7151174 100644 --- a/src/solrtransform.c +++ b/src/solrtransform.c @@ -4,7 +4,8 @@ */ /** * \file solrtransform.c - * \brief Implements SOLR transform (SOLR to RPN conversion). + * \brief Old wrappers + * */ #if HAVE_CONFIG_H #include @@ -13,951 +14,53 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct solr_prop_entry { - char *pattern; - char *value; - Z_AttributeList attr_list; - struct solr_prop_entry *next; -}; - -struct solr_transform_t_ { - struct solr_prop_entry *entry; - yaz_tok_cfg_t tok_cfg; - int error; - char *addinfo; - WRBUF w; - NMEM nmem; -}; - - -/* TODO Utility functions, split out into separate file */ -int solr_strcmp(const char *s1, const char *s2) { - return cql_strcmp(s1, s2); -} - -int solr_strncmp(const char *s1, const char *s2, size_t n) { - return cql_strncmp(s1, s2, n); -} - -/* TODO FIX */ -const char *solr_uri(void) -{ - return "TODO:SOLR URI"; -} - -void solr_buf_write_handler (const char *b, void *client_data) -{ - struct solr_buf_write_info *info = (struct solr_buf_write_info *)client_data; - int l = strlen(b); - if (info->off < 0 || (info->off + l >= info->max)) - { - info->off = -1; - return; - } - memcpy (info->buf + info->off, b, l); - info->off += l; -} - - -/* Utility functions end */ +#include +#include solr_transform_t solr_transform_create(void) { - solr_transform_t ct = (solr_transform_t) xmalloc(sizeof(*ct)); - ct->tok_cfg = yaz_tok_cfg_create(); - ct->w = wrbuf_alloc(); - ct->error = 0; - ct->addinfo = 0; - ct->entry = 0; - ct->nmem = nmem_create(); - return ct; -} - -static int solr_transform_parse_tok_line(solr_transform_t ct, - const char *pattern, - yaz_tok_parse_t tp) -{ - int ae_num = 0; - Z_AttributeElement *ae[20]; - int ret = 0; /* 0=OK, != 0 FAIL */ - int t; - t = yaz_tok_move(tp); - - while (t == YAZ_TOK_STRING && ae_num < 20) - { - WRBUF type_str = wrbuf_alloc(); - WRBUF set_str = 0; - Z_AttributeElement *elem = 0; - const char *value_str = 0; - /* attset type=value OR type=value */ - - elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem)); - elem->attributeSet = 0; - ae[ae_num] = elem; - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); - wrbuf_puts(type_str, yaz_tok_parse_string(tp)); - t = yaz_tok_move(tp); - if (t == YAZ_TOK_EOF) - { - wrbuf_destroy(type_str); - if (set_str) - wrbuf_destroy(set_str); - break; - } - if (t == YAZ_TOK_STRING) - { - wrbuf_puts(ct->w, " "); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); - set_str = type_str; - - elem->attributeSet = - yaz_string_to_oid_nmem(yaz_oid_std(), CLASS_ATTSET, - wrbuf_cstr(set_str), ct->nmem); - - type_str = wrbuf_alloc(); - wrbuf_puts(type_str, yaz_tok_parse_string(tp)); - t = yaz_tok_move(tp); - } - elem->attributeType = nmem_intdup(ct->nmem, 0); - if (sscanf(wrbuf_cstr(type_str), ODR_INT_PRINTF, elem->attributeType) - != 1) - { - wrbuf_destroy(type_str); - if (set_str) - wrbuf_destroy(set_str); - yaz_log(YLOG_WARN, "Expected numeric attribute type"); - ret = -1; - break; - } - - wrbuf_destroy(type_str); - if (set_str) - wrbuf_destroy(set_str); - - if (t != '=') - { - yaz_log(YLOG_WARN, "Expected = after after attribute type"); - ret = -1; - break; - } - t = yaz_tok_move(tp); - if (t != YAZ_TOK_STRING) /* value */ - { - yaz_log(YLOG_WARN, "Missing attribute value"); - ret = -1; - break; - } - value_str = yaz_tok_parse_string(tp); - if (yaz_isdigit(*value_str)) - { - elem->which = Z_AttributeValue_numeric; - elem->value.numeric = - nmem_intdup(ct->nmem, atoi(value_str)); - } - else - { - Z_ComplexAttribute *ca = (Z_ComplexAttribute *) - nmem_malloc(ct->nmem, sizeof(*ca)); - elem->which = Z_AttributeValue_complex; - elem->value.complex = ca; - ca->num_list = 1; - ca->list = (Z_StringOrNumeric **) - nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric *)); - ca->list[0] = (Z_StringOrNumeric *) - nmem_malloc(ct->nmem, sizeof(Z_StringOrNumeric)); - ca->list[0]->which = Z_StringOrNumeric_string; - ca->list[0]->u.string = nmem_strdup(ct->nmem, value_str); - ca->num_semanticAction = 0; - ca->semanticAction = 0; - } - wrbuf_puts(ct->w, "="); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); - t = yaz_tok_move(tp); - wrbuf_puts(ct->w, " "); - ae_num++; - } - if (ret == 0) /* OK? */ - { - struct solr_prop_entry **pp = &ct->entry; - while (*pp) - pp = &(*pp)->next; - *pp = (struct solr_prop_entry *) xmalloc(sizeof(**pp)); - (*pp)->pattern = xstrdup(pattern); - (*pp)->value = xstrdup(wrbuf_cstr(ct->w)); - - (*pp)->attr_list.num_attributes = ae_num; - if (ae_num == 0) - (*pp)->attr_list.attributes = 0; - else - { - (*pp)->attr_list.attributes = (Z_AttributeElement **) - nmem_malloc(ct->nmem, - ae_num * sizeof(Z_AttributeElement *)); - memcpy((*pp)->attr_list.attributes, ae, - ae_num * sizeof(Z_AttributeElement *)); - } - (*pp)->next = 0; - - if (0) - { - ODR pr = odr_createmem(ODR_PRINT); - Z_AttributeList *alp = &(*pp)->attr_list; - odr_setprint(pr, yaz_log_file()); - z_AttributeList(pr, &alp, 0, 0); - odr_setprint(pr, 0); - odr_destroy(pr); - } - } - return ret; -} - -int solr_transform_define_pattern(solr_transform_t ct, const char *pattern, - const char *value) -{ - int r; - yaz_tok_parse_t tp = yaz_tok_parse_buf(ct->tok_cfg, value); - yaz_tok_cfg_single_tokens(ct->tok_cfg, "="); - r = solr_transform_parse_tok_line(ct, pattern, tp); - yaz_tok_parse_destroy(tp); - return r; + return cql_transform_create(); } solr_transform_t solr_transform_open_FILE(FILE *f) { - solr_transform_t ct = solr_transform_create(); - char line[1024]; - - yaz_tok_cfg_single_tokens(ct->tok_cfg, "="); - - while (fgets(line, sizeof(line)-1, f)) - { - yaz_tok_parse_t tp = yaz_tok_parse_buf(ct->tok_cfg, line); - int t; - wrbuf_rewind(ct->w); - t = yaz_tok_move(tp); - if (t == YAZ_TOK_STRING) - { - char * pattern = xstrdup(yaz_tok_parse_string(tp)); - t = yaz_tok_move(tp); - if (t != '=') - { - yaz_tok_parse_destroy(tp); - solr_transform_close(ct); - return 0; - } - if (solr_transform_parse_tok_line(ct, pattern, tp)) - { - yaz_tok_parse_destroy(tp); - solr_transform_close(ct); - return 0; - } - xfree(pattern); - } - else if (t != YAZ_TOK_EOF) - { - yaz_tok_parse_destroy(tp); - solr_transform_close(ct); - return 0; - } - yaz_tok_parse_destroy(tp); - } - return ct; -} - -void solr_transform_close(solr_transform_t ct) -{ - struct solr_prop_entry *pe; - if (!ct) - return; - pe = ct->entry; - while (pe) - { - struct solr_prop_entry *pe_next = pe->next; - xfree(pe->pattern); - xfree(pe->value); - xfree(pe); - pe = pe_next; - } - xfree(ct->addinfo); - yaz_tok_cfg_destroy(ct->tok_cfg); - wrbuf_destroy(ct->w); - nmem_destroy(ct->nmem); - xfree(ct); + return cql_transform_open_FILE(f); } solr_transform_t solr_transform_open_fname(const char *fname) { - solr_transform_t ct; - FILE *f = fopen(fname, "r"); - if (!f) - return 0; - ct = solr_transform_open_FILE(f); - fclose(f); - return ct; -} - -static int compare_attr(Z_AttributeElement *a, Z_AttributeElement *b) -{ - ODR odr_a = odr_createmem(ODR_ENCODE); - ODR odr_b = odr_createmem(ODR_ENCODE); - int len_a, len_b; - char *buf_a, *buf_b; - int ret; - - z_AttributeElement(odr_a, &a, 0, 0); - z_AttributeElement(odr_b, &b, 0, 0); - - buf_a = odr_getbuf(odr_a, &len_a, 0); - buf_b = odr_getbuf(odr_b, &len_b, 0); - - ret = yaz_memcmp(buf_a, buf_b, len_a, len_b); - - odr_destroy(odr_a); - odr_destroy(odr_b); - return ret; -} - -const char *solr_lookup_reverse(solr_transform_t ct, - const char *category, - Z_AttributeList *attributes) -{ - struct solr_prop_entry *e; - size_t clen = strlen(category); - for (e = ct->entry; e; e = e->next) - { - if (!strncmp(e->pattern, category, clen)) - { - /* category matches.. See if attributes in pattern value - are all listed in actual attributes */ - int i; - for (i = 0; i < e->attr_list.num_attributes; i++) - { - /* entry attribute */ - Z_AttributeElement *e_ae = e->attr_list.attributes[i]; - int j; - for (j = 0; j < attributes->num_attributes; j++) - { - /* actual attribute */ - Z_AttributeElement *a_ae = attributes->attributes[j]; - int r = compare_attr(e_ae, a_ae); - if (r == 0) - break; - } - if (j == attributes->num_attributes) - break; /* i was not found at all.. try next pattern */ - - } - if (i == e->attr_list.num_attributes) - return e->pattern + clen; - } - } - return 0; -} - -static const char *solr_lookup_property(solr_transform_t ct, - const char *pat1, const char *pat2, - const char *pat3) -{ - char pattern[120]; - struct solr_prop_entry *e; - - if (pat1 && pat2 && pat3) - sprintf(pattern, "%.39s.%.39s.%.39s", pat1, pat2, pat3); - else if (pat1 && pat2) - sprintf(pattern, "%.39s.%.39s", pat1, pat2); - else if (pat1 && pat3) - sprintf(pattern, "%.39s.%.39s", pat1, pat3); - else if (pat1) - sprintf(pattern, "%.39s", pat1); - else - return 0; - - for (e = ct->entry; e; e = e->next) - { - if (!solr_strcmp(e->pattern, pattern)) - return e->value; - } - return 0; + return cql_transform_open_fname(fname); } -int solr_pr_attr_uri(solr_transform_t ct, const char *category, - const char *uri, const char *val, const char *default_val, - void (*pr)(const char *buf, void *client_data), - void *client_data, - int errcode) +int solr_transform_define_pattern(cql_transform_t ct, const char *pattern, + const char *value) { - const char *res = 0; - const char *eval = val ? val : default_val; - const char *prefix = 0; - - if (uri) - { - struct solr_prop_entry *e; - - for (e = ct->entry; e; e = e->next) - if (!memcmp(e->pattern, "set.", 4) && e->value && - !strcmp(e->value, uri)) - { - prefix = e->pattern+4; - break; - } - /* must have a prefix now - if not it's an error */ - } - - if (!uri || prefix) - { - if (!res) - res = solr_lookup_property(ct, category, prefix, eval); - /* we have some aliases for some relations unfortunately.. */ - if (!res && !prefix && !strcmp(category, "relation")) - { - if (!strcmp(val, "==")) - res = solr_lookup_property(ct, category, prefix, "exact"); - if (!strcmp(val, "=")) - res = solr_lookup_property(ct, category, prefix, "eq"); - if (!strcmp(val, "<=")) - res = solr_lookup_property(ct, category, prefix, "le"); - if (!strcmp(val, ">=")) - res = solr_lookup_property(ct, category, prefix, "ge"); - } - if (!res) - res = solr_lookup_property(ct, category, prefix, "*"); - } - if (res) - { - char buf[64]; - - const char *cp0 = res, *cp1; - while ((cp1 = strchr(cp0, '='))) - { - int i; - while (*cp1 && *cp1 != ' ') - cp1++; - if (cp1 - cp0 >= (ptrdiff_t) sizeof(buf)) - break; - memcpy(buf, cp0, cp1 - cp0); - buf[cp1-cp0] = 0; - (*pr)("@attr ", client_data); - - for (i = 0; buf[i]; i++) - { - if (buf[i] == '*') - (*pr)(eval, client_data); - else - { - char tmp[2]; - tmp[0] = buf[i]; - tmp[1] = '\0'; - (*pr)(tmp, client_data); - } - } - (*pr)(" ", client_data); - cp0 = cp1; - while (*cp0 == ' ') - cp0++; - } - return 1; - } - /* error ... */ - if (errcode && !ct->error) - { - ct->error = errcode; - if (val) - ct->addinfo = xstrdup(val); - else - ct->addinfo = 0; - } - return 0; + return cql_transform_define_pattern(ct, pattern, value); } -int solr_pr_attr(solr_transform_t ct, const char *category, - const char *val, const char *default_val, - void (*pr)(const char *buf, void *client_data), - void *client_data, - int errcode) -{ - return solr_pr_attr_uri(ct, category, 0 /* uri */, - val, default_val, pr, client_data, errcode); -} - - -static void solr_pr_int(int val, - void (*pr)(const char *buf, void *client_data), - void *client_data) -{ - char buf[21]; /* enough characters to 2^64 */ - sprintf(buf, "%d", val); - (*pr)(buf, client_data); - (*pr)(" ", client_data); -} - - -static int solr_pr_prox(solr_transform_t ct, struct solr_node *mods, - void (*pr)(const char *buf, void *client_data), - void *client_data) -{ - int exclusion = 0; - int distance = -1; - int ordered = 0; - int proxrel = 2; /* less than or equal */ - int unit = 2; /* word */ - - while (mods) - { - const char *name = mods->u.st.index; - const char *term = mods->u.st.term; - const char *relation = mods->u.st.relation; - - if (!strcmp(name, "distance")) { - distance = strtol(term, (char**) 0, 0); - if (!strcmp(relation, "=")) - proxrel = 3; - else if (!strcmp(relation, ">")) - proxrel = 5; - else if (!strcmp(relation, "<")) - proxrel = 1; - else if (!strcmp(relation, ">=")) - proxrel = 4; - else if (!strcmp(relation, "<=")) - proxrel = 2; - else if (!strcmp(relation, "<>")) - proxrel = 6; - else - { - ct->error = YAZ_SRW_UNSUPP_PROX_RELATION; - ct->addinfo = xstrdup(relation); - return 0; - } - } - else if (!strcmp(name, "ordered")) - ordered = 1; - else if (!strcmp(name, "unordered")) - ordered = 0; - else if (!strcmp(name, "unit")) - { - if (!strcmp(term, "word")) - unit = 2; - else if (!strcmp(term, "sentence")) - unit = 3; - else if (!strcmp(term, "paragraph")) - unit = 4; - else if (!strcmp(term, "element")) - unit = 8; - else - { - ct->error = YAZ_SRW_UNSUPP_PROX_UNIT; - ct->addinfo = xstrdup(term); - return 0; - } - } - else - { - ct->error = YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; - ct->addinfo = xstrdup(name); - return 0; - } - mods = mods->u.st.modifiers; - } - - if (distance == -1) - distance = (unit == 2) ? 1 : 0; - - solr_pr_int(exclusion, pr, client_data); - solr_pr_int(distance, pr, client_data); - solr_pr_int(ordered, pr, client_data); - solr_pr_int(proxrel, pr, client_data); - (*pr)("k ", client_data); - solr_pr_int(unit, pr, client_data); - - return 1; -} - -/* Returns location of first wildcard character in the `length' - * characters starting at `term', or a null pointer of there are - * none -- like memchr(). - */ -static const char *wcchar(int start, const char *term, int length) -{ - while (length > 0) - { - if (start || term[-1] != '\\') - if (strchr("*?", *term)) - return term; - term++; - length--; - start = 0; - } - return 0; -} - - -/* ### checks for SOLR relation-name rather than Type-1 attribute */ -static int has_modifier(struct solr_node *cn, const char *name) { - struct solr_node *mod; - for (mod = cn->u.st.modifiers; mod != 0; mod = mod->u.st.modifiers) { - if (!strcmp(mod->u.st.index, name)) - return 1; - } - - return 0; -} - - -static void emit_term(solr_transform_t ct, - struct solr_node *cn, - const char *term, int length, - void (*pr)(const char *buf, void *client_data), - void *client_data) -{ - int i; - const char *ns = cn->u.st.index_uri; - int process_term = !has_modifier(cn, "regexp"); - char *z3958_mem = 0; - - assert(cn->which == SOLR_NODE_ST); - - if (process_term && length > 0) - { - if (length > 1 && term[0] == '^' && term[length-1] == '^') - { - solr_pr_attr(ct, "position", "firstAndLast", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); - term++; - length -= 2; - } - else if (term[0] == '^') - { - solr_pr_attr(ct, "position", "first", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); - term++; - length--; - } - else if (term[length-1] == '^') - { - solr_pr_attr(ct, "position", "last", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); - length--; - } - else - { - solr_pr_attr(ct, "position", "any", 0, - pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); - } - } - - if (process_term && length > 0) - { - const char *first_wc = wcchar(1, term, length); - const char *second_wc = first_wc ? - wcchar(0, first_wc+1, length-(first_wc-term)-1) : 0; - - /* Check for well-known globbing patterns that represent - * simple truncation attributes as expected by, for example, - * Bath-compliant server. If we find such a pattern but - * there's no mapping for it, that's fine: we just use a - * general pattern-matching attribute. - */ - if (first_wc == term && second_wc == term + length-1 - && *first_wc == '*' && *second_wc == '*' - && solr_pr_attr(ct, "truncation", "both", 0, pr, client_data, 0)) - { - term++; - length -= 2; - } - else if (first_wc == term && second_wc == 0 && *first_wc == '*' - && solr_pr_attr(ct, "truncation", "left", 0, - pr, client_data, 0)) - { - term++; - length--; - } - else if (first_wc == term + length-1 && second_wc == 0 - && *first_wc == '*' - && solr_pr_attr(ct, "truncation", "right", 0, - pr, client_data, 0)) - { - length--; - } - else if (first_wc) - { - /* We have one or more wildcard characters, but not in a - * way that can be dealt with using only the standard - * left-, right- and both-truncation attributes. We need - * to translate the pattern into a Z39.58-type pattern, - * which has been supported in BIB-1 since 1996. If - * there's no configuration element for "truncation.z3958" - * we indicate this as error 28 "Masking character not - * supported". - */ - int i; - solr_pr_attr(ct, "truncation", "z3958", 0, - pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); - z3958_mem = (char *) xmalloc(length+1); - for (i = 0; i < length; i++) - { - if (i > 0 && term[i-1] == '\\') - z3958_mem[i] = term[i]; - else if (term[i] == '*') - z3958_mem[i] = '?'; - else if (term[i] == '?') - z3958_mem[i] = '#'; - else - z3958_mem[i] = term[i]; - } - z3958_mem[length] = '\0'; - term = z3958_mem; - } - else { - /* No masking characters. Use "truncation.none" if given. */ - solr_pr_attr(ct, "truncation", "none", 0, - pr, client_data, 0); - } - } - if (ns) { - solr_pr_attr_uri(ct, "index", ns, - cn->u.st.index, "serverChoice", - pr, client_data, YAZ_SRW_UNSUPP_INDEX); - } - if (cn->u.st.modifiers) - { - struct solr_node *mod = cn->u.st.modifiers; - for (; mod; mod = mod->u.st.modifiers) - { - solr_pr_attr(ct, "relationModifier", mod->u.st.index, 0, - pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER); - } - } - - (*pr)("\"", client_data); - for (i = 0; iu.st.extra_terms; - if (ne) - { - (*pr)("@", client_data); - (*pr)(op, client_data); - (*pr)(" ", client_data); - } - emit_term(ct, cn, cn->u.st.term, strlen(cn->u.st.term), - pr, client_data); - for (; ne; ne = ne->u.st.extra_terms) - { - if (ne->u.st.extra_terms) - { - (*pr)("@", client_data); - (*pr)(op, client_data); - (*pr)(" ", client_data); - } - emit_term(ct, cn, ne->u.st.term, strlen(ne->u.st.term), - pr, client_data); - } -} - -static void emit_wordlist(solr_transform_t ct, - struct solr_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data, - const char *op) -{ - const char *cp0 = cn->u.st.term; - const char *cp1; - const char *last_term = 0; - int last_length = 0; - while(cp0) - { - while (*cp0 == ' ') - cp0++; - cp1 = strchr(cp0, ' '); - if (last_term) - { - (*pr)("@", client_data); - (*pr)(op, client_data); - (*pr)(" ", client_data); - emit_term(ct, cn, last_term, last_length, pr, client_data); - } - last_term = cp0; - if (cp1) - last_length = cp1 - cp0; - else - last_length = strlen(cp0); - cp0 = cp1; - } - if (last_term) - emit_term(ct, cn, last_term, last_length, pr, client_data); -} - -void solr_transform_r(solr_transform_t ct, - struct solr_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data) -{ - const char *ns; - struct solr_node *mods; - - if (!cn) - return; - switch (cn->which) - { - case SOLR_NODE_ST: - ns = cn->u.st.index_uri; - if (ns) - { - /* TODO If relevant fix with solr_uri */ - if (!strcmp(ns, solr_uri()) - && cn->u.st.index && !solr_strcmp(cn->u.st.index, "resultSet")) - { - (*pr)("@set \"", client_data); - (*pr)(cn->u.st.term, client_data); - (*pr)("\" ", client_data); - return ; - } - } - else - { - if (!ct->error) - { - ct->error = YAZ_SRW_UNSUPP_CONTEXT_SET; - ct->addinfo = 0; - } - } - solr_pr_attr(ct, "always", 0, 0, pr, client_data, 0); - solr_pr_attr(ct, "relation", cn->u.st.relation, 0, pr, client_data, - YAZ_SRW_UNSUPP_RELATION); - solr_pr_attr(ct, "structure", cn->u.st.relation, 0, - pr, client_data, YAZ_SRW_UNSUPP_COMBI_OF_RELATION_AND_TERM); - if (cn->u.st.relation && !solr_strcmp(cn->u.st.relation, "all")) - emit_wordlist(ct, cn, pr, client_data, "and"); - else if (cn->u.st.relation && !solr_strcmp(cn->u.st.relation, "any")) - emit_wordlist(ct, cn, pr, client_data, "or"); - else - emit_terms(ct, cn, pr, client_data, "and"); - break; - case SOLR_NODE_BOOL: - (*pr)("@", client_data); - (*pr)(cn->u.boolean.value, client_data); - (*pr)(" ", client_data); - mods = cn->u.boolean.modifiers; - if (!strcmp(cn->u.boolean.value, "prox")) - { - if (!solr_pr_prox(ct, mods, pr, client_data)) - return; - } - else if (mods) - { - /* Boolean modifiers other than on proximity not supported */ - ct->error = YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER; - ct->addinfo = xstrdup(mods->u.st.index); - return; - } - - solr_transform_r(ct, cn->u.boolean.left, pr, client_data); - solr_transform_r(ct, cn->u.boolean.right, pr, client_data); - break; - - default: - fprintf(stderr, "Fatal: impossible SOLR node-type %d\n", cn->which); - abort(); - } -} - -int solr_transform(solr_transform_t ct, struct solr_node *cn, - void (*pr)(const char *buf, void *client_data), - void *client_data) +void solr_transform_close(solr_transform_t ct) { - struct solr_prop_entry *e; - NMEM nmem = nmem_create(); - - ct->error = 0; - xfree(ct->addinfo); - ct->addinfo = 0; - - for (e = ct->entry; e ; e = e->next) - { - /* TODO remove as SOLR dont supports sets. - if (!solr_strncmp(e->pattern, "set.", 4)) - solr_apply_prefix(nmem, cn, e->pattern+4, e->value); - else if (!solr_strcmp(e->pattern, "set")) - solr_apply_prefix(nmem, cn, 0, e->value); - */ - } - solr_transform_r(ct, cn, pr, client_data); - nmem_destroy(nmem); - return ct->error; + cql_transform_close(ct); } - -int solr_transform_FILE(solr_transform_t ct, struct solr_node *cn, FILE *f) +int solr_transform_error(solr_transform_t ct, const char **addinfo) { - /* We can use the cql_fputs util */ - return solr_transform(ct, cn, cql_fputs, f); + return cql_transform_error(ct, addinfo); } -int solr_transform_buf(solr_transform_t ct, struct solr_node *cn, char *out, int max) +void solr_transform_set_error(solr_transform_t ct, int error, + const char *addinfo) { - struct solr_buf_write_info info; - int r; - - info.off = 0; - info.max = max; - info.buf = out; - r = solr_transform(ct, cn, cql_buf_write_handler, &info); - if (info.off < 0) { - /* Attempt to write past end of buffer. For some reason, this - SRW diagnostic is deprecated, but it's so perfect for our - purposes that it would be stupid not to use it. */ - char numbuf[30]; - ct->error = YAZ_SRW_TOO_MANY_CHARS_IN_QUERY; - sprintf(numbuf, "%ld", (long) info.max); - ct->addinfo = xstrdup(numbuf); - return -1; - } - if (info.off >= 0) - info.buf[info.off] = '\0'; - return r; + cql_transform_set_error(ct, error, addinfo); } -int solr_transform_error(solr_transform_t ct, const char **addinfo) +const char *solr_lookup_reverse(solr_transform_t ct, + const char *category, + Z_AttributeList *attributes) { - *addinfo = ct->addinfo; - return ct->error; + return cql_lookup_reverse(ct, category, attributes); } -void solr_transform_set_error(solr_transform_t ct, int error, const char *addinfo) -{ - xfree(ct->addinfo); - ct->addinfo = addinfo ? xstrdup(addinfo) : 0; - ct->error = error; -} /* * Local variables: diff --git a/src/zoom-query.c b/src/zoom-query.c index 2fc197d..a9b0941 100644 --- a/src/zoom-query.c +++ b/src/zoom-query.c @@ -136,12 +136,6 @@ Z_SortKeySpecList *ZOOM_query_get_sortspec(ZOOM_query s) return s->sort_strategy == SORT_STRATEGY_Z3950 ? s->sort_spec : 0; } -static void cql2pqf_wrbuf_puts(const char *buf, void *client_data) -{ - WRBUF wrbuf = (WRBUF) client_data; - wrbuf_puts(wrbuf, buf); -} - const char *ZOOM_query_get_query_string(ZOOM_query s) { return wrbuf_cstr(s->full_query); @@ -194,7 +188,7 @@ static char *cql2pqf(ZOOM_connection c, const char *cql) { WRBUF wrbuf_result = wrbuf_alloc(); error = cql_transform(trans, cql_parser_result(parser), - cql2pqf_wrbuf_puts, wrbuf_result); + wrbuf_vp_puts, wrbuf_result); if (error != 0) { char buf[512]; const char *addinfo; diff --git a/test/test_rpn2cql.c b/test/test_rpn2cql.c index 0d929e5..0d05fab 100644 --- a/test/test_rpn2cql.c +++ b/test/test_rpn2cql.c @@ -15,7 +15,8 @@ #include #include -static int compare(cql_transform_t ct, const char *pqf, const char *cql) +static int compare2(cql_transform_t ct, const char *pqf, const char *cql, + int expected_error) { int ret = 0; ODR odr = odr_createmem(ODR_ENCODE); @@ -28,15 +29,26 @@ static int compare(cql_transform_t ct, const char *pqf, const char *cql) if (r != 0) { + const char *addinfo = 0; + int err = cql_transform_error(ct, &addinfo); /* transform error */ yaz_log(YLOG_LOG, "%s -> Error %d", pqf, r); - if (!cql) /* also expected error? */ - ret = 1; + if (err == 0) + ; + else if (err == expected_error) + { + if (addinfo && cql && !strcmp(addinfo, cql)) + ret = 1; + else if (!addinfo && !cql) + ret = 1; + } } else if (r == 0) { yaz_log(YLOG_LOG, "%s -> %s", pqf, wrbuf_cstr(w)); - if (cql && !strcmp(wrbuf_cstr(w), cql)) + if (!expected_error) + ret = 1; + else if (cql && !strcmp(wrbuf_cstr(w), cql)) { ret = 1; } @@ -52,6 +64,11 @@ static int compare(cql_transform_t ct, const char *pqf, const char *cql) return ret; } +static int compare(cql_transform_t ct, const char *pqf, const char *cql) +{ + return compare2(ct, pqf, cql, 0); +} + static void tst1(void) { cql_transform_t ct = cql_transform_create(); @@ -65,7 +82,7 @@ static void tst1(void) YAZ_CHECK(compare(ct, "@and @and a b @and c d", "(a and b) and (c and d)")); YAZ_CHECK(compare(ct, "@attr 1=field abc", "field=abc")); - YAZ_CHECK(compare(ct, "@attr 1=4 abc", 0)); /* should fail */ + YAZ_CHECK(compare2(ct, "@attr 1=4 abc", 0, 114)); /* should fail */ cql_transform_define_pattern(ct, "index.title", "1=4"); YAZ_CHECK(compare(ct, "@attr 1=4 abc", "title=abc")); @@ -151,7 +168,8 @@ static void tst2(void) /* Other */ YAZ_CHECK(compare(ct, "@attr 2=103 @attr 1=_ALLRECORDS 1", "cql.allRecords=1")); - YAZ_CHECK(compare(ct, "@attr 1=500 abc", 0)); + YAZ_CHECK(compare2(ct, "@attr 1=500 abc", 0, 114)); + YAZ_CHECK(compare2(ct, "@attr 5=99 x", "99", 120)); cql_transform_close(ct); wrbuf_destroy(w); } diff --git a/util/cql2pqf.c b/util/cql2pqf.c index eec4767..0baa175 100644 --- a/util/cql2pqf.c +++ b/util/cql2pqf.c @@ -10,13 +10,17 @@ #include #include +#include #include #include static void usage(void) { - fprintf(stderr, "usage\n cql2pqf [-n ] [-r] [-S] " + fprintf(stderr, "usage\n cql2pqf [-n ] [-r] [-s] [-S] " "[]\n"); + fprintf(stderr, " -r reverse conversion (RPN to Solr/CQL)\n"); + fprintf(stderr, " -s Solr instead of CQL\n"); + fprintf(stderr, " -S strict CQL 2.0\n"); exit(1); } @@ -27,13 +31,14 @@ int main(int argc, char **argv) char *query = 0; char *fname = 0; int reverse = 0; + int solr = 0; int verbose = 0; int do_strict = 0; int ret; char *arg; - while ((ret = options("n:rSv", argv, argc, &arg)) != -2) + while ((ret = options("n:rsSv", argv, argc, &arg)) != -2) { switch (ret) { @@ -52,6 +57,9 @@ int main(int argc, char **argv) case 'S': do_strict = 1; break; + case 's': + solr = 1; + break; case 'v': verbose = 1; break; @@ -59,17 +67,17 @@ int main(int argc, char **argv) usage(); } } - if (!fname) - usage(); - if (!strcmp(fname, "-")) - ct = cql_transform_create(); - else - ct = cql_transform_open_fname(fname); - if (!ct) + if (fname) { - fprintf(stderr, "failed to read properties %s\n", fname); - exit(1); + ct = cql_transform_open_fname(fname); + if (!ct) + { + fprintf(stderr, "failed to read properties %s\n", fname); + exit(1); + } } + else + ct = cql_transform_create(); if (reverse) { @@ -78,7 +86,11 @@ int main(int argc, char **argv) if (!query) { if (fgets(buf, sizeof buf, stdin)) + { + if (*buf && buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; query = buf; + } } if (query) { @@ -91,9 +103,13 @@ int main(int argc, char **argv) } else { - int ret = cql_transform_rpn2cql_stream(ct, cql_fputs, + int ret = 0; + if (solr) + ret = solr_transform_rpn2solr_stream(ct, cql_fputs, + stdout, rpn); + else + ret = cql_transform_rpn2cql_stream(ct, cql_fputs, stdout, rpn); - if (ret) { const char *addinfo; @@ -125,6 +141,10 @@ int main(int argc, char **argv) if (r) fprintf(stderr, "Syntax error\n"); + else if (solr) + { + printf("CQL to Solr not supported (supported is reverse -r)\n"); + } else { r = cql_transform_FILE(ct, cql_parser_result(cp), stdout);