allow triplestore endpoint to be given once MPSPARQL-10
[mp-sparql-moved-to-github.git] / src / filter_sparql.cpp
index 235989b..3a824f0 100644 (file)
@@ -129,16 +129,31 @@ void yf::SPARQL::configure(const xmlNode *xmlnode, bool test_only,
                            const char *path)
 {
     const xmlNode *ptr = xmlnode->children;
+    std::string uri;
 
     for (; ptr; ptr = ptr->next)
     {
         if (ptr->type != XML_ELEMENT_NODE)
             continue;
-        if (!strcmp((const char *) ptr->name, "db"))
+        if (!strcmp((const char *) ptr->name, "defaults"))
+        {
+            const struct _xmlAttr *attr;
+            for (attr = ptr->properties; attr; attr = attr->next)
+            {
+                if (!strcmp((const char *) attr->name, "uri"))
+                    uri = mp::xml::get_text(attr->children);
+                else
+                    throw mp::filter::FilterException(
+                        "Bad attribute " + std::string((const char *)
+                                                       attr->name));
+            }
+        }
+        else if (!strcmp((const char *) ptr->name, "db"))
         {
             yaz_sparql_t s = yaz_sparql_create();
             ConfPtr conf(new Conf);
             conf->s = s;
+            conf->uri = uri;
 
             const struct _xmlAttr *attr;
             for (attr = ptr->properties; attr; attr = attr->next)
@@ -269,14 +284,24 @@ void yf::SPARQL::release_session(Package &package) const
     }
 }
 
-static xmlNode *get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos)
+static bool get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos,
+                       xmlDoc **ndoc)
 {
     xmlNode *ptr = xmlDocGetRootElement(doc);
+    xmlNode *q0;
     Odr_int cur = 0;
 
+    if (ndoc)
+        *ndoc = xmlNewDoc(BAD_CAST "1.0");
+
     if (ptr->type == XML_ELEMENT_NODE &&
         !strcmp((const char *) ptr->name, "RDF"))
     {
+        if (ndoc)
+        {
+            q0 = xmlCopyNode(ptr, 2);
+            xmlDocSetRootElement(*ndoc, q0);
+        }
         ptr = ptr->children;
 
         while (ptr && ptr->type != XML_ELEMENT_NODE)
@@ -296,7 +321,14 @@ static xmlNode *get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos)
                         !strcmp((const char *) ptr->name, "solution"))
                     {
                         if (cur++ == pos)
+                        {
+                            if (ndoc)
+                            {
+                                xmlNode *q1 = xmlCopyNode(ptr, 1);
+                                xmlAddChild(q0, q1);
+                            }
                             break;
+                        }
                     }
             }
             else
@@ -306,7 +338,14 @@ static xmlNode *get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos)
                         !strcmp((const char *) ptr->name, "Description"))
                     {
                         if (cur++ == pos)
-                            break;
+                        {
+                            if (ndoc)
+                            {
+                                xmlNode *q1 = xmlCopyNode(ptr, 1);
+                                xmlAddChild(q0, q1);
+                            }
+                            return true;
+                        }
                     }
             }
         }
@@ -319,6 +358,11 @@ static xmlNode *get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos)
                 break;
         if (ptr)
         {
+            if (ndoc)
+            {
+                q0 = xmlCopyNode(ptr, 2);
+                xmlDocSetRootElement(*ndoc, q0);
+            }
             for (ptr = ptr->children; ptr; ptr = ptr->next)
                 if (ptr->type == XML_ELEMENT_NODE &&
                     !strcmp((const char *) ptr->name, "results"))
@@ -326,18 +370,31 @@ static xmlNode *get_result(xmlDoc *doc, Odr_int *sz, Odr_int pos)
         }
         if (ptr)
         {
+            xmlNode *q1 = 0;
+            if (ndoc)
+            {
+                q1 = xmlCopyNode(ptr, 0);
+                xmlAddChild(q0, q1);
+            }
             for (ptr = ptr->children; ptr; ptr = ptr->next)
                 if (ptr->type == XML_ELEMENT_NODE &&
                     !strcmp((const char *) ptr->name, "result"))
                 {
                     if (cur++ == pos)
-                        break;
+                    {
+                        if (ndoc)
+                        {
+                            xmlNode *q2 = xmlCopyNode(ptr, 1);
+                            xmlAddChild(q1, q2);
+                        }
+                        return true;
+                    }
                 }
         }
     }
     if (sz)
         *sz = cur;
-    return ptr;
+    return false;
 }
 
 Z_Records *yf::SPARQL::Session::fetch(
@@ -375,17 +432,25 @@ Z_Records *yf::SPARQL::Session::fetch(
         Z_NamePlusRecord *npr = rec->u.databaseOrSurDiagnostics->records[i];
         npr->databaseName = odr_strdup(odr, fset->db.c_str());
         npr->which = Z_NamePlusRecord_databaseRecord;
+        xmlDoc *ndoc = 0;
 
-        xmlNode *node = get_result(fset->doc, 0, start - 1 + i);
-        if (!node)
+        if (!get_result(fset->doc, 0, start - 1 + i, &ndoc))
+        {
+            if (ndoc)
+                xmlFreeDoc(ndoc);
+            break;
+        }
+        xmlNode *ndoc_root = xmlDocGetRootElement(ndoc);
+        if (!ndoc_root)
+        {
+            xmlFreeDoc(ndoc);
             break;
-        assert(node->type == XML_ELEMENT_NODE);
-        xmlNode *tmp = xmlCopyNode(node, 1);
+        }
         xmlBufferPtr buf = xmlBufferCreate();
-        xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
+        xmlNodeDump(buf, ndoc, ndoc_root, 0, 0);
         npr->u.databaseRecord =
             z_ext_record_xml(odr, (const char *) buf->content, buf->use);
-        xmlFreeNode(tmp);
+        xmlFreeDoc(ndoc);
         xmlBufferFree(buf);
     }
     rec->u.databaseOrSurDiagnostics->num_records = i;
@@ -469,7 +534,7 @@ Z_APDU *yf::SPARQL::Session::run_sparql(mp::Package &package,
             int error_code = 0;
             std::string addinfo;
 
-            get_result(fset->doc, &fset->hits, -1);
+            get_result(fset->doc, &fset->hits, -1, 0);
             m_frontend_sets[req->resultSetName] = fset;
 
             Odr_int number = 0;