#define CQL_H_INCLUDED
#include <stdio.h>
#include <yaz/nmem.h>
+#include <yaz/wrbuf.h>
YAZ_BEGIN_CDECL
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
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)
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
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
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
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
\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
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
return 0;
}
-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,
if (errcode == 0)
return 1; /* signal error, but do not set addinfo */
if (val)
- *addinfo = xstrdup(val);
+ wrbuf_puts(addinfo, val);
return errcode;
}
-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,
static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods,
- char **addinfo,
+ WRBUF addinfo,
void (*pr)(const char *buf, void *client_data),
void *client_data)
{
proxrel = 6;
else
{
- *addinfo = xstrdup(relation);
+ wrbuf_puts(addinfo, relation);
return YAZ_SRW_UNSUPP_PROX_RELATION;
}
}
unit = 8;
else
{
- *addinfo = xstrdup(term);
+ wrbuf_puts(addinfo, term);
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;
}
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)
}
static int emit_terms(cql_transform_t ct, struct cql_node *cn,
- char **addinfo,
+ WRBUF addinfo,
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,
- char **addinfo,
+ WRBUF addinfo,
void (*pr)(const char *buf, void *client_data),
void *client_data,
const char *op)
return r;
}
-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;
}
else
{
- *addinfo = 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 */
- *addinfo = xstrdup(mods->u.st.index);
+ wrbuf_puts(addinfo, mods->u.st.index);
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);
if (r)
return r;
- 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:
- 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);
return r;
}
-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();
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;
}
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);
return r;
}
relation = lookup_relation_index_from_attr(attributes);
if (!index)
+ {
+ wrbuf_rewind(w);
return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
+ }
/* for serverChoice we omit index+relation+structure */
if (strcmp(index, "cql.serverChoice"))
{
Z_Operand *q, WRBUF w)
{
if (q->which != Z_Operand_APT)
+ {
+ wrbuf_rewind(w);
return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
+ }
else
{
Z_AttributesPlusTerm *apt = q->u.attributesPlusTerm;
lterm = strlen(sterm);
break;
default:
+ wrbuf_rewind(w);
+ wrbuf_printf(w, "%d", term->which);
return YAZ_BIB1_TERM_TYPE_UNSUPP;
}
}
else
{
+ wrbuf_rewind(w);
+ wrbuf_printf(w, ODR_INT_PRINTF, trunc);
return YAZ_BIB1_UNSUPP_TRUNCATION_ATTRIBUTE;
}
pr(wrbuf_cstr(w), client_data);
*prox->relationType < Z_ProximityOperator_Prox_lessThan ||
*prox->relationType > Z_ProximityOperator_Prox_notEqual)
{
+ wrbuf_rewind(w);
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 r;
WRBUF w = wrbuf_alloc();
- 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, 0);
+ cql_transform_set_error(ct, r, wrbuf_len(w) ? wrbuf_cstr(w) : 0);
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 r;
WRBUF w = wrbuf_alloc();
- 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, 0);
+ 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)
#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);
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;
}
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();
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"));
/* 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);
}