7 #include <yaz/diagbib1.h>
8 #include <yaz/tokenizer.h>
14 struct sparql_entry *next;
19 struct sparql_entry *conf;
20 struct sparql_entry **last;
23 yaz_sparql_t yaz_sparql_create(void)
25 NMEM nmem = nmem_create();
26 yaz_sparql_t s = (yaz_sparql_t) nmem_malloc(nmem, sizeof *s);
34 void yaz_sparql_destroy(yaz_sparql_t s)
37 nmem_destroy(s->nmem);
40 void yaz_sparql_include(yaz_sparql_t s, yaz_sparql_t u)
42 struct sparql_entry *e = u->conf;
43 for (; e; e = e->next)
44 yaz_sparql_add_pattern(s, e->pattern, e->value);
47 int yaz_sparql_add_pattern(yaz_sparql_t s, const char *pattern,
50 struct sparql_entry *e;
53 e = (struct sparql_entry *) nmem_malloc(s->nmem, sizeof(*e));
54 e->pattern = nmem_strdup(s->nmem, pattern);
55 e->value = nmem_strdup(s->nmem, value);
62 int yaz_sparql_from_rpn_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
65 return yaz_sparql_from_rpn_stream(s, addinfo, wrbuf_vp_puts, w, q);
68 int yaz_sparql_from_uri_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
69 const char *uri, const char *schema)
71 return yaz_sparql_from_uri_stream(s, addinfo, wrbuf_vp_puts, w, uri,
75 static Odr_int lookup_attr_numeric(Z_AttributeList *attributes, int type)
78 for (j = 0; j < attributes->num_attributes; j++)
80 Z_AttributeElement *ae = attributes->attributes[j];
81 if (*ae->attributeType == type)
83 if (ae->which == Z_AttributeValue_numeric)
84 return *ae->value.numeric;
90 static const char *lookup_attr_string(Z_AttributeList *attributes, int type)
93 for (j = 0; j < attributes->num_attributes; j++)
95 Z_AttributeElement *ae = attributes->attributes[j];
96 if (*ae->attributeType == type)
98 if (ae->which == Z_AttributeValue_complex)
100 Z_ComplexAttribute *ca = ae->value.complex;
102 for (i = 0; i < ca->num_list; i++)
104 Z_StringOrNumeric *son = ca->list[i];
105 if (son->which == Z_StringOrNumeric_string)
106 return son->u.string;
114 static int z_term(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
115 struct sparql_entry *e, const char *use_var,
116 Z_Term *term, int indent, int *var_no)
119 for (cp = e->value; *cp; cp++)
121 if (strchr(" \t\r\n\f", *cp) && !use_var)
124 if (strchr("$?", e->value[0]))
126 wrbuf_write(vars, e->value + 1, cp - e->value - 1);
127 wrbuf_puts(vars, " ");
135 wrbuf_puts(addinfo, "\"");
139 wrbuf_json_write(addinfo,
140 term->u.general->buf, term->u.general->len);
143 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
145 case Z_Term_characterString:
146 wrbuf_json_puts(addinfo, term->u.characterString);
149 wrbuf_puts(addinfo, "\"");
152 wrbuf_puts(addinfo, "<");
156 wrbuf_json_write(addinfo,
157 term->u.general->buf, term->u.general->len);
160 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
162 case Z_Term_characterString:
163 wrbuf_json_puts(addinfo, term->u.characterString);
166 wrbuf_puts(addinfo, ">");
172 wrbuf_json_write(addinfo,
173 term->u.general->buf, term->u.general->len);
176 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
178 case Z_Term_characterString:
179 wrbuf_json_puts(addinfo, term->u.characterString);
188 term->u.general->buf, term->u.general->len);
191 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
193 case Z_Term_characterString:
194 wrbuf_puts(addinfo, term->u.characterString);
199 wrbuf_printf(addinfo, "?v%d", *var_no);
202 wrbuf_putc(addinfo, '%');
207 wrbuf_putc(addinfo, *cp);
209 wrbuf_puts(res, wrbuf_cstr(addinfo));
213 static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
214 Z_AttributesPlusTerm *q, int indent, int *var_no)
216 Odr_int v = lookup_attr_numeric(q->attributes, 1);
217 struct sparql_entry *e = 0;
218 const char *use_var = 0;
221 wrbuf_puts(res, " ");
222 for (i = 0; i < indent; i++)
223 wrbuf_puts(res, " ");
226 for (e = s->conf; e; e = e->next)
228 if (!strncmp(e->pattern, "index.", 6))
231 Odr_int w = odr_strtol(e->pattern + 6, &end, 10);
233 if (end && *end == '\0' && v == w)
239 wrbuf_printf(addinfo, ODR_INT_PRINTF, v);
240 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
245 const char *index_name = lookup_attr_string(q->attributes, 1);
248 for (e = s->conf; e; e = e->next)
250 if (!strncmp(e->pattern, "index.", 6))
252 if (!strcmp(e->pattern + 6, index_name))
258 wrbuf_puts(addinfo, index_name);
259 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
263 wrbuf_rewind(addinfo);
265 z_term(s, addinfo, res, vars, e, use_var, q->term, indent, var_no);
271 static int rpn_structure(yaz_sparql_t s, WRBUF addinfo,
272 WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent,
276 if (q->which == Z_RPNStructure_complex)
279 Z_Complex *c = q->u.complex;
280 Z_Operator *op = c->roperator;
281 if (op->which == Z_Operator_and)
283 r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no);
286 wrbuf_puts(res, " .\n");
287 return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no);
289 else if (op->which == Z_Operator_or)
291 for (i = 0; i < indent; i++)
292 wrbuf_puts(res, " ");
293 wrbuf_puts(res, " {\n");
294 r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no);
297 wrbuf_puts(res, "\n");
298 for (i = 0; i < indent; i++)
299 wrbuf_puts(res, " ");
300 wrbuf_puts(res, " } UNION {\n");
301 r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no);
302 wrbuf_puts(res, "\n");
303 for (i = 0; i < indent; i++)
304 wrbuf_puts(res, " ");
305 wrbuf_puts(res, " }");
310 return YAZ_BIB1_OPERATOR_UNSUPP;
315 Z_Operand *op = q->u.simple;
316 if (op->which == Z_Operand_APT)
317 return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent,
320 return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
325 static int emit_prefixes(yaz_sparql_t s,
327 void (*pr)(const char *buf,
331 struct sparql_entry *e;
332 yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
334 for (e = s->conf; e; e = e->next)
336 if (!strcmp(e->pattern, "prefix"))
338 yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
341 pr("PREFIX", client_data);
345 int token = yaz_tok_move(p);
346 if (token != YAZ_TOK_STRING)
348 pr(" ", client_data);
350 tok_str = yaz_tok_parse_string(p);
353 if (no > 0 && tok_str[0] != '<')
354 pr("<", client_data);
355 pr(tok_str, client_data);
356 if (no > 0 && tok_str[strlen(tok_str)-1] != '>')
357 pr(">", client_data);
361 pr("\n", client_data);
362 yaz_tok_parse_destroy(p);
364 else if (!strcmp(e->pattern, "criteria"))
368 else if (!strcmp(e->pattern, "criteria.optional"))
372 else if (!strncmp(e->pattern, "index.", 6))
376 else if (!strcmp(e->pattern, "form"))
380 else if (!strcmp(e->pattern, "modifier"))
384 else if (!strncmp(e->pattern, "present", 7))
388 else if (!strncmp(e->pattern, "uri", 3))
397 yaz_tok_cfg_destroy(cfg);
401 struct sparql_entry *lookup_schema(yaz_sparql_t s, const char *schema)
403 struct sparql_entry *e;
405 for (e = s->conf; e; e = e->next)
407 if (!strncmp(e->pattern, "present.", 8))
409 if (!schema || !strcmp(e->pattern + 8, schema))
412 if (!strncmp(e->pattern, "uri.", 4))
414 if (!schema || !strcmp(e->pattern + 4, schema))
421 int yaz_sparql_lookup_schema(yaz_sparql_t s, const char *schema)
423 return lookup_schema(s, schema) ? 1 : 0;
426 int yaz_sparql_from_uri_stream(yaz_sparql_t s,
428 void (*pr)(const char *buf, void *client_data),
430 const char *uri, const char *schema)
432 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
433 struct sparql_entry *e = lookup_schema(s, schema);
438 WRBUF res = wrbuf_alloc();
439 WRBUF vars = wrbuf_alloc();
443 term.which = Z_Term_characterString;
444 term.u.characterString = (char *) uri;
445 r = z_term(s, addinfo, res, vars, e, 0, &term, 0, &var_no);
448 pr(wrbuf_cstr(res), client_data);
449 pr("\n", client_data);
454 return errors ? -1 : r;
457 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
459 void (*pr)(const char *buf,
464 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
465 struct sparql_entry *e;
467 for (e = s->conf; e; e = e->next)
469 if (!strcmp(e->pattern, "form"))
471 pr(e->value, client_data);
472 pr("\n", client_data);
475 pr("WHERE {\n", client_data);
476 for (e = s->conf; e; e = e->next)
478 if (!strcmp(e->pattern, "criteria"))
480 pr(" ", client_data);
481 pr(e->value, client_data);
482 pr(" .\n", client_data);
487 WRBUF res = wrbuf_alloc();
488 WRBUF vars = wrbuf_alloc();
490 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
493 WRBUF t_var = wrbuf_alloc();
494 for (e = s->conf; e; e = e->next)
496 if (!strcmp(e->pattern, "criteria.optional"))
499 size_t i = strlen(e->value), j;
501 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
504 while (i > 0 && !strchr("$?", e->value[i-1]))
509 wrbuf_write(t_var, e->value + i, j - i);
510 wrbuf_puts(t_var, " ");
511 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
515 pr(" ", client_data);
517 pr("OPTIONAL { ", client_data);
518 pr(e->value, client_data);
520 pr(" }", client_data);
521 pr(" .\n", client_data);
524 pr(wrbuf_cstr(res), client_data);
525 wrbuf_destroy(t_var);
530 pr("\n}\n", client_data);
532 for (e = s->conf; e; e = e->next)
534 if (!strcmp(e->pattern, "modifier"))
536 pr(e->value, client_data);
537 pr("\n", client_data);
540 return errors ? -1 : r;
543 void yaz_sparql_explain_indexes( yaz_sparql_t s, WRBUF w, int indent)
545 char indentspace[200]; // must be enough
548 for (i=0; i < indent; i++)
549 indentspace[i] = ' ';
550 indentspace[indent] = '\0';
552 struct sparql_entry *e;
553 wrbuf_puts(w,indentspace);
554 wrbuf_puts(w,"<indexInfo>\n");
556 for (e = s->conf; e; e = e->next)
559 wrbuf_puts(w," <FOO>");
560 wrbuf_xmlputs(w, e->pattern );
562 wrbuf_xmlputs(w, e->value );
563 wrbuf_puts(w," </FOO>\n");
565 if ( strncmp(e->pattern, "index.", 6 ) == 0 )
567 wrbuf_puts(w,indentspace);
568 wrbuf_puts(w," <index>\n");
569 wrbuf_puts(w,indentspace);
570 wrbuf_puts(w," <title>");
571 wrbuf_xmlputs(w, e->pattern + 6);
572 wrbuf_puts(w,"</title>\n");
573 wrbuf_puts(w,indentspace);
574 wrbuf_puts(w," <map><name>");
575 wrbuf_xmlputs(w, e->pattern + 6);
576 wrbuf_puts(w,"</name></map>\n");
577 wrbuf_puts(w,indentspace);
578 wrbuf_puts(w," </index>\n");
581 wrbuf_puts(w,indentspace);
582 wrbuf_puts(w,"</indexInfo>\n");
588 * c-file-style: "Stroustrup"
589 * indent-tabs-mode: nil
591 * vim: shiftwidth=4 tabstop=8 expandtab