From 5ae134cc01cf31868aa2adaa7daf801993e7c1e3 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Thu, 10 Apr 2014 10:29:35 +0200 Subject: [PATCH] Remove CQL to Solr conversion and base on cql_transform_t The RPN to Solr is indeed in use. It uses exact same data structure as cql_transform_t. --- include/yaz/solr.h | 268 +-------------- src/solrtransform.c | 939 ++------------------------------------------------- 2 files changed, 23 insertions(+), 1184 deletions(-) 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/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: -- 1.7.10.4