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)
}
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)
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)
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
{
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;
}
{
;
}
+ else if (!strcmp(e->pattern, "criteria.optional"))
+ {
+ ;
+ }
else if (!strncmp(e->pattern, "index.", 6))
{
;
}
}
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);
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))");
" ?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"
" ?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"));
" ?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 "
" ?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"
" ?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 "
" ?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"
" ?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 "
" ?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"
" ?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"
));