The re-entrant functions are: cql_transform_r,
cql_transform_rpn2cql_stream_r, solr_transform_rpn2solr_stream_r.
These have same functionality as cql_transform,
cql_transform_rpn2cql_stream, solr_transform_rpn2solr_stream. They
return the additional infomration as WRBUF to make them re-entrant.
#define CQL_H_INCLUDED
#include <stdio.h>
#include <yaz/nmem.h>
#define CQL_H_INCLUDED
#include <stdio.h>
#include <yaz/nmem.h>
YAZ_EXPORT
void cql_transform_close(cql_transform_t ct);
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
\param ct CQL transform handle
\param cn CQL node tree
\param pr print function
void (*pr)(const char *buf, void *client_data),
void *client_data);
void (*pr)(const char *buf, void *client_data),
void *client_data);
-/** \brief tranforms PQF given a CQL tree
+/** \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 ct CQL transform handle
\param cn CQL node tree
\param addinfo additional information (if error)
The result is written to a user-defined stream.
*/
The result is written to a user-defined stream.
*/
-int cql_transform_cql2rpn(cql_transform_t ct, struct cql_node *cn,
- char **addinfo,
- 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);
-/** \brief transforms PQF given a CQL tree (from FILE)
+/** \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
\param ct CQL transform handle
\param cn CQL tree
\param f FILE where output is written
int cql_transform_FILE(cql_transform_t ct,
struct cql_node *cn, FILE *f);
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
\param ct CQL transform handle
\param cn CQL tree
\param out buffer for output
-/** \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
\param ct CQL transform handle
\param pr print function
\param client_data opaque data to be passed to print handler
-/** \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
\param ct CQL transform handle
\param w WRBUF handle for result
\param q RPN Query
\retval !=0 failure (error code)
*/
YAZ_EXPORT
\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
/** \brief find a pattern that has a subset of attributes
\param ct CQL transform handle
-/** \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
\param ct SOLR transform handle
\param pr print function
\param client_data opaque data to be passed to print handler
-int cql_pr_attr_uri(cql_transform_t ct, char **addinfo, 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,
const char *uri, const char *val, const char *default_val,
void (*pr)(const char *buf, void *client_data),
void *client_data,
if (errcode == 0)
return 1; /* signal error, but do not set addinfo */
if (val)
if (errcode == 0)
return 1; /* signal error, but do not set addinfo */
if (val)
- *addinfo = xstrdup(val);
+ wrbuf_puts(addinfo, val);
-int cql_pr_attr(cql_transform_t ct, char **addinfo, 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,
const char *val, const char *default_val,
void (*pr)(const char *buf, void *client_data),
void *client_data,
static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods,
static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods,
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
- *addinfo = xstrdup(relation);
+ wrbuf_puts(addinfo, relation);
return YAZ_SRW_UNSUPP_PROX_RELATION;
}
}
return YAZ_SRW_UNSUPP_PROX_RELATION;
}
}
- *addinfo = xstrdup(term);
+ wrbuf_puts(addinfo, term);
return YAZ_SRW_UNSUPP_PROX_UNIT;
}
}
else
{
return YAZ_SRW_UNSUPP_PROX_UNIT;
}
}
else
{
- *addinfo = xstrdup(name);
+ wrbuf_puts(addinfo, name);
return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER;
}
mods = mods->u.st.modifiers;
return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER;
}
mods = mods->u.st.modifiers;
}
static int emit_term(cql_transform_t ct,
}
static int emit_term(cql_transform_t ct,
- struct cql_node *cn, char **addinfo,
+ struct cql_node *cn, WRBUF addinfo,
const char *term, int length,
void (*pr)(const char *buf, void *client_data),
void *client_data)
const char *term, int length,
void (*pr)(const char *buf, void *client_data),
void *client_data)
}
static int emit_terms(cql_transform_t ct, struct cql_node *cn,
}
static int emit_terms(cql_transform_t ct, struct cql_node *cn,
void (*pr)(const char *buf, void *client_data),
void *client_data,
const char *op)
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,
}
static int emit_wordlist(cql_transform_t ct, struct cql_node *cn,
void (*pr)(const char *buf, void *client_data),
void *client_data,
const char *op)
void (*pr)(const char *buf, void *client_data),
void *client_data,
const char *op)
-int cql_transform_r(cql_transform_t ct, struct cql_node *cn,
- char **addinfo,
- void (*pr)(const char *buf, void *client_data),
- void *client_data)
+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;
{
const char *ns;
int r = 0;
return YAZ_SRW_UNSUPP_CONTEXT_SET;
}
cql_pr_attr(ct, addinfo, "always", 0, 0, pr, client_data, 0);
return YAZ_SRW_UNSUPP_CONTEXT_SET;
}
cql_pr_attr(ct, addinfo, "always", 0, 0, pr, client_data, 0);
else if (mods)
{
/* Boolean modifiers other than on proximity not supported */
else if (mods)
{
/* Boolean modifiers other than on proximity not supported */
- *addinfo = xstrdup(mods->u.st.index);
+ wrbuf_puts(addinfo, mods->u.st.index);
return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER;
}
return YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER;
}
- r = cql_transform_r(ct, cn->u.boolean.left, addinfo, pr, client_data);
+ r = emit_node(ct, cn->u.boolean.left, addinfo, pr, client_data);
- r = cql_transform_r(ct, cn->u.boolean.right, addinfo, pr, client_data);
+ r = emit_node(ct, cn->u.boolean.right, addinfo, pr, client_data);
if (r)
return r;
break;
case CQL_NODE_SORT:
if (r)
return r;
break;
case CQL_NODE_SORT:
- r = cql_transform_r(ct, cn->u.sort.search, addinfo, 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);
break;
default:
fprintf(stderr, "Fatal: impossible CQL node-type %d\n", cn->which);
-int cql_transform_cql2rpn(cql_transform_t ct, struct cql_node *cn,
- char **addinfo,
- 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();
{
struct cql_prop_entry *e;
NMEM nmem = nmem_create();
else if (!cql_strcmp(e->pattern, "set"))
cql_apply_prefix(nmem, cn, 0, e->value);
}
else if (!cql_strcmp(e->pattern, "set"))
cql_apply_prefix(nmem, cn, 0, e->value);
}
- r = cql_transform_r(ct, cn, addinfo, pr, client_data);
+ r = emit_node(ct, cn, addinfo, pr, client_data);
nmem_destroy(nmem);
return r;
}
nmem_destroy(nmem);
return r;
}
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
- char *addinfo = 0;
- int r = cql_transform_cql2rpn(ct, cn, &addinfo, pr, client_data);
- cql_transform_set_error(ct, r, addinfo);
- xfree(addinfo);
+ 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);
relation = lookup_relation_index_from_attr(attributes);
if (!index)
relation = lookup_relation_index_from_attr(attributes);
if (!index)
return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
/* for serverChoice we omit index+relation+structure */
if (strcmp(index, "cql.serverChoice"))
{
/* for serverChoice we omit index+relation+structure */
if (strcmp(index, "cql.serverChoice"))
{
Z_Operand *q, WRBUF w)
{
if (q->which != Z_Operand_APT)
Z_Operand *q, WRBUF w)
{
if (q->which != Z_Operand_APT)
return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
else
{
Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
else
{
Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
lterm = strlen(sterm);
break;
default:
lterm = strlen(sterm);
break;
default:
+ wrbuf_rewind(w);
+ wrbuf_printf(w, "%d", term->which);
return YAZ_BIB1_TERM_TYPE_UNSUPP;
}
return YAZ_BIB1_TERM_TYPE_UNSUPP;
}
+ wrbuf_rewind(w);
+ wrbuf_printf(w, ODR_INT_PRINTF, trunc);
return YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE;
}
pr(wrbuf_cstr(w), client_data);
return YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE;
}
pr(wrbuf_cstr(w), client_data);
*prox->relationType < Z_ProximityOperator_Prox_lessThan ||
*prox->relationType > Z_ProximityOperator_Prox_notEqual)
{
*prox->relationType < Z_ProximityOperator_Prox_lessThan ||
*prox->relationType > Z_ProximityOperator_Prox_notEqual)
{
return YAZ_BIB1_UNSUPP_SEARCH;
}
pr(op2name[*prox->relationType-1], client_data);
return YAZ_BIB1_UNSUPP_SEARCH;
}
pr(op2name[*prox->relationType-1], client_data);
+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 cql_transform_rpn2cql_stream(cql_transform_t ct,
void (*pr)(const char *buf, void *client_data),
void *client_data,
Z_RPNQuery *q)
{
- r = rpn2cql_structure(ct, pr, client_data, q->RPNStructure, 0, w);
+ int r = cql_transform_rpn2cql_stream_r(ct, w, pr, client_data, q);
- cql_transform_set_error(ct, r, 0);
+ cql_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
wrbuf_destroy(w);
return r;
}
wrbuf_destroy(w);
return r;
}
+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 solr_transform_rpn2solr_stream(solr_transform_t ct,
void (*pr)(const char *buf, void *client_data),
void *client_data,
Z_RPNQuery *q)
{
- r = rpn2solr_structure(ct, pr, client_data, q->RPNStructure, 0, w);
+ int r = solr_transform_rpn2solr_stream_r(ct, w, pr, client_data, q);
- solr_transform_set_error(ct, r, 0);
+ solr_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
wrbuf_destroy(w);
return r;
}
wrbuf_destroy(w);
return r;
}
int solr_transform_rpn2solr_wrbuf(solr_transform_t ct,
WRBUF w,
Z_RPNQuery *q)
int solr_transform_rpn2solr_wrbuf(solr_transform_t ct,
WRBUF w,
Z_RPNQuery *q)
#include <yaz/wrbuf.h>
#include <yaz/pquery.h>
#include <yaz/wrbuf.h>
#include <yaz/pquery.h>
-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);
{
int ret = 0;
ODR odr = odr_createmem(ODR_ENCODE);
+ const char *addinfo = 0;
+ int err = cql_transform_error(ct, &addinfo);
/* transform error */
yaz_log(YLOG_LOG, "%s -> Error %d", pqf, r);
/* 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));
}
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))
+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();
static void tst1(void)
{
cql_transform_t ct = cql_transform_create();
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, "@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"));
cql_transform_define_pattern(ct, "index.title", "1=4");
YAZ_CHECK(compare(ct, "@attr 1=4 abc", "title=abc"));
/* Other */
YAZ_CHECK(compare(ct, "@attr 2=103 @attr 1=_ALLRECORDS 1", "cql.allRecords=1"));
/* 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);
}
cql_transform_close(ct);
wrbuf_destroy(w);
}