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 int yaz_sparql_add_pattern(yaz_sparql_t s, const char *pattern,
43 struct sparql_entry *e;
46 e = (struct sparql_entry *) nmem_malloc(s->nmem, sizeof(*e));
47 e->pattern = nmem_strdup(s->nmem, pattern);
48 e->value = nmem_strdup(s->nmem, value);
55 int yaz_sparql_from_rpn_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
58 return yaz_sparql_from_rpn_stream(s, addinfo, wrbuf_vp_puts, w, q);
61 int yaz_sparql_from_uri_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
62 const char *uri, const char *schema)
64 return yaz_sparql_from_uri_stream(s, addinfo, wrbuf_vp_puts, w, uri,
68 static Odr_int lookup_attr_numeric(Z_AttributeList *attributes, int type)
71 for (j = 0; j < attributes->num_attributes; j++)
73 Z_AttributeElement *ae = attributes->attributes[j];
74 if (*ae->attributeType == type)
76 if (ae->which == Z_AttributeValue_numeric)
77 return *ae->value.numeric;
83 static const char *lookup_attr_string(Z_AttributeList *attributes, int type)
86 for (j = 0; j < attributes->num_attributes; j++)
88 Z_AttributeElement *ae = attributes->attributes[j];
89 if (*ae->attributeType == type)
91 if (ae->which == Z_AttributeValue_complex)
93 Z_ComplexAttribute *ca = ae->value.complex;
95 for (i = 0; i < ca->num_list; i++)
97 Z_StringOrNumeric *son = ca->list[i];
98 if (son->which == Z_StringOrNumeric_string)
107 static int z_term(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
108 struct sparql_entry *e, const char *use_var,
109 Z_Term *term, int indent, int *var_no)
112 for (cp = e->value; *cp; cp++)
114 if (strchr(" \t\r\n\f", *cp) && !use_var)
117 if (strchr("$?", e->value[0]))
119 wrbuf_write(vars, e->value + 1, cp - e->value - 1);
120 wrbuf_puts(vars, " ");
128 wrbuf_puts(addinfo, "\"");
132 wrbuf_json_write(addinfo,
133 term->u.general->buf, term->u.general->len);
136 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
138 case Z_Term_characterString:
139 wrbuf_json_puts(addinfo, term->u.characterString);
142 wrbuf_puts(addinfo, "\"");
145 wrbuf_puts(addinfo, "<");
149 wrbuf_json_write(addinfo,
150 term->u.general->buf, term->u.general->len);
153 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
155 case Z_Term_characterString:
156 wrbuf_json_puts(addinfo, term->u.characterString);
159 wrbuf_puts(addinfo, ">");
166 term->u.general->buf, term->u.general->len);
169 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
171 case Z_Term_characterString:
172 wrbuf_puts(addinfo, term->u.characterString);
177 wrbuf_printf(addinfo, "?v%d", *var_no);
180 wrbuf_putc(addinfo, '%');
185 wrbuf_putc(addinfo, *cp);
187 wrbuf_puts(res, wrbuf_cstr(addinfo));
191 static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
192 Z_AttributesPlusTerm *q, int indent, int *var_no)
194 Odr_int v = lookup_attr_numeric(q->attributes, 1);
195 struct sparql_entry *e = 0;
196 const char *use_var = 0;
199 wrbuf_puts(res, " ");
200 for (i = 0; i < indent; i++)
201 wrbuf_puts(res, " ");
204 for (e = s->conf; e; e = e->next)
206 if (!strncmp(e->pattern, "index.", 6))
209 Odr_int w = odr_strtol(e->pattern + 6, &end, 10);
211 if (end && *end == '\0' && v == w)
217 wrbuf_printf(addinfo, ODR_INT_PRINTF, v);
218 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
223 const char *index_name = lookup_attr_string(q->attributes, 1);
226 for (e = s->conf; e; e = e->next)
228 if (!strncmp(e->pattern, "index.", 6))
230 if (!strcmp(e->pattern + 6, index_name))
236 wrbuf_puts(addinfo, index_name);
237 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
241 wrbuf_rewind(addinfo);
243 z_term(s, addinfo, res, vars, e, use_var, q->term, indent, var_no);
249 static int rpn_structure(yaz_sparql_t s, WRBUF addinfo,
250 WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent,
254 if (q->which == Z_RPNStructure_complex)
257 Z_Complex *c = q->u.complex;
258 Z_Operator *op = c->roperator;
259 if (op->which == Z_Operator_and)
261 r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no);
264 wrbuf_puts(res, " .\n");
265 return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no);
267 else if (op->which == Z_Operator_or)
269 for (i = 0; i < indent; i++)
270 wrbuf_puts(res, " ");
271 wrbuf_puts(res, " {\n");
272 r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no);
275 wrbuf_puts(res, "\n");
276 for (i = 0; i < indent; i++)
277 wrbuf_puts(res, " ");
278 wrbuf_puts(res, " } UNION {\n");
279 r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no);
280 wrbuf_puts(res, "\n");
281 for (i = 0; i < indent; i++)
282 wrbuf_puts(res, " ");
283 wrbuf_puts(res, " }");
288 return YAZ_BIB1_OPERATOR_UNSUPP;
293 Z_Operand *op = q->u.simple;
294 if (op->which == Z_Operand_APT)
295 return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent,
298 return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
303 static int emit_prefixes(yaz_sparql_t s,
305 void (*pr)(const char *buf,
309 struct sparql_entry *e;
310 yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
312 for (e = s->conf; e; e = e->next)
314 if (!strcmp(e->pattern, "prefix"))
316 yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
319 pr("PREFIX", client_data);
323 int token = yaz_tok_move(p);
324 if (token != YAZ_TOK_STRING)
326 pr(" ", client_data);
328 tok_str = yaz_tok_parse_string(p);
331 if (no > 0 && tok_str[0] != '<')
332 pr("<", client_data);
333 pr(tok_str, client_data);
334 if (no > 0 && tok_str[strlen(tok_str)-1] != '>')
335 pr(">", client_data);
339 pr("\n", client_data);
340 yaz_tok_parse_destroy(p);
342 else if (!strcmp(e->pattern, "criteria"))
346 else if (!strcmp(e->pattern, "criteria.optional"))
350 else if (!strncmp(e->pattern, "index.", 6))
354 else if (!strcmp(e->pattern, "form"))
358 else if (!strcmp(e->pattern, "modifier"))
362 else if (!strncmp(e->pattern, "uri", 3))
371 yaz_tok_cfg_destroy(cfg);
375 int yaz_sparql_lookup_schema(yaz_sparql_t s, const char *schema)
377 struct sparql_entry *e;
379 for (e = s->conf; e; e = e->next)
381 if (!schema && !strcmp(e->pattern, "uri"))
383 else if (schema && !strncmp(e->pattern, "uri.", 4))
385 if (!strcmp(e->pattern + 4, schema))
392 int yaz_sparql_from_uri_stream(yaz_sparql_t s,
394 void (*pr)(const char *buf, void *client_data),
396 const char *uri, const char *schema)
398 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
399 struct sparql_entry *e;
401 for (e = s->conf; e; e = e->next)
403 if (!schema && !strcmp(e->pattern, "uri"))
405 else if (schema && !strncmp(e->pattern, "uri.", 4))
407 if (!strcmp(e->pattern + 4, schema))
415 WRBUF res = wrbuf_alloc();
416 WRBUF vars = wrbuf_alloc();
420 term.which = Z_Term_characterString;
421 term.u.characterString = (char *) uri;
422 r = z_term(s, addinfo, res, vars, e, 0, &term, 0, &var_no);
425 pr(wrbuf_cstr(res), client_data);
426 pr("\n", client_data);
431 return errors ? -1 : r;
434 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
436 void (*pr)(const char *buf,
441 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
442 struct sparql_entry *e;
444 for (e = s->conf; e; e = e->next)
446 if (!strcmp(e->pattern, "form"))
448 pr(e->value, client_data);
449 pr("\n", client_data);
452 pr("WHERE {\n", client_data);
453 for (e = s->conf; e; e = e->next)
455 if (!strcmp(e->pattern, "criteria"))
457 pr(" ", client_data);
458 pr(e->value, client_data);
459 pr(" .\n", client_data);
464 WRBUF res = wrbuf_alloc();
465 WRBUF vars = wrbuf_alloc();
467 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
470 WRBUF t_var = wrbuf_alloc();
471 for (e = s->conf; e; e = e->next)
473 if (!strcmp(e->pattern, "criteria.optional"))
476 size_t i = strlen(e->value), j;
478 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
481 while (i > 0 && !strchr("$?", e->value[i-1]))
486 wrbuf_write(t_var, e->value + i, j - i);
487 wrbuf_puts(t_var, " ");
488 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
492 pr(" ", client_data);
494 pr("OPTIONAL { ", client_data);
495 pr(e->value, client_data);
497 pr(" }", client_data);
498 pr(" .\n", client_data);
501 pr(wrbuf_cstr(res), client_data);
502 wrbuf_destroy(t_var);
507 pr("\n}\n", client_data);
509 for (e = s->conf; e; e = e->next)
511 if (!strcmp(e->pattern, "modifier"))
513 pr(e->value, client_data);
514 pr("\n", client_data);
517 return errors ? -1 : r;
523 * c-file-style: "Stroustrup"
524 * indent-tabs-mode: nil
526 * vim: shiftwidth=4 tabstop=8 expandtab