X-Git-Url: http://sru.miketaylor.org.uk/?a=blobdiff_plain;f=src%2Ffilter_zoom.cpp;h=44986d65392234d86cce0855c197e6045a3cc7d7;hb=ec6d4b11a9ea36bb2b02f8def619d3eaa59e00e3;hp=82928c370c5d7eefee2e016a6d5e592aa1a6dd3a;hpb=bb4e0b54f53e46d28b8196be71d5c5d1976fc0ba;p=metaproxy-moved-to-github.git diff --git a/src/filter_zoom.cpp b/src/filter_zoom.cpp index 82928c3..44986d6 100644 --- a/src/filter_zoom.cpp +++ b/src/filter_zoom.cpp @@ -30,6 +30,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include +#include #include #include #include @@ -76,9 +78,12 @@ namespace metaproxy_1 { void connect(std::string zurl, int *error, const char **addinfo); void search_pqf(const char *pqf, Odr_int *hits, int *error, const char **addinfo); + void search_cql(const char *cql, Odr_int *hits, + int *error, const char **addinfo); void present(Odr_int start, Odr_int number, ZOOM_record *recs, int *error, const char **addinfo); void set_option(const char *name, const char *value); + const char *get_option(const char *name); int get_error(const char **addinfo); }; class Zoom::Frontend : boost::noncopyable { @@ -117,11 +122,12 @@ namespace metaproxy_1 { FrontendPtr get_frontend(mp::Package &package); void release_frontend(mp::Package &package); SearchablePtr parse_torus(const xmlNode *ptr); - + struct cql_node *convert_cql_fields(struct cql_node *cn, ODR odr); std::map m_clients; boost::mutex m_mutex; boost::condition m_cond_session_ready; std::string torus_url; + std::map fieldmap; std::string xsldir; }; } @@ -183,6 +189,22 @@ void yf::Zoom::Backend::search_pqf(const char *pqf, Odr_int *hits, *hits = 0; } +void yf::Zoom::Backend::search_cql(const char *cql, Odr_int *hits, + int *error, const char **addinfo) +{ + ZOOM_query q = ZOOM_query_create(); + + ZOOM_query_cql(q, cql); + + m_resultset = ZOOM_connection_search(m_connection, q); + ZOOM_query_destroy(q); + *error = ZOOM_connection_error(m_connection, 0, addinfo); + if (*error == 0) + *hits = ZOOM_resultset_size(m_resultset); + else + *hits = 0; +} + void yf::Zoom::Backend::present(Odr_int start, Odr_int number, ZOOM_record *recs, int *error, const char **addinfo) @@ -198,6 +220,11 @@ void yf::Zoom::Backend::set_option(const char *name, const char *value) ZOOM_resultset_option_set(m_resultset, name, value); } +const char *yf::Zoom::Backend::get_option(const char *name) +{ + return ZOOM_connection_option_get(m_connection, name); +} + int yf::Zoom::Backend::get_error(const char **addinfo) { return ZOOM_connection_error(m_connection, 0, addinfo); @@ -406,6 +433,25 @@ void yf::Zoom::Impl::configure(const xmlNode *ptr, bool test_only) attr->name)); } } + else if (!strcmp((const char *) ptr->name, "fieldmap")) + { + const struct _xmlAttr *attr; + std::string ccl_field; + std::string cql_field; + for (attr = ptr->properties; attr; attr = attr->next) + { + if (!strcmp((const char *) attr->name, "ccl")) + ccl_field = mp::xml::get_text(attr->children); + else if (!strcmp((const char *) attr->name, "cql")) + cql_field = mp::xml::get_text(attr->children); + else + throw mp::filter::FilterException( + "Bad attribute " + std::string((const char *) + attr->name)); + } + if (cql_field.length()) + fieldmap[cql_field] = ccl_field; + } else if (!strcmp((const char *) ptr->name, "records")) { yaz_log(YLOG_WARN, "records ignored!"); @@ -427,7 +473,19 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( if (m_backend && m_backend->m_frontend_database == database) return m_backend; - xmlDoc *doc = mp::get_searchable(m_p->torus_url, database); + std::string db_args; + std::string cf_parm; + std::string torus_db; + size_t db_arg_pos = database.find(','); + if (db_arg_pos != std::string::npos) + { + torus_db = database.substr(0, db_arg_pos); + db_args = database.substr(db_arg_pos+1); + } + else + torus_db = database; + + xmlDoc *doc = mp::get_searchable(m_p->torus_url, torus_db); if (!doc) { *error = YAZ_BIB1_DATABASE_DOES_NOT_EXIST; @@ -477,7 +535,6 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( BackendPtr b(new Backend(sptr)); - std::string cf_parm; b->xsp = xsp; b->m_frontend_database = database; std::string authentication = sptr->authentication; @@ -526,10 +583,11 @@ yf::Zoom::BackendPtr yf::Zoom::Frontend::get_backend_from_databases( { url = sptr->target; } - if (cf_parm.length()) - { + if (db_args.length()) + url += "," + db_args; + else if (cf_parm.length()) url += "," + cf_parm; - } + yaz_log(YLOG_LOG, "url=%s", url.c_str()); b->connect(url, error, addinfo); if (*error == 0) { @@ -702,6 +760,38 @@ Z_Records *yf::Zoom::Frontend::get_records(Odr_int start, return records; } +struct cql_node *yf::Zoom::Impl::convert_cql_fields(struct cql_node *cn, + ODR odr) +{ + struct cql_node *r = 0; + if (!cn) + return 0; + switch (cn->which) + { + case CQL_NODE_ST: + if (cn->u.st.index) + { + std::map::const_iterator it; + it = fieldmap.find(cn->u.st.index); + if (it == fieldmap.end()) + return cn; + if (it->second.length()) + cn->u.st.index = odr_strdup(odr, it->second.c_str()); + else + cn->u.st.index = 0; + } + break; + case CQL_NODE_BOOL: + r = convert_cql_fields(cn->u.boolean.left, odr); + if (!r) + r = convert_cql_fields(cn->u.boolean.right, odr); + break; + case CQL_NODE_SORT: + r = convert_cql_fields(cn->u.sort.search, odr); + break; + } + return r; +} void yf::Zoom::Frontend::handle_search(mp::Package &package) { @@ -769,6 +859,21 @@ void yf::Zoom::Frontend::handle_search(mp::Package &package) return; } struct cql_node *cn = cql_parser_result(cp); + struct cql_node *cn_error = m_p->convert_cql_fields(cn, odr); + if (cn_error) + { + // hopefully we are getting a ptr to a index+relation+term node + addinfo = 0; + if (cn_error->which == CQL_NODE_ST) + addinfo = cn_error->u.st.index; + + apdu_res = + odr.create_searchResponse(apdu_req, + YAZ_BIB1_UNSUPP_USE_ATTRIBUTE, + addinfo); + package.response() = apdu_res; + return; + } char ccl_buf[1024]; r = cql_to_ccl_buf(cn, ccl_buf, sizeof(ccl_buf)); @@ -802,6 +907,7 @@ void yf::Zoom::Frontend::handle_search(mp::Package &package) assert(pqf_wrbuf == 0); int cerror, cpos; struct ccl_rpn_node *cn; + yaz_log(YLOG_LOG, "CCL: %s", wrbuf_cstr(ccl_wrbuf)); cn = ccl_find_str(b->sptr->ccl_bibset, wrbuf_cstr(ccl_wrbuf), &cerror, &cpos); wrbuf_destroy(ccl_wrbuf); @@ -832,9 +938,42 @@ void yf::Zoom::Frontend::handle_search(mp::Package &package) } assert(pqf_wrbuf); - b->search_pqf(wrbuf_cstr(pqf_wrbuf), &hits, &error, &addinfo); + if (b->get_option("sru")) + { + cql_transform_t cqlt = cql_transform_create(); + Z_RPNQuery *zquery; + WRBUF wrb = wrbuf_alloc(); + int status; + + zquery = p_query_rpn(odr, wrbuf_cstr(pqf_wrbuf)); + status = cql_transform_rpn2cql_wrbuf(cqlt, wrb, zquery); + + cql_transform_close(cqlt); + + if (status == 0) + { + yaz_log(YLOG_LOG, "search CQL: %s", wrbuf_cstr(wrb)); + b->search_cql(wrbuf_cstr(wrb), &hits, &error, &addinfo); + } + + wrbuf_destroy(wrb); + wrbuf_destroy(pqf_wrbuf); + if (status) + { + apdu_res = + odr.create_searchResponse(apdu_req, YAZ_BIB1_MALFORMED_QUERY, + "can not convert from RPN to CQL"); + package.response() = apdu_res; + return; + } + } + else + { + yaz_log(YLOG_LOG, "search PQF: %s", wrbuf_cstr(pqf_wrbuf)); + b->search_pqf(wrbuf_cstr(pqf_wrbuf), &hits, &error, &addinfo); + wrbuf_destroy(pqf_wrbuf); + } - wrbuf_destroy(pqf_wrbuf); const char *element_set_name = 0; Odr_int number_to_present = 0;