From 15aec38caac1af2f751e8a0577b58cc1d78ecced Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Mon, 10 Nov 2014 14:40:34 +0100 Subject: [PATCH] Support of criteria.optional --- src/sparql.c | 111 ++++++++++++++++++++++++++++++++++++---------------- test/test_sparql.c | 11 ++++++ 2 files changed, 88 insertions(+), 34 deletions(-) diff --git a/src/sparql.c b/src/sparql.c index fb6c302..b85ee76 100644 --- a/src/sparql.c +++ b/src/sparql.c @@ -104,22 +104,19 @@ static const char *lookup_attr_string(Z_AttributeList *attributes, int type) return 0; } -static int apt(yaz_sparql_t s, - WRBUF addinfo, - void (*pr)(const char *buf, void *client_data), - void *client_data, +static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars, Z_AttributesPlusTerm *q, int indent) { Z_Term *term = q->term; Odr_int v = lookup_attr_numeric(q->attributes, 1); struct sparql_entry *e = 0; const char *cp; + const char *use_var = 0; int i; - pr(" ", client_data); + wrbuf_puts(res, " "); for (i = 0; i < indent; i++) - pr(" ", client_data); - + wrbuf_puts(res, " "); if (v) { for (e = s->conf; e; e = e->next) @@ -160,8 +157,18 @@ static int apt(yaz_sparql_t s, } assert(e); wrbuf_rewind(addinfo); + for (cp = e->value; *cp; cp++) { + if (strchr(" \t\r\n\f", *cp) && !use_var) + { + use_var = e->value; + if (strchr("$?", e->value[0])) + { + wrbuf_write(vars, e->value + 1, cp - e->value - 1); + wrbuf_puts(vars, " "); + } + } if (*cp == '%') { switch (*++cp) @@ -206,17 +213,13 @@ static int apt(yaz_sparql_t s, else wrbuf_putc(addinfo, *cp); } - pr(wrbuf_cstr(addinfo), client_data); + wrbuf_puts(res, wrbuf_cstr(addinfo)); return 0; } -static int rpn_structure(yaz_sparql_t s, - WRBUF addinfo, - void (*pr)(const char *buf, - void *client_data), - void *client_data, - Z_RPNStructure *q, int indent) +static int rpn_structure(yaz_sparql_t s, WRBUF addinfo, + WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent) { int i; if (q->which == Z_RPNStructure_complex) @@ -226,33 +229,29 @@ static int rpn_structure(yaz_sparql_t s, Z_Operator *op = c->roperator; if (op->which == Z_Operator_and) { - r = rpn_structure(s, addinfo, pr, client_data, c->s1, - indent); + r = rpn_structure(s, addinfo, res, vars, c->s1, indent); if (r) return r; - pr(" .\n", client_data); - return rpn_structure(s, addinfo, pr, client_data, c->s2, - indent); + wrbuf_puts(res, " .\n"); + return rpn_structure(s, addinfo, res, vars, c->s2, indent); } else if (op->which == Z_Operator_or) { for (i = 0; i < indent; i++) - pr(" ", client_data); - pr(" {\n", client_data); - r = rpn_structure(s, addinfo, pr, client_data, c->s1, - indent + 1); + wrbuf_puts(res, " "); + wrbuf_puts(res, " {\n"); + r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1); if (r) return r; - pr("\n", client_data); + wrbuf_puts(res, "\n"); for (i = 0; i < indent; i++) - pr(" ", client_data); - pr(" } UNION {\n", client_data); - r = rpn_structure(s, addinfo, pr, client_data, c->s2, - indent + 1); - pr("\n", client_data); + wrbuf_puts(res, " "); + wrbuf_puts(res, " } UNION {\n"); + r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1); + wrbuf_puts(res, "\n"); for (i = 0; i < indent; i++) - pr(" ", client_data); - pr(" }", client_data); + wrbuf_puts(res, " "); + wrbuf_puts(res, " }"); return r; } else @@ -264,8 +263,7 @@ static int rpn_structure(yaz_sparql_t s, { Z_Operand *op = q->u.simple; if (op->which == Z_Operand_APT) - return apt(s, addinfo, pr, client_data, op->u.attributesPlusTerm, - indent); + return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent); else return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM; } @@ -317,6 +315,10 @@ int yaz_sparql_from_rpn_stream(yaz_sparql_t s, { ; } + else if (!strcmp(e->pattern, "criteria.optional")) + { + ; + } else if (!strncmp(e->pattern, "index.", 6)) { ; @@ -352,8 +354,49 @@ int yaz_sparql_from_rpn_stream(yaz_sparql_t s, } } if (!errors) - r = rpn_structure(s, addinfo, pr, client_data, q->RPNStructure, 0); + { + WRBUF res = wrbuf_alloc(); + WRBUF vars = wrbuf_alloc(); + r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0); + if (r == 0) + { + WRBUF t_var = wrbuf_alloc(); + for (e = s->conf; e; e = e->next) + { + if (!strcmp(e->pattern, "criteria.optional")) + { + int optional = 1; + size_t i = strlen(e->value), j; + + while (i > 0 && strchr(" \t\r\n\f", e->value[i-1])) + --i; + j = i; + while (i > 0 && !strchr("$?", e->value[i-1])) + --i; + if (i > 0 && j > i) + { + wrbuf_rewind(t_var); + wrbuf_write(t_var, e->value + i, j - i); + wrbuf_puts(t_var, " "); + if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var))) + optional = 0; + } + pr(" ", client_data); + if (optional) + pr("OPTIONAL { ", client_data); + pr(e->value, client_data); + if (optional) + pr(" }", client_data); + pr(" .\n", client_data); + } + } + pr(wrbuf_cstr(res), client_data); + wrbuf_destroy(t_var); + } + wrbuf_destroy(res); + wrbuf_destroy(vars); + } pr("\n}\n", client_data); yaz_tok_cfg_destroy(cfg); diff --git a/test/test_sparql.c b/test/test_sparql.c index 6ead793..cee9550 100644 --- a/test/test_sparql.c +++ b/test/test_sparql.c @@ -83,6 +83,8 @@ static void tst1(void) yaz_sparql_add_pattern(s, "criteria", "?work bf:note ?description"); yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceOf ?work"); yaz_sparql_add_pattern(s, "criteria", "?inst bf:instanceTitle/bf:titleValue ?ititle"); + yaz_sparql_add_pattern(s, "criteria.optional", "?inst bf:heldBy ?lib"); + yaz_sparql_add_pattern(s, "index.bf.title", "?work bf:workTitle/bf:titleValue ?o1 " "FILTER(contains(?o1, %s))"); @@ -119,6 +121,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " ?work bf:workTitle/bf:titleValue ?o1 " "FILTER(contains(?o1, \"computer\"))\n" "}\n" @@ -138,6 +141,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " ?work bf:creator/bf:label ?o2 " "FILTER(contains(?o2, \"london\"))\n" "}\n")); @@ -157,6 +161,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " ?work bf:creator/bf:label ?o2 " "FILTER(contains(?o2, \"london\")) .\n" " ?work bf:workTitle/bf:titleValue ?o1 " @@ -177,6 +182,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " {\n" " ?work bf:creator/bf:label ?o2 " "FILTER(contains(?o2, \"london\"))\n" @@ -201,6 +207,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " {\n" " {\n" " ?work bf:creator/bf:label ?o2 " @@ -230,6 +237,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " {\n" " ?work bf:creator/bf:label ?o2 " "FILTER(contains(?o2, \"a\")) .\n" @@ -256,6 +264,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " ?work bf:creator/bf:label ?o2 " "FILTER(contains(?o2, \"a\")) .\n" " ?work bf:workTitle/bf:titleValue ?o1 " @@ -280,6 +289,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " ?inst bf:heldBy ?lib .\n" " ?work bf:workTitle/bf:titleValue ?o1 " "FILTER(contains(?o1, \"Phantom Tollbooth\")) .\n" " ?lib gs:nearby (40.1583 83.0742 30)\n" @@ -300,6 +310,7 @@ static void tst1(void) " ?work bf:note ?description .\n" " ?inst bf:instanceOf ?work .\n" " ?inst bf:instanceTitle/bf:titleValue ?ititle .\n" + " OPTIONAL { ?inst bf:heldBy ?lib } .\n" " ?inst bf:ISBN \"9780316154697\"\n" "}\n" )); -- 1.7.10.4