From 63c48920fd45817bf28177279f65099670fe258b Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Wed, 11 Aug 2010 13:39:37 +0200 Subject: [PATCH] Refactor ZOOM_query to separate source --- include/yaz/zoom.h | 3 + src/Makefile.am | 2 +- src/zoom-c.c | 245 +++++------------------------------------------- src/zoom-p.h | 12 +-- src/zoom-query.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/zoom-z3950.c | 18 ++-- win/makefile | 1 + 7 files changed, 303 insertions(+), 240 deletions(-) create mode 100644 src/zoom-query.c diff --git a/include/yaz/zoom.h b/include/yaz/zoom.h index 3551a77..ca38b0d 100644 --- a/include/yaz/zoom.h +++ b/include/yaz/zoom.h @@ -293,6 +293,9 @@ ZOOM_query_prefix(ZOOM_query s, const char *str); ZOOM_API(int) ZOOM_query_sortby(ZOOM_query s, const char *criteria); +ZOOM_API(void) +ZOOM_query_addref(ZOOM_query s); + /* ----------------------------------------------------------- */ /* scan */ ZOOM_API(ZOOM_scanset) diff --git a/src/Makefile.am b/src/Makefile.am index 4fbb1b3..4b72c8c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,7 +88,7 @@ libyaz_la_SOURCES=version.c options.c log.c \ zget.c yaz-ccl.c diag-entry.c diag-entry.h \ logrpn.c \ otherinfo.c pquery.c sortspec.c charneg.c initopt.c \ - zoom-c.c zoom-z3950.c zoom-socket.c zoom-opt.c zoom-p.h \ + zoom-c.c zoom-z3950.c zoom-query.c zoom-socket.c zoom-opt.c zoom-p.h \ grs1disp.c zgdu.c soap.c srw.c srwutil.c uri.c \ opacdisp.c cclfind.c ccltoken.c cclerrms.c cclqual.c cclptree.c cclp.h \ cclqfile.c cclstr.c cclxmlconfig.c ccl_stop_words.c \ diff --git a/src/zoom-c.c b/src/zoom-c.c index 923e500..75b694a 100644 --- a/src/zoom-c.c +++ b/src/zoom-c.c @@ -16,14 +16,9 @@ #include #include #include -#include #include #include #include -#include -#include -#include -#include #include #include #include @@ -40,7 +35,6 @@ static int log_details0 = 0; static void resultset_destroy(ZOOM_resultset r); static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out); -static char *cql2pqf(ZOOM_connection c, const char *cql); ZOOM_API(const char *) ZOOM_get_event_str(int event) { @@ -621,142 +615,6 @@ ZOOM_API(void) } } -ZOOM_API(ZOOM_query) - ZOOM_query_create(void) -{ - ZOOM_query s = (ZOOM_query) xmalloc(sizeof(*s)); - - s->refcount = 1; - s->z_query = 0; - s->sort_spec = 0; - s->odr = odr_createmem(ODR_ENCODE); - s->query_string = 0; - - return s; -} - -ZOOM_API(void) - ZOOM_query_destroy(ZOOM_query s) -{ - if (!s) - return; - - (s->refcount)--; - if (s->refcount == 0) - { - odr_destroy(s->odr); - xfree(s); - } -} - -ZOOM_API(int) - ZOOM_query_prefix(ZOOM_query s, const char *str) -{ - s->query_string = odr_strdup(s->odr, str); - s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query)); - s->z_query->which = Z_Query_type_1; - s->z_query->u.type_1 = p_query_rpn(s->odr, str); - if (!s->z_query->u.type_1) - { - s->z_query = 0; - return -1; - } - return 0; -} - -ZOOM_API(int) - ZOOM_query_cql(ZOOM_query s, const char *str) -{ - Z_External *ext; - - s->query_string = odr_strdup(s->odr, str); - - ext = (Z_External *) odr_malloc(s->odr, sizeof(*ext)); - ext->direct_reference = odr_oiddup(s->odr, yaz_oid_userinfo_cql); - ext->indirect_reference = 0; - ext->descriptor = 0; - ext->which = Z_External_CQL; - ext->u.cql = s->query_string; - - s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query)); - s->z_query->which = Z_Query_type_104; - s->z_query->u.type_104 = ext; - - return 0; -} - -/* - * Translate the CQL string client-side into RPN which is passed to - * the server. This is useful for server's that don't themselves - * support CQL, for which ZOOM_query_cql() is useless. `conn' is used - * only as a place to stash diagnostics if compilation fails; if this - * information is not needed, a null pointer may be used. - */ -ZOOM_API(int) - ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn) -{ - char *rpn; - int ret; - ZOOM_connection freeme = 0; - - if (conn == 0) - conn = freeme = ZOOM_connection_create(0); - - rpn = cql2pqf(conn, str); - if (freeme != 0) - ZOOM_connection_destroy(freeme); - if (rpn == 0) - return -1; - - ret = ZOOM_query_prefix(s, rpn); - xfree(rpn); - return ret; -} - -/* - * Analogous in every way to ZOOM_query_cql2rpn(), except that there - * is no analogous ZOOM_query_ccl() that just sends uninterpreted CCL - * to the server, as the YAZ GFS doesn't know how to handle this. - */ -ZOOM_API(int) - ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config, - int *ccl_error, const char **error_string, - int *error_pos) -{ - int ret; - struct ccl_rpn_node *rpn; - CCL_bibset bibset = ccl_qual_mk(); - - if (config) - ccl_qual_buf(bibset, config); - - rpn = ccl_find_str(bibset, str, ccl_error, error_pos); - if (!rpn) - { - *error_string = ccl_err_msg(*ccl_error); - ret = -1; - } - else - { - WRBUF wr = wrbuf_alloc(); - ccl_pquery(wr, rpn); - ccl_rpn_delete(rpn); - ret = ZOOM_query_prefix(s, wrbuf_cstr(wr)); - wrbuf_destroy(wr); - } - ccl_qual_rm(&bibset); - return ret; -} - -ZOOM_API(int) - ZOOM_query_sortby(ZOOM_query s, const char *criteria) -{ - s->sort_spec = yaz_sort_spec(s->odr, criteria); - if (!s->sort_spec) - return -1; - return 0; -} - ZOOM_API(void) ZOOM_resultset_release(ZOOM_resultset r) { #if ZOOM_RESULT_LISTS @@ -910,7 +768,7 @@ ZOOM_API(ZOOM_resultset) #endif yaz_log(c->log_api, "%p ZOOM_connection_search set %p query %p", c, r, q); - r->r_sort_spec = q->sort_spec; + r->r_sort_spec = ZOOM_query_get_sortspec(q); r->query = q; r->options = ZOOM_options_create_with_parent(c->options); @@ -975,7 +833,7 @@ ZOOM_API(ZOOM_resultset) ZOOM_resultset_addref(r); - (q->refcount)++; + ZOOM_query_addref(q); if (!c->async) { @@ -1417,6 +1275,7 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c) ZOOM_resultset resultset = 0; Z_SRW_PDU *sr = 0; const char *option_val = 0; + Z_Query *z_query; if (c->error) /* don't continue on error */ return zoom_complete; @@ -1468,17 +1327,19 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c) assert(resultset->query); sr = ZOOM_srw_get_pdu(c, Z_SRW_searchRetrieve_request); - if (resultset->query->z_query->which == Z_Query_type_104 - && resultset->query->z_query->u.type_104->which == Z_External_CQL) + z_query = ZOOM_query_get_Z_Query(resultset->query); + + if (z_query->which == Z_Query_type_104 + && z_query->u.type_104->which == Z_External_CQL) { sr->u.request->query_type = Z_SRW_query_type_cql; - sr->u.request->query.cql =resultset->query->z_query->u.type_104->u.cql; + sr->u.request->query.cql = z_query->u.type_104->u.cql; } - else if (resultset->query->z_query->which == Z_Query_type_1 && - resultset->query->z_query->u.type_1) + else if (z_query->which == Z_Query_type_1 && z_query->u.type_1) { sr->u.request->query_type = Z_SRW_query_type_pqf; - sr->u.request->query.pqf = resultset->query->query_string; + sr->u.request->query.pqf = + ZOOM_query_get_query_string(resultset->query); } else { @@ -2075,8 +1936,9 @@ ZOOM_API(ZOOM_scanset) ZOOM_connection_scan1(ZOOM_connection c, ZOOM_query q) { ZOOM_scanset scan = 0; + Z_Query *z_query = ZOOM_query_get_Z_Query(q); - if (!q->z_query) + if (!z_query) return 0; scan = (ZOOM_scanset) xmalloc(sizeof(*scan)); scan->connection = c; @@ -2087,7 +1949,7 @@ ZOOM_API(ZOOM_scanset) scan->srw_scan_response = 0; scan->query = q; - (q->refcount)++; + ZOOM_query_addref(q); scan->databaseNames = ZOOM_connection_get_databases(c, c->options, &scan->num_databaseNames, scan->odr); @@ -2148,6 +2010,7 @@ static zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c) ZOOM_scanset scan; Z_SRW_PDU *sr = 0; const char *option_val = 0; + Z_Query *z_query; if (!c->tasks) return zoom_complete; @@ -2156,17 +2019,20 @@ static zoom_ret ZOOM_connection_srw_send_scan(ZOOM_connection c) sr = ZOOM_srw_get_pdu(c, Z_SRW_scan_request); + z_query = ZOOM_query_get_Z_Query(scan->query); /* SRU scan can only carry CQL and PQF */ - if (scan->query->z_query->which == Z_Query_type_104) + if (z_query->which == Z_Query_type_104) { sr->u.scan_request->query_type = Z_SRW_query_type_cql; - sr->u.scan_request->scanClause.cql = scan->query->query_string; + sr->u.scan_request->scanClause.cql = + ZOOM_query_get_query_string(scan->query); } - else if (scan->query->z_query->which == Z_Query_type_1 - || scan->query->z_query->which == Z_Query_type_101) + else if (z_query->which == Z_Query_type_1 + || z_query->which == Z_Query_type_101) { sr->u.scan_request->query_type = Z_SRW_query_type_pqf; - sr->u.scan_request->scanClause.pqf = scan->query->query_string; + sr->u.scan_request->scanClause.pqf = + ZOOM_query_get_query_string(scan->query); } else { @@ -2419,7 +2285,7 @@ ZOOM_API(int) break; case ZOOM_TASK_SORT: c->tasks->u.sort.resultset->r_sort_spec = - c->tasks->u.sort.q->sort_spec; + ZOOM_query_get_sortspec(c->tasks->u.sort.q); ret = send_Z3950_sort(c, c->tasks->u.sort.resultset); break; } @@ -3130,69 +2996,6 @@ ZOOM_API(int) } -static void cql2pqf_wrbuf_puts(const char *buf, void *client_data) -{ - WRBUF wrbuf = (WRBUF) client_data; - wrbuf_puts(wrbuf, buf); -} - -/* - * Returns an xmalloc()d string containing RPN that corresponds to the - * CQL passed in. On error, sets the Connection object's error state - * and returns a null pointer. - * ### We could cache CQL parser and/or transformer in Connection. - */ -static char *cql2pqf(ZOOM_connection c, const char *cql) -{ - CQL_parser parser; - int error; - const char *cqlfile; - cql_transform_t trans; - char *result = 0; - - parser = cql_parser_create(); - if ((error = cql_parser_string(parser, cql)) != 0) { - cql_parser_destroy(parser); - ZOOM_set_error(c, ZOOM_ERROR_CQL_PARSE, cql); - return 0; - } - - cqlfile = ZOOM_connection_option_get(c, "cqlfile"); - if (cqlfile == 0) - { - ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file"); - } - else if ((trans = cql_transform_open_fname(cqlfile)) == 0) - { - char buf[512]; - sprintf(buf, "can't open CQL transform file '%.200s': %.200s", - cqlfile, strerror(errno)); - ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); - } - else - { - WRBUF wrbuf_result = wrbuf_alloc(); - error = cql_transform(trans, cql_parser_result(parser), - cql2pqf_wrbuf_puts, wrbuf_result); - if (error != 0) { - char buf[512]; - const char *addinfo; - error = cql_transform_error(trans, &addinfo); - sprintf(buf, "%.200s (addinfo=%.200s)", - cql_strerror(error), addinfo); - ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); - } - else - { - result = xstrdup(wrbuf_cstr(wrbuf_result)); - } - cql_transform_close(trans); - wrbuf_destroy(wrbuf_result); - } - cql_parser_destroy(parser); - return result; -} - ZOOM_API(int) ZOOM_connection_fire_event_timeout(ZOOM_connection c) { if (c->mask) diff --git a/src/zoom-p.h b/src/zoom-p.h index 6a95040..f0eb8a8 100644 --- a/src/zoom-p.h +++ b/src/zoom-p.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -42,14 +41,6 @@ typedef struct ZOOM_Event_p *ZOOM_Event; -struct ZOOM_query_p { - Z_Query *z_query; - Z_SortKeySpecList *sort_spec; - int refcount; - ODR odr; - char *query_string; -}; - typedef enum { zoom_sru_error, zoom_sru_soap, @@ -320,6 +311,9 @@ void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, const char *schema, Z_SRW_diagnostic *diag); +Z_Query *ZOOM_query_get_Z_Query(ZOOM_query s); +Z_SortKeySpecList *ZOOM_query_get_sortspec(ZOOM_query s); +char *ZOOM_query_get_query_string(ZOOM_query s); /* * Local variables: diff --git a/src/zoom-query.c b/src/zoom-query.c new file mode 100644 index 0000000..1049873 --- /dev/null +++ b/src/zoom-query.c @@ -0,0 +1,262 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data + * See the file LICENSE for details. + */ +/** + * \file zoom-query.c + * \brief Implements ZOOM C query interface. + */ + +#include +#include +#include +#include "zoom-p.h" + +#include +#include +#include +#include +#include +#include +#include + +struct ZOOM_query_p { + Z_Query *z_query; + Z_SortKeySpecList *sort_spec; + int refcount; + ODR odr; + char *query_string; +}; + +Z_Query *ZOOM_query_get_Z_Query(ZOOM_query s) +{ + return s->z_query; +} + + +Z_SortKeySpecList *ZOOM_query_get_sortspec(ZOOM_query s) +{ + return s->sort_spec; +} + +static void cql2pqf_wrbuf_puts(const char *buf, void *client_data) +{ + WRBUF wrbuf = (WRBUF) client_data; + wrbuf_puts(wrbuf, buf); +} + +char *ZOOM_query_get_query_string(ZOOM_query s) +{ + return s->query_string; +} + +/* + * Returns an xmalloc()d string containing RPN that corresponds to the + * CQL passed in. On error, sets the Connection object's error state + * and returns a null pointer. + * ### We could cache CQL parser and/or transformer in Connection. + */ +static char *cql2pqf(ZOOM_connection c, const char *cql) +{ + CQL_parser parser; + int error; + const char *cqlfile; + cql_transform_t trans; + char *result = 0; + + parser = cql_parser_create(); + if ((error = cql_parser_string(parser, cql)) != 0) { + cql_parser_destroy(parser); + ZOOM_set_error(c, ZOOM_ERROR_CQL_PARSE, cql); + return 0; + } + + cqlfile = ZOOM_connection_option_get(c, "cqlfile"); + if (cqlfile == 0) + { + ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, "no CQL transform file"); + } + else if ((trans = cql_transform_open_fname(cqlfile)) == 0) + { + char buf[512]; + sprintf(buf, "can't open CQL transform file '%.200s': %.200s", + cqlfile, strerror(errno)); + ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); + } + else + { + WRBUF wrbuf_result = wrbuf_alloc(); + error = cql_transform(trans, cql_parser_result(parser), + cql2pqf_wrbuf_puts, wrbuf_result); + if (error != 0) { + char buf[512]; + const char *addinfo; + error = cql_transform_error(trans, &addinfo); + sprintf(buf, "%.200s (addinfo=%.200s)", + cql_strerror(error), addinfo); + ZOOM_set_error(c, ZOOM_ERROR_CQL_TRANSFORM, buf); + } + else + { + result = xstrdup(wrbuf_cstr(wrbuf_result)); + } + cql_transform_close(trans); + wrbuf_destroy(wrbuf_result); + } + cql_parser_destroy(parser); + return result; +} + + +ZOOM_API(ZOOM_query) + ZOOM_query_create(void) +{ + ZOOM_query s = (ZOOM_query) xmalloc(sizeof(*s)); + + s->refcount = 1; + s->z_query = 0; + s->sort_spec = 0; + s->odr = odr_createmem(ODR_ENCODE); + s->query_string = 0; + + return s; +} + +ZOOM_API(void) + ZOOM_query_destroy(ZOOM_query s) +{ + if (!s) + return; + + (s->refcount)--; + if (s->refcount == 0) + { + odr_destroy(s->odr); + xfree(s); + } +} + +ZOOM_API(void) + ZOOM_query_addref(ZOOM_query s) +{ + s->refcount++; +} + +ZOOM_API(int) + ZOOM_query_prefix(ZOOM_query s, const char *str) +{ + s->query_string = odr_strdup(s->odr, str); + s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query)); + s->z_query->which = Z_Query_type_1; + s->z_query->u.type_1 = p_query_rpn(s->odr, str); + if (!s->z_query->u.type_1) + { + s->z_query = 0; + return -1; + } + return 0; +} + +ZOOM_API(int) + ZOOM_query_cql(ZOOM_query s, const char *str) +{ + Z_External *ext; + + s->query_string = odr_strdup(s->odr, str); + + ext = (Z_External *) odr_malloc(s->odr, sizeof(*ext)); + ext->direct_reference = odr_oiddup(s->odr, yaz_oid_userinfo_cql); + ext->indirect_reference = 0; + ext->descriptor = 0; + ext->which = Z_External_CQL; + ext->u.cql = s->query_string; + + s->z_query = (Z_Query *) odr_malloc(s->odr, sizeof(*s->z_query)); + s->z_query->which = Z_Query_type_104; + s->z_query->u.type_104 = ext; + + return 0; +} + +/* + * Translate the CQL string client-side into RPN which is passed to + * the server. This is useful for server's that don't themselves + * support CQL, for which ZOOM_query_cql() is useless. `conn' is used + * only as a place to stash diagnostics if compilation fails; if this + * information is not needed, a null pointer may be used. + */ +ZOOM_API(int) + ZOOM_query_cql2rpn(ZOOM_query s, const char *str, ZOOM_connection conn) +{ + char *rpn; + int ret; + ZOOM_connection freeme = 0; + + if (conn == 0) + conn = freeme = ZOOM_connection_create(0); + + rpn = cql2pqf(conn, str); + if (freeme != 0) + ZOOM_connection_destroy(freeme); + if (rpn == 0) + return -1; + + ret = ZOOM_query_prefix(s, rpn); + xfree(rpn); + return ret; +} + +/* + * Analogous in every way to ZOOM_query_cql2rpn(), except that there + * is no analogous ZOOM_query_ccl() that just sends uninterpreted CCL + * to the server, as the YAZ GFS doesn't know how to handle this. + */ +ZOOM_API(int) + ZOOM_query_ccl2rpn(ZOOM_query s, const char *str, const char *config, + int *ccl_error, const char **error_string, + int *error_pos) +{ + int ret; + struct ccl_rpn_node *rpn; + CCL_bibset bibset = ccl_qual_mk(); + + if (config) + ccl_qual_buf(bibset, config); + + rpn = ccl_find_str(bibset, str, ccl_error, error_pos); + if (!rpn) + { + *error_string = ccl_err_msg(*ccl_error); + ret = -1; + } + else + { + WRBUF wr = wrbuf_alloc(); + ccl_pquery(wr, rpn); + ccl_rpn_delete(rpn); + ret = ZOOM_query_prefix(s, wrbuf_cstr(wr)); + wrbuf_destroy(wr); + } + ccl_qual_rm(&bibset); + return ret; +} + +ZOOM_API(int) + ZOOM_query_sortby(ZOOM_query s, const char *criteria) +{ + s->sort_spec = yaz_sort_spec(s->odr, criteria); + if (!s->sort_spec) + return -1; + return 0; +} + + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/zoom-z3950.c b/src/zoom-z3950.c index bf31a7c..bbd2e2a 100644 --- a/src/zoom-z3950.c +++ b/src/zoom-z3950.c @@ -21,9 +21,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -676,14 +673,14 @@ zoom_ret ZOOM_connection_Z3950_send_search(ZOOM_connection c) assert(r->query); /* prepare query for the search request */ - search_req->query = r->query->z_query; + search_req->query = ZOOM_query_get_Z_Query(r->query); if (!search_req->query) { ZOOM_set_error(c, ZOOM_ERROR_INVALID_QUERY, 0); return zoom_complete; } - if (r->query->z_query->which == Z_Query_type_1 || - r->query->z_query->which == Z_Query_type_101) + if (search_req->query->which == Z_Query_type_1 || + search_req->query->which == Z_Query_type_101) { const char *cp = ZOOM_options_get(r->options, "rpnCharset"); if (cp) @@ -811,6 +808,7 @@ zoom_ret ZOOM_connection_Z3950_send_scan(ZOOM_connection c) ZOOM_scanset scan; Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_scanRequest); Z_ScanRequest *req = apdu->u.scanRequest; + Z_Query *z_query; yaz_log(c->log_details, "%p send_scan", c); if (!c->tasks) @@ -818,11 +816,13 @@ zoom_ret ZOOM_connection_Z3950_send_scan(ZOOM_connection c) assert (c->tasks->which == ZOOM_TASK_SCAN); scan = c->tasks->u.scan.scan; + z_query = ZOOM_query_get_Z_Query(scan->query); + /* Z39.50 scan can only carry RPN */ - if (scan->query->z_query->which == Z_Query_type_1 || - scan->query->z_query->which == Z_Query_type_101) + if (z_query->which == Z_Query_type_1 || + z_query->which == Z_Query_type_101) { - Z_RPNQuery *rpn = scan->query->z_query->u.type_1; + Z_RPNQuery *rpn = z_query->u.type_1; const char *cp = ZOOM_options_get(scan->options, "rpnCharset"); if (cp) { diff --git a/win/makefile b/win/makefile index 51d1c24..4935f35 100644 --- a/win/makefile +++ b/win/makefile @@ -474,6 +474,7 @@ MISC_OBJS= \ $(OBJDIR)\srwutil.obj \ $(OBJDIR)\zoom-c.obj \ $(OBJDIR)\zoom-z3950.obj \ + $(OBJDIR)\zoom-query.obj \ $(OBJDIR)\facet.obj \ $(OBJDIR)\zoom-opt.obj \ $(OBJDIR)\zoom-socket.obj \ -- 1.7.10.4