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 struct sparql_entry *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 (!strncmp(e->pattern, "uri.", 4))
383 if (!schema || !strcmp(e->pattern + 4, schema))
390 int yaz_sparql_lookup_schema(yaz_sparql_t s, const char *schema)
392 return lookup_schema(s, schema) ? 1 : 0;
395 int yaz_sparql_from_uri_stream(yaz_sparql_t s,
397 void (*pr)(const char *buf, void *client_data),
399 const char *uri, const char *schema)
401 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
402 struct sparql_entry *e = lookup_schema(s, schema);
407 WRBUF res = wrbuf_alloc();
408 WRBUF vars = wrbuf_alloc();
412 term.which = Z_Term_characterString;
413 term.u.characterString = (char *) uri;
414 r = z_term(s, addinfo, res, vars, e, 0, &term, 0, &var_no);
417 pr(wrbuf_cstr(res), client_data);
418 pr("\n", client_data);
423 return errors ? -1 : r;
426 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
428 void (*pr)(const char *buf,
433 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
434 struct sparql_entry *e;
436 for (e = s->conf; e; e = e->next)
438 if (!strcmp(e->pattern, "form"))
440 pr(e->value, client_data);
441 pr("\n", client_data);
444 pr("WHERE {\n", client_data);
445 for (e = s->conf; e; e = e->next)
447 if (!strcmp(e->pattern, "criteria"))
449 pr(" ", client_data);
450 pr(e->value, client_data);
451 pr(" .\n", client_data);
456 WRBUF res = wrbuf_alloc();
457 WRBUF vars = wrbuf_alloc();
459 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
462 WRBUF t_var = wrbuf_alloc();
463 for (e = s->conf; e; e = e->next)
465 if (!strcmp(e->pattern, "criteria.optional"))
468 size_t i = strlen(e->value), j;
470 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
473 while (i > 0 && !strchr("$?", e->value[i-1]))
478 wrbuf_write(t_var, e->value + i, j - i);
479 wrbuf_puts(t_var, " ");
480 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
484 pr(" ", client_data);
486 pr("OPTIONAL { ", client_data);
487 pr(e->value, client_data);
489 pr(" }", client_data);
490 pr(" .\n", client_data);
493 pr(wrbuf_cstr(res), client_data);
494 wrbuf_destroy(t_var);
499 pr("\n}\n", client_data);
501 for (e = s->conf; e; e = e->next)
503 if (!strcmp(e->pattern, "modifier"))
505 pr(e->value, client_data);
506 pr("\n", client_data);
509 return errors ? -1 : r;
515 * c-file-style: "Stroustrup"
516 * indent-tabs-mode: nil
518 * vim: shiftwidth=4 tabstop=8 expandtab