return yaz_sparql_from_rpn_stream(s, addinfo, wrbuf_vp_puts, w, q);
}
+static Odr_int lookup_attr_numeric(Z_AttributeList *attributes, int type)
+{
+ int j;
+ for (j = 0; j < attributes->num_attributes; j++)
+ {
+ Z_AttributeElement *ae = attributes->attributes[j];
+ if (*ae->attributeType == type)
+ {
+ if (ae->which == Z_AttributeValue_numeric)
+ return *ae->value.numeric;
+ }
+ }
+ return 0;
+}
+
+static const char *lookup_attr_string(Z_AttributeList *attributes, int type)
+{
+ int j;
+ for (j = 0; j < attributes->num_attributes; j++)
+ {
+ Z_AttributeElement *ae = attributes->attributes[j];
+ if (*ae->attributeType == type)
+ {
+ if (ae->which == Z_AttributeValue_complex)
+ {
+ Z_ComplexAttribute *ca = ae->value.complex;
+ int i;
+ for (i = 0; i < ca->num_list; i++)
+ {
+ Z_StringOrNumeric *son = ca->list[i];
+ if (son->which == Z_StringOrNumeric_string)
+ return son->u.string;
+ }
+ }
+ }
+ }
+ return 0;
+}
static int apt(yaz_sparql_t s,
WRBUF addinfo,
void (*pr)(const char *buf, void *client_data),
void *client_data,
- Z_AttributesPlusTerm *q)
+ 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;
+ int i;
+
+ pr(" ", client_data);
+ for (i = 0; i < indent; i++)
+ pr(" ", client_data);
+
+ if (v)
+ {
+ for (e = s->conf; e; e = e->next)
+ {
+ if (!strncmp(e->pattern, "index.", 6))
+ {
+ char *end = 0;
+ Odr_int w = odr_strtol(e->pattern + 6, &end, 10);
+
+ if (end && *end == '\0' && v == w)
+ break;
+ }
+ }
+ if (!e)
+ {
+ wrbuf_printf(addinfo, ODR_INT_PRINTF, v);
+ return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
+ }
+ }
+ else
+ {
+ const char *index_name = lookup_attr_string(q->attributes, 1);
+ if (!index_name)
+ index_name = "any";
+ for (e = s->conf; e; e = e->next)
+ {
+ if (!strncmp(e->pattern, "index.", 6))
+ {
+ if (!strcmp(e->pattern + 6, index_name))
+ break;
+ }
+ }
+ if (!e)
+ {
+ wrbuf_puts(addinfo, index_name);
+ return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
+ }
+ }
+ assert(e);
+ wrbuf_rewind(addinfo);
+ for (cp = e->value; *cp; cp++)
+ {
+ if (*cp == '%')
+ {
+ switch (*++cp)
+ {
+ case 's':
+ wrbuf_puts(addinfo, "\"");
+ switch (term->which)
+ {
+ case Z_Term_general:
+ wrbuf_json_write(addinfo,
+ term->u.general->buf, term->u.general->len);
+ break;
+ case Z_Term_numeric:
+ wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
+ break;
+ case Z_Term_characterString:
+ wrbuf_json_puts(addinfo, term->u.characterString);
+ break;
+ }
+ wrbuf_puts(addinfo, "\"");
+ break;
+ case 'd':
+ switch (term->which)
+ {
+ case Z_Term_general:
+ wrbuf_write(addinfo,
+ term->u.general->buf, term->u.general->len);
+ break;
+ case Z_Term_numeric:
+ wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
+ break;
+ case Z_Term_characterString:
+ wrbuf_puts(addinfo, term->u.characterString);
+ break;
+ }
+ break;
+ case '%':
+ wrbuf_putc(addinfo, '%');
+ break;
+ }
+ }
+ else
+ wrbuf_putc(addinfo, *cp);
+ }
+ pr(wrbuf_cstr(addinfo), client_data);
return 0;
}
void (*pr)(const char *buf,
void *client_data),
void *client_data,
- Z_RPNStructure *q)
+ Z_RPNStructure *q, int indent)
{
+ int i;
if (q->which == Z_RPNStructure_complex)
{
int r;
Z_Operator *op = c->roperator;
if (op->which == Z_Operator_and)
{
- r = rpn_structure(s, addinfo, pr, client_data, c->s1);
+ r = rpn_structure(s, addinfo, pr, client_data, c->s1,
+ indent);
if (r)
return r;
pr(" .\n", client_data);
- return rpn_structure(s, addinfo, pr, client_data, c->s2);
+ return rpn_structure(s, addinfo, pr, client_data, c->s2,
+ indent);
}
else if (op->which == Z_Operator_or)
{
- pr("{\n", client_data);
- r = rpn_structure(s, addinfo, pr, client_data, c->s1);
+ 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);
if (r)
return r;
- pr("} UNION {\n", client_data);
- r = rpn_structure(s, addinfo, pr, client_data, c->s1);
- pr("}\n", client_data);
+ pr("\n", client_data);
+ 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);
+ for (i = 0; i < indent; i++)
+ pr(" ", client_data);
+ pr(" }", client_data);
return r;
}
else
{
Z_Operand *op = q->u.simple;
if (op->which == Z_Operand_APT)
- return apt(s, addinfo, pr, client_data, op->u.attributesPlusTerm);
+ return apt(s, addinfo, pr, client_data, op->u.attributesPlusTerm,
+ indent);
else
return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
}
{
struct sparql_entry *e;
yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
- int errors = 0;
+ int r = 0, errors = 0;
for (e = s->conf; e; e = e->next)
{
{
;
}
- else if (!strncmp(e->pattern, "index", 5))
+ else if (!strncmp(e->pattern, "index.", 6))
{
;
}
pr(" .\n", client_data);
}
}
- rpn_structure(s, addinfo, pr, client_data, q->RPNStructure);
+ if (!errors)
+ r = rpn_structure(s, addinfo, pr, client_data, q->RPNStructure, 0);
- pr("}\n", client_data);
+ pr("\n}\n", client_data);
yaz_tok_cfg_destroy(cfg);
- return errors ? -1 : 0;
+ return errors ? -1 : r;
}
/*
"rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns");
yaz_sparql_add_pattern(s, "prefix",
"bf: <http://bibframe.org/vocab/>");
+ 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, "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, "index.bf.title",
+ "?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, %s))");
+ yaz_sparql_add_pattern(s, "index.bf.creator",
+ "?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, %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 ?o5 FILTER(contains(?o5, %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 "
+ "?o6 FILTER(contains(?o6, %s))");
+ yaz_sparql_add_pattern(s, "index.bf.baseCreator",
+ "?work bf:derivativeOf/bf:creator/bf:label "
+ "?o7 FILTER(contains(?o7, %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, "computer",
+ s, "@attr 1=bf.title computer",
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
"PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\n"
"\n"
"SELECT ?title ?author ?description ?ititle\n"
"WHERE {\n"
" ?work bf:note ?description .\n"
" ?inst bf:instanceOf ?work .\n"
" ?inst bf:instanceTitle/bf:titleValue ?ititle .\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"computer\"))\n"
"}\n"
-));
+ ));
+
+ YAZ_CHECK(test_query(
+ s, "@attr 1=bf.creator london",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"london\"))\n"
+ "}\n"));
+
+
+ YAZ_CHECK(test_query(
+ s, "@and @attr 1=bf.creator london @attr 1=bf.title computer",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"london\")) .\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"computer\"))\n"
+ "}\n"));
+
+ YAZ_CHECK(test_query(
+ s, "@or @attr 1=bf.creator london @attr 1=bf.title computer",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " {\n"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"london\"))\n"
+ " } UNION {\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"computer\"))\n"
+ " }\n"
+ "}\n"
+ ));
+
+ YAZ_CHECK(test_query(
+ s, "@or @or @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " {\n"
+ " {\n"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"a\"))\n"
+ " } UNION {\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"b\"))\n"
+ " }\n"
+ " } UNION {\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"c\"))\n"
+ " }\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: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " {\n"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"a\")) .\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"b\"))\n"
+ " } UNION {\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"c\"))\n"
+ " }\n"
+ "}\n"
+ ));
+
+ YAZ_CHECK(test_query(
+ s, "@and @and @attr 1=bf.creator a @attr 1=bf.title b @attr 1=bf.title c",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " ?work bf:creator/bf:label ?o2 "
+ "FILTER(contains(?o2, \"a\")) .\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"b\")) .\n"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"c\"))\n"
+ "}\n"
+ ));
+
+ YAZ_CHECK(test_query(
+ s, "@and @attr 1=bf.title \"Phantom Tollbooth\" "
+ "@attr 1=bf.nearby \"40.1583 83.0742 30\"",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " ?work bf:workTitle/bf:titleValue ?o1 "
+ "FILTER(contains(?o1, \"Phantom Tollbooth\")) .\n"
+ " ?lib gs:nearby (40.1583 83.0742 30)\n"
+ "}\n"
+ ));
+
+ YAZ_CHECK(test_query(
+ s, "@attr 1=bf.isbn 9780316154697",
+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ "PREFIX gs: <http://gs.com/panorama/domain-model>\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"
+ " ?inst bf:ISBN \"9780316154697\"\n"
+ "}\n"
+ ));
+
yaz_sparql_destroy(s);
}