From: Adam Dickmeiss Date: Wed, 12 Nov 2014 12:11:30 +0000 (+0100) Subject: SPARQL: Add support for local variables: %v X-Git-Url: http://lists.indexdata.dk/?a=commitdiff_plain;h=refs%2Fheads%2Fyaz-799;p=yaz-moved-to-github.git SPARQL: Add support for local variables: %v --- diff --git a/src/sparql.c b/src/sparql.c index b85ee76..a848a9d 100644 --- a/src/sparql.c +++ b/src/sparql.c @@ -105,7 +105,7 @@ static const char *lookup_attr_string(Z_AttributeList *attributes, int type) } static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars, - Z_AttributesPlusTerm *q, int indent) + Z_AttributesPlusTerm *q, int indent, int *var_no) { Z_Term *term = q->term; Odr_int v = lookup_attr_numeric(q->attributes, 1); @@ -205,6 +205,9 @@ static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars, break; } break; + case 'v': + wrbuf_printf(addinfo, "?v%d", *var_no); + break; case '%': wrbuf_putc(addinfo, '%'); break; @@ -214,12 +217,14 @@ static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars, wrbuf_putc(addinfo, *cp); } wrbuf_puts(res, wrbuf_cstr(addinfo)); + (*var_no)++; return 0; } static int rpn_structure(yaz_sparql_t s, WRBUF addinfo, - WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent) + WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent, + int *var_no) { int i; if (q->which == Z_RPNStructure_complex) @@ -229,25 +234,25 @@ static int rpn_structure(yaz_sparql_t s, WRBUF addinfo, Z_Operator *op = c->roperator; if (op->which == Z_Operator_and) { - r = rpn_structure(s, addinfo, res, vars, c->s1, indent); + r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no); if (r) return r; wrbuf_puts(res, " .\n"); - return rpn_structure(s, addinfo, res, vars, c->s2, indent); + return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no); } else if (op->which == Z_Operator_or) { for (i = 0; i < indent; i++) wrbuf_puts(res, " "); wrbuf_puts(res, " {\n"); - r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1); + r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no); if (r) return r; wrbuf_puts(res, "\n"); for (i = 0; i < indent; i++) wrbuf_puts(res, " "); wrbuf_puts(res, " } UNION {\n"); - r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1); + r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no); wrbuf_puts(res, "\n"); for (i = 0; i < indent; i++) wrbuf_puts(res, " "); @@ -263,7 +268,8 @@ static int rpn_structure(yaz_sparql_t s, WRBUF addinfo, { Z_Operand *op = q->u.simple; if (op->which == Z_Operand_APT) - return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent); + return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent, + var_no); else return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM; } @@ -357,7 +363,8 @@ int yaz_sparql_from_rpn_stream(yaz_sparql_t s, { WRBUF res = wrbuf_alloc(); WRBUF vars = wrbuf_alloc(); - r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0); + int var_no = 0; + r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no); if (r == 0) { WRBUF t_var = wrbuf_alloc(); diff --git a/test/test_sparql.c b/test/test_sparql.c index cee9550..f67dbcc 100644 --- a/test/test_sparql.c +++ b/test/test_sparql.c @@ -319,11 +319,125 @@ static void tst1(void) yaz_sparql_destroy(s); } +static void tst2(void) +{ + yaz_sparql_t s = yaz_sparql_create(); + + yaz_sparql_add_pattern(s, "prefix", + "rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns"); + yaz_sparql_add_pattern(s, "prefix", + "bf: "); + yaz_sparql_add_pattern(s, "prefix", + "gs: http://gs.com/panorama/domain-model"); + yaz_sparql_add_pattern(s, "field.title", "?title"); + yaz_sparql_add_pattern(s, "field.author", "?author"); + yaz_sparql_add_pattern(s, "field.description", "?description"); + yaz_sparql_add_pattern(s, "field.instanceTitle", "?ititle"); + yaz_sparql_add_pattern(s, "criteria", "?work a bf:Work"); + yaz_sparql_add_pattern(s, "criteria", "?work bf:workTitle/bf:titleValue ?title"); + yaz_sparql_add_pattern(s, "criteria", "?work bf:creator/bf:label ?author"); + 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 %v " + "FILTER(contains(%v, %s))"); + yaz_sparql_add_pattern(s, "index.bf.creator", + "?work bf:creator/bf:label %v " + "FILTER(contains(%v, %s))"); + yaz_sparql_add_pattern(s, "index.bf.authorityCreator", + "?work bf:author %s"); + yaz_sparql_add_pattern(s, "index.bf.type", "?inst rdf:type %s"); + yaz_sparql_add_pattern(s, "index.bf.format", + "?inst bf:format %v FILTER(contains(%v, %s))"); + yaz_sparql_add_pattern(s, "index.bf.nearby", "?lib gs:nearby (%d)"); + yaz_sparql_add_pattern(s, "index.bf.baseTitle", + "?work bf:derivativeOf/bf:workTitle/bf:titleValue " + "%v FILTER(contains(%v, %s))"); + yaz_sparql_add_pattern(s, "index.bf.baseCreator", + "?work bf:derivativeOf/bf:creator/bf:label " + "%v FILTER(contains(%v, %s))"); + yaz_sparql_add_pattern(s, "index.bf.targetAudience", + "?work bf:targetAudience %s"); + yaz_sparql_add_pattern(s, "index.bf.isbn", "?inst bf:ISBN %s"); + + YAZ_CHECK(test_query( + s, "@attr 1=bf.title computer", + "PREFIX rdf: \n" + "PREFIX bf: \n" + "PREFIX gs: \n" + "\n" + "SELECT ?title ?author ?description ?ititle\n" + "WHERE {\n" + " ?work a bf:Work .\n" + " ?work bf:workTitle/bf:titleValue ?title .\n" + " ?work bf:creator/bf:label ?author .\n" + " ?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 ?v0 " + "FILTER(contains(?v0, \"computer\"))\n" + "}\n" + )); + + YAZ_CHECK(test_query( + s, "@attr 1=bf.creator london", + "PREFIX rdf: \n" + "PREFIX bf: \n" + "PREFIX gs: \n" + "\n" + "SELECT ?title ?author ?description ?ititle\n" + "WHERE {\n" + " ?work a bf:Work .\n" + " ?work bf:workTitle/bf:titleValue ?title .\n" + " ?work bf:creator/bf:label ?author .\n" + " ?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 ?v0 " + "FILTER(contains(?v0, \"london\"))\n" + "}\n")); + + YAZ_CHECK(test_query( + s, "@or @and @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c", + "PREFIX rdf: \n" + "PREFIX bf: \n" + "PREFIX gs: \n" + "\n" + "SELECT ?title ?author ?description ?ititle\n" + "WHERE {\n" + " ?work a bf:Work .\n" + " ?work bf:workTitle/bf:titleValue ?title .\n" + " ?work bf:creator/bf:label ?author .\n" + " ?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 ?v0 " + "FILTER(contains(?v0, \"a\")) .\n" + " ?work bf:workTitle/bf:titleValue ?v1 " + "FILTER(contains(?v1, \"b\"))\n" + " } UNION {\n" + " ?work bf:workTitle/bf:titleValue ?v2 " + "FILTER(contains(?v2, \"c\"))\n" + " }\n" + "}\n" + )); + + yaz_sparql_destroy(s); +} + int main(int argc, char **argv) { YAZ_CHECK_INIT(argc, argv); YAZ_CHECK_LOG(); tst1(); + tst2(); YAZ_CHECK_TERM; } /*