42448444112454944c000284901419ff273e24f7
[mp-sparql-moved-to-github.git] / src / test_sparql.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <string.h>
10 #include "sparql.h"
11 #include <yaz/log.h>
12 #include <yaz/test.h>
13 #include <yaz/pquery.h>
14
15 static int test_query(yaz_sparql_t s, const char *pqf, const char *expect)
16 {
17     YAZ_PQF_Parser parser = yaz_pqf_create();
18     ODR odr = odr_createmem(ODR_ENCODE);
19     Z_RPNQuery *rpn = yaz_pqf_parse(parser, odr, pqf);
20     int ret = 0;
21     WRBUF addinfo = wrbuf_alloc();
22     WRBUF w = wrbuf_alloc();
23
24     if (rpn)
25     {
26         int r = yaz_sparql_from_rpn_wrbuf(s, addinfo, w, rpn);
27         if (expect)
28         {
29             if (!r)
30             {
31                 if (!strcmp(expect, wrbuf_cstr(w)))
32                     ret = 1;
33                 else
34                 {
35                     yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
36                     yaz_log(YLOG_WARN, " expect: %s", expect);
37                     yaz_log(YLOG_WARN, " got:    %s", wrbuf_cstr(w));
38                 }
39             }
40             else
41             {
42                 yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
43                 yaz_log(YLOG_WARN, " expect: %s", expect);
44                 yaz_log(YLOG_WARN, " got error: %d:%s", r, wrbuf_cstr(addinfo));
45             }
46         }
47         else
48         {
49             if (r)
50                 ret = 1;
51             else
52             {
53                 yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
54                 yaz_log(YLOG_WARN, " expect error");
55                 yaz_log(YLOG_WARN, " got:    %s", wrbuf_cstr(w));
56             }
57         }
58     }
59     wrbuf_destroy(w);
60     wrbuf_destroy(addinfo);
61     odr_destroy(odr);
62     yaz_pqf_destroy(parser);
63     return ret;
64 }
65
66 static void tst1(void)
67 {
68     yaz_sparql_t s = yaz_sparql_create();
69
70     yaz_sparql_add_pattern(s, "prefix",
71                            "rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns");
72     yaz_sparql_add_pattern(s, "prefix",
73                            "bf: <http://bibframe.org/vocab/>");
74     yaz_sparql_add_pattern(s, "prefix",
75                            "gs: http://gs.com/panorama/domain-model");
76     yaz_sparql_add_pattern(s, "form", "SELECT ?title ?author ?description ?ititle");
77     yaz_sparql_add_pattern(s, "criteria", "?work a bf:Work");
78     yaz_sparql_add_pattern(s, "criteria", "?work bf:workTitle/bf:titleValue ?title");
79     yaz_sparql_add_pattern(s, "criteria", "?work bf:creator/bf:label ?author");
80     yaz_sparql_add_pattern(s, "criteria", "?work bf:note ?description");
81     yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceOf ?work");
82     yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceTitle/bf:titleValue ?ititle");
83     yaz_sparql_add_pattern(s, "criteria.optional", "?inst bf:heldBy ?lib");
84
85     yaz_sparql_add_pattern(s, "index.bf.title",
86                            "?work bf:workTitle/bf:titleValue ?o1 "
87                            "FILTER(contains(?o1, %s))");
88     yaz_sparql_add_pattern(s, "index.bf.creator",
89                            "?work bf:creator/bf:label ?o2 "
90                            "FILTER(contains(?o2, %s))");
91     yaz_sparql_add_pattern(s, "index.bf.authorityCreator",
92                            "?work bf:author %s");
93     yaz_sparql_add_pattern(s, "index.bf.type",
94                            "?inst rdf:type %s");
95     yaz_sparql_add_pattern(s, "index.bf.format",
96                            "?inst bf:format ?o5 FILTER(contains(?o5, %s))");
97     yaz_sparql_add_pattern(s, "index.bf.nearby", "?lib gs:nearby (%d)");
98     yaz_sparql_add_pattern(s, "index.bf.baseTitle",
99                            "?work bf:derivativeOf/bf:workTitle/bf:titleValue "
100                            "?o6 FILTER(contains(?o6, %s))");
101     yaz_sparql_add_pattern(s, "index.bf.baseCreator",
102                            "?work bf:derivativeOf/bf:creator/bf:label "
103                            "?o7 FILTER(contains(?o7, %s))");
104     yaz_sparql_add_pattern(s, "index.bf.targetAudience",
105                            "?work bf:targetAudience %s");
106     yaz_sparql_add_pattern(s, "index.bf.isbn", "?inst bf:ISBN %s");
107     YAZ_CHECK(test_query(
108                   s, "@attr 1=bf.title computer",
109                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
110                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
111                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
112                   "SELECT ?title ?author ?description ?ititle\n"
113                   "WHERE {\n"
114                   "  ?work a bf:Work .\n"
115                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
116                   "  ?work bf:creator/bf:label ?author .\n"
117                   "  ?work bf:note ?description .\n"
118                   "  ?inst bf:instanceOf ?work .\n"
119                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
120                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
121                   "  ?work bf:workTitle/bf:titleValue ?o1 "
122                   "FILTER(contains(?o1, \"computer\"))\n"
123                   "}\n"
124                   ));
125
126     YAZ_CHECK(test_query(
127                   s, "@attr 1=bf.creator london",
128                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
129                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
130                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
131                   "SELECT ?title ?author ?description ?ititle\n"
132                   "WHERE {\n"
133                   "  ?work a bf:Work .\n"
134                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
135                   "  ?work bf:creator/bf:label ?author .\n"
136                   "  ?work bf:note ?description .\n"
137                   "  ?inst bf:instanceOf ?work .\n"
138                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
139                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
140                   "  ?work bf:creator/bf:label ?o2 "
141                   "FILTER(contains(?o2, \"london\"))\n"
142                   "}\n"));
143
144
145     YAZ_CHECK(test_query(
146                   s, "@and @attr 1=bf.creator london @attr 1=bf.title computer",
147                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
148                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
149                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
150                   "SELECT ?title ?author ?description ?ititle\n"
151                   "WHERE {\n"
152                   "  ?work a bf:Work .\n"
153                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
154                   "  ?work bf:creator/bf:label ?author .\n"
155                   "  ?work bf:note ?description .\n"
156                   "  ?inst bf:instanceOf ?work .\n"
157                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
158                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
159                   "  ?work bf:creator/bf:label ?o2 "
160                   "FILTER(contains(?o2, \"london\")) .\n"
161                   "  ?work bf:workTitle/bf:titleValue ?o1 "
162                   "FILTER(contains(?o1, \"computer\"))\n"
163                   "}\n"));
164
165     YAZ_CHECK(test_query(
166                   s, "@or @attr 1=bf.creator london @attr 1=bf.title computer",
167                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
168                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
169                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
170                   "SELECT ?title ?author ?description ?ititle\n"
171                   "WHERE {\n"
172                   "  ?work a bf:Work .\n"
173                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
174                   "  ?work bf:creator/bf:label ?author .\n"
175                   "  ?work bf:note ?description .\n"
176                   "  ?inst bf:instanceOf ?work .\n"
177                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
178                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
179                   "  {\n"
180                   "   ?work bf:creator/bf:label ?o2 "
181                   "FILTER(contains(?o2, \"london\"))\n"
182                   "  } UNION {\n"
183                   "   ?work bf:workTitle/bf:titleValue ?o1 "
184                   "FILTER(contains(?o1, \"computer\"))\n"
185                   "  }\n"
186                   "}\n"
187                   ));
188
189     YAZ_CHECK(test_query(
190                   s, "@or @or @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
191                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
192                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
193                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
194                   "SELECT ?title ?author ?description ?ititle\n"
195                   "WHERE {\n"
196                   "  ?work a bf:Work .\n"
197                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
198                   "  ?work bf:creator/bf:label ?author .\n"
199                   "  ?work bf:note ?description .\n"
200                   "  ?inst bf:instanceOf ?work .\n"
201                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
202                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
203                   "  {\n"
204                   "   {\n"
205                   "    ?work bf:creator/bf:label ?o2 "
206                   "FILTER(contains(?o2, \"a\"))\n"
207                   "   } UNION {\n"
208                   "    ?work bf:workTitle/bf:titleValue ?o1 "
209                   "FILTER(contains(?o1, \"b\"))\n"
210                   "   }\n"
211                   "  } UNION {\n"
212                   "   ?work bf:workTitle/bf:titleValue ?o1 "
213                   "FILTER(contains(?o1, \"c\"))\n"
214                   "  }\n"
215                   "}\n"
216                   ));
217
218     YAZ_CHECK(test_query(
219                   s, "@or @and @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
220                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
221                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
222                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
223                   "SELECT ?title ?author ?description ?ititle\n"
224                   "WHERE {\n"
225                   "  ?work a bf:Work .\n"
226                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
227                   "  ?work bf:creator/bf:label ?author .\n"
228                   "  ?work bf:note ?description .\n"
229                   "  ?inst bf:instanceOf ?work .\n"
230                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
231                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
232                   "  {\n"
233                   "   ?work bf:creator/bf:label ?o2 "
234                   "FILTER(contains(?o2, \"a\")) .\n"
235                   "   ?work bf:workTitle/bf:titleValue ?o1 "
236                   "FILTER(contains(?o1, \"b\"))\n"
237                   "  } UNION {\n"
238                   "   ?work bf:workTitle/bf:titleValue ?o1 "
239                   "FILTER(contains(?o1, \"c\"))\n"
240                   "  }\n"
241                   "}\n"
242                   ));
243
244     YAZ_CHECK(test_query(
245                   s, "@and @and @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
246                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
247                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
248                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
249                   "SELECT ?title ?author ?description ?ititle\n"
250                   "WHERE {\n"
251                   "  ?work a bf:Work .\n"
252                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
253                   "  ?work bf:creator/bf:label ?author .\n"
254                   "  ?work bf:note ?description .\n"
255                   "  ?inst bf:instanceOf ?work .\n"
256                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
257                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
258                   "  ?work bf:creator/bf:label ?o2 "
259                   "FILTER(contains(?o2, \"a\")) .\n"
260                   "  ?work bf:workTitle/bf:titleValue ?o1 "
261                   "FILTER(contains(?o1, \"b\")) .\n"
262                   "  ?work bf:workTitle/bf:titleValue ?o1 "
263                   "FILTER(contains(?o1, \"c\"))\n"
264                   "}\n"
265                   ));
266
267     YAZ_CHECK(test_query(
268                   s, "@and @attr 1=bf.title \"Phantom Tollbooth\" "
269                   "@attr 1=bf.nearby \"40.1583 83.0742 30\"",
270                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
271                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
272                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
273                   "SELECT ?title ?author ?description ?ititle\n"
274                   "WHERE {\n"
275                   "  ?work a bf:Work .\n"
276                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
277                   "  ?work bf:creator/bf:label ?author .\n"
278                   "  ?work bf:note ?description .\n"
279                   "  ?inst bf:instanceOf ?work .\n"
280                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
281                   "  ?inst bf:heldBy ?lib .\n"
282                   "  ?work bf:workTitle/bf:titleValue ?o1 "
283                   "FILTER(contains(?o1, \"Phantom Tollbooth\")) .\n"
284                   "  ?lib gs:nearby (40.1583 83.0742 30)\n"
285                   "}\n"
286                   ));
287
288     YAZ_CHECK(test_query(
289                   s, "@attr 1=bf.isbn 9780316154697",
290                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
291                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
292                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
293                   "SELECT ?title ?author ?description ?ititle\n"
294                   "WHERE {\n"
295                   "  ?work a bf:Work .\n"
296                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
297                   "  ?work bf:creator/bf:label ?author .\n"
298                   "  ?work bf:note ?description .\n"
299                   "  ?inst bf:instanceOf ?work .\n"
300                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
301                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
302                   "  ?inst bf:ISBN \"9780316154697\"\n"
303                   "}\n"
304                  ));
305
306
307     yaz_sparql_destroy(s);
308 }
309
310 static void tst2(void)
311 {
312     yaz_sparql_t s = yaz_sparql_create();
313
314     yaz_sparql_add_pattern(s, "prefix",
315                            "rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns");
316     yaz_sparql_add_pattern(s, "prefix",
317                            "bf: <http://bibframe.org/vocab/>");
318     yaz_sparql_add_pattern(s, "prefix",
319                            "gs: http://gs.com/panorama/domain-model");
320     yaz_sparql_add_pattern(s, "form", "SELECT ?title ?author ?description ?ititle");
321     yaz_sparql_add_pattern(s, "criteria", "?work a bf:Work");
322     yaz_sparql_add_pattern(s, "criteria", "?work bf:workTitle/bf:titleValue ?title");
323     yaz_sparql_add_pattern(s, "criteria", "?work bf:creator/bf:label ?author");
324     yaz_sparql_add_pattern(s, "criteria", "?work bf:note ?description");
325     yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceOf ?work");
326     yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceTitle/bf:titleValue ?ititle");
327     yaz_sparql_add_pattern(s, "criteria.optional", "?inst bf:heldBy ?lib");
328
329     yaz_sparql_add_pattern(s, "index.bf.title",
330                            "?work bf:workTitle/bf:titleValue %v "
331                            "FILTER(contains(%v, %s))");
332     yaz_sparql_add_pattern(s, "index.bf.creator",
333                            "?work bf:creator/bf:label %v "
334                            "FILTER(contains(%v, %s))");
335     yaz_sparql_add_pattern(s, "index.bf.authorityCreator",
336                            "?work bf:author %s");
337     yaz_sparql_add_pattern(s, "index.bf.type", "?inst rdf:type %s");
338     yaz_sparql_add_pattern(s, "index.bf.format",
339                            "?inst bf:format %v FILTER(contains(%v, %s))");
340     yaz_sparql_add_pattern(s, "index.bf.nearby", "?lib gs:nearby (%d)");
341     yaz_sparql_add_pattern(s, "index.bf.baseTitle",
342                            "?work bf:derivativeOf/bf:workTitle/bf:titleValue "
343                            "%v FILTER(contains(%v, %s))");
344     yaz_sparql_add_pattern(s, "index.bf.baseCreator",
345                            "?work bf:derivativeOf/bf:creator/bf:label "
346                            "%v FILTER(contains(%v, %s))");
347     yaz_sparql_add_pattern(s, "index.bf.targetAudience",
348                            "?work bf:targetAudience %s");
349     yaz_sparql_add_pattern(s, "index.bf.isbn", "?inst bf:ISBN %s");
350
351     YAZ_CHECK(test_query(
352                   s, "@attr 1=bf.title computer",
353                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
354                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
355                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
356                   "SELECT ?title ?author ?description ?ititle\n"
357                   "WHERE {\n"
358                   "  ?work a bf:Work .\n"
359                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
360                   "  ?work bf:creator/bf:label ?author .\n"
361                   "  ?work bf:note ?description .\n"
362                   "  ?inst bf:instanceOf ?work .\n"
363                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
364                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
365                   "  ?work bf:workTitle/bf:titleValue ?v0 "
366                   "FILTER(contains(?v0, \"computer\"))\n"
367                   "}\n"
368                   ));
369
370     YAZ_CHECK(test_query(
371                   s, "@attr 1=bf.creator london",
372                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
373                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
374                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
375                   "SELECT ?title ?author ?description ?ititle\n"
376                   "WHERE {\n"
377                   "  ?work a bf:Work .\n"
378                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
379                   "  ?work bf:creator/bf:label ?author .\n"
380                   "  ?work bf:note ?description .\n"
381                   "  ?inst bf:instanceOf ?work .\n"
382                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
383                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
384                   "  ?work bf:creator/bf:label ?v0 "
385                   "FILTER(contains(?v0, \"london\"))\n"
386                   "}\n"));
387
388     YAZ_CHECK(test_query(
389                   s, "@or @and @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
390                   "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
391                   "PREFIX bf: <http://bibframe.org/vocab/>\n"
392                   "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
393                   "SELECT ?title ?author ?description ?ititle\n"
394                   "WHERE {\n"
395                   "  ?work a bf:Work .\n"
396                   "  ?work bf:workTitle/bf:titleValue ?title .\n"
397                   "  ?work bf:creator/bf:label ?author .\n"
398                   "  ?work bf:note ?description .\n"
399                   "  ?inst bf:instanceOf ?work .\n"
400                   "  ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
401                   "  OPTIONAL { ?inst bf:heldBy ?lib } .\n"
402                   "  {\n"
403                   "   ?work bf:creator/bf:label ?v0 "
404                   "FILTER(contains(?v0, \"a\")) .\n"
405                   "   ?work bf:workTitle/bf:titleValue ?v1 "
406                   "FILTER(contains(?v1, \"b\"))\n"
407                   "  } UNION {\n"
408                   "   ?work bf:workTitle/bf:titleValue ?v2 "
409                   "FILTER(contains(?v2, \"c\"))\n"
410                   "  }\n"
411                   "}\n"
412                   ));
413
414     yaz_sparql_destroy(s);
415 }
416
417 int main(int argc, char **argv)
418 {
419     YAZ_CHECK_INIT(argc, argv);
420     YAZ_CHECK_LOG();
421     tst1();
422     tst2();
423     YAZ_CHECK_TERM;
424 }
425 /*
426  * Local variables:
427  * c-basic-offset: 4
428  * c-file-style: "Stroustrup"
429  * indent-tabs-mode: nil
430  * End:
431  * vim: shiftwidth=4 tabstop=8 expandtab
432  */
433