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, ">");
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_puts(addinfo, term->u.characterString);
184 wrbuf_printf(addinfo, "?v%d", *var_no);
187 wrbuf_putc(addinfo, '%');
192 wrbuf_putc(addinfo, *cp);
194 wrbuf_puts(res, wrbuf_cstr(addinfo));
198 static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
199 Z_AttributesPlusTerm *q, int indent, int *var_no)
201 Odr_int v = lookup_attr_numeric(q->attributes, 1);
202 struct sparql_entry *e = 0;
203 const char *use_var = 0;
206 wrbuf_puts(res, " ");
207 for (i = 0; i < indent; i++)
208 wrbuf_puts(res, " ");
211 for (e = s->conf; e; e = e->next)
213 if (!strncmp(e->pattern, "index.", 6))
216 Odr_int w = odr_strtol(e->pattern + 6, &end, 10);
218 if (end && *end == '\0' && v == w)
224 wrbuf_printf(addinfo, ODR_INT_PRINTF, v);
225 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
230 const char *index_name = lookup_attr_string(q->attributes, 1);
233 for (e = s->conf; e; e = e->next)
235 if (!strncmp(e->pattern, "index.", 6))
237 if (!strcmp(e->pattern + 6, index_name))
243 wrbuf_puts(addinfo, index_name);
244 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
248 wrbuf_rewind(addinfo);
250 z_term(s, addinfo, res, vars, e, use_var, q->term, indent, var_no);
256 static int rpn_structure(yaz_sparql_t s, WRBUF addinfo,
257 WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent,
261 if (q->which == Z_RPNStructure_complex)
264 Z_Complex *c = q->u.complex;
265 Z_Operator *op = c->roperator;
266 if (op->which == Z_Operator_and)
268 r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no);
271 wrbuf_puts(res, " .\n");
272 return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no);
274 else if (op->which == Z_Operator_or)
276 for (i = 0; i < indent; i++)
277 wrbuf_puts(res, " ");
278 wrbuf_puts(res, " {\n");
279 r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no);
282 wrbuf_puts(res, "\n");
283 for (i = 0; i < indent; i++)
284 wrbuf_puts(res, " ");
285 wrbuf_puts(res, " } UNION {\n");
286 r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no);
287 wrbuf_puts(res, "\n");
288 for (i = 0; i < indent; i++)
289 wrbuf_puts(res, " ");
290 wrbuf_puts(res, " }");
295 return YAZ_BIB1_OPERATOR_UNSUPP;
300 Z_Operand *op = q->u.simple;
301 if (op->which == Z_Operand_APT)
302 return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent,
305 return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
310 static int emit_prefixes(yaz_sparql_t s,
312 void (*pr)(const char *buf,
316 struct sparql_entry *e;
317 yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
319 for (e = s->conf; e; e = e->next)
321 if (!strcmp(e->pattern, "prefix"))
323 yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
326 pr("PREFIX", client_data);
330 int token = yaz_tok_move(p);
331 if (token != YAZ_TOK_STRING)
333 pr(" ", client_data);
335 tok_str = yaz_tok_parse_string(p);
338 if (no > 0 && tok_str[0] != '<')
339 pr("<", client_data);
340 pr(tok_str, client_data);
341 if (no > 0 && tok_str[strlen(tok_str)-1] != '>')
342 pr(">", client_data);
346 pr("\n", client_data);
347 yaz_tok_parse_destroy(p);
349 else if (!strcmp(e->pattern, "criteria"))
353 else if (!strcmp(e->pattern, "criteria.optional"))
357 else if (!strncmp(e->pattern, "index.", 6))
361 else if (!strcmp(e->pattern, "form"))
365 else if (!strcmp(e->pattern, "modifier"))
369 else if (!strncmp(e->pattern, "present", 7))
373 else if (!strncmp(e->pattern, "uri", 3))
382 yaz_tok_cfg_destroy(cfg);
386 struct sparql_entry *lookup_schema(yaz_sparql_t s, const char *schema)
388 struct sparql_entry *e;
390 for (e = s->conf; e; e = e->next)
392 if (!strncmp(e->pattern, "present.", 8))
394 if (!schema || !strcmp(e->pattern + 8, schema))
397 if (!strncmp(e->pattern, "uri.", 4))
399 if (!schema || !strcmp(e->pattern + 4, schema))
406 int yaz_sparql_lookup_schema(yaz_sparql_t s, const char *schema)
408 return lookup_schema(s, schema) ? 1 : 0;
411 int yaz_sparql_from_uri_stream(yaz_sparql_t s,
413 void (*pr)(const char *buf, void *client_data),
415 const char *uri, const char *schema)
417 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
418 struct sparql_entry *e = lookup_schema(s, schema);
423 WRBUF res = wrbuf_alloc();
424 WRBUF vars = wrbuf_alloc();
428 term.which = Z_Term_characterString;
429 term.u.characterString = (char *) uri;
430 r = z_term(s, addinfo, res, vars, e, 0, &term, 0, &var_no);
433 pr(wrbuf_cstr(res), client_data);
434 pr("\n", client_data);
439 return errors ? -1 : r;
442 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
444 void (*pr)(const char *buf,
449 int r = 0, errors = emit_prefixes(s, addinfo, pr, client_data);
450 struct sparql_entry *e;
452 for (e = s->conf; e; e = e->next)
454 if (!strcmp(e->pattern, "form"))
456 pr(e->value, client_data);
457 pr("\n", client_data);
460 pr("WHERE {\n", client_data);
461 for (e = s->conf; e; e = e->next)
463 if (!strcmp(e->pattern, "criteria"))
465 pr(" ", client_data);
466 pr(e->value, client_data);
467 pr(" .\n", client_data);
472 WRBUF res = wrbuf_alloc();
473 WRBUF vars = wrbuf_alloc();
475 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
478 WRBUF t_var = wrbuf_alloc();
479 for (e = s->conf; e; e = e->next)
481 if (!strcmp(e->pattern, "criteria.optional"))
484 size_t i = strlen(e->value), j;
486 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
489 while (i > 0 && !strchr("$?", e->value[i-1]))
494 wrbuf_write(t_var, e->value + i, j - i);
495 wrbuf_puts(t_var, " ");
496 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
500 pr(" ", client_data);
502 pr("OPTIONAL { ", client_data);
503 pr(e->value, client_data);
505 pr(" }", client_data);
506 pr(" .\n", client_data);
509 pr(wrbuf_cstr(res), client_data);
510 wrbuf_destroy(t_var);
515 pr("\n}\n", client_data);
517 for (e = s->conf; e; e = e->next)
519 if (!strcmp(e->pattern, "modifier"))
521 pr(e->value, client_data);
522 pr("\n", client_data);
525 return errors ? -1 : r;
531 * c-file-style: "Stroustrup"
532 * indent-tabs-mode: nil
534 * vim: shiftwidth=4 tabstop=8 expandtab