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 static Odr_int lookup_attr_numeric(Z_AttributeList *attributes, int type)
64 for (j = 0; j < attributes->num_attributes; j++)
66 Z_AttributeElement *ae = attributes->attributes[j];
67 if (*ae->attributeType == type)
69 if (ae->which == Z_AttributeValue_numeric)
70 return *ae->value.numeric;
76 static const char *lookup_attr_string(Z_AttributeList *attributes, int type)
79 for (j = 0; j < attributes->num_attributes; j++)
81 Z_AttributeElement *ae = attributes->attributes[j];
82 if (*ae->attributeType == type)
84 if (ae->which == Z_AttributeValue_complex)
86 Z_ComplexAttribute *ca = ae->value.complex;
88 for (i = 0; i < ca->num_list; i++)
90 Z_StringOrNumeric *son = ca->list[i];
91 if (son->which == Z_StringOrNumeric_string)
100 static int apt(yaz_sparql_t s, WRBUF addinfo, WRBUF res, WRBUF vars,
101 Z_AttributesPlusTerm *q, int indent, int *var_no)
103 Z_Term *term = q->term;
104 Odr_int v = lookup_attr_numeric(q->attributes, 1);
105 struct sparql_entry *e = 0;
107 const char *use_var = 0;
110 wrbuf_puts(res, " ");
111 for (i = 0; i < indent; i++)
112 wrbuf_puts(res, " ");
115 for (e = s->conf; e; e = e->next)
117 if (!strncmp(e->pattern, "index.", 6))
120 Odr_int w = odr_strtol(e->pattern + 6, &end, 10);
122 if (end && *end == '\0' && v == w)
128 wrbuf_printf(addinfo, ODR_INT_PRINTF, v);
129 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
134 const char *index_name = lookup_attr_string(q->attributes, 1);
137 for (e = s->conf; e; e = e->next)
139 if (!strncmp(e->pattern, "index.", 6))
141 if (!strcmp(e->pattern + 6, index_name))
147 wrbuf_puts(addinfo, index_name);
148 return YAZ_BIB1_UNSUPP_USE_ATTRIBUTE;
152 wrbuf_rewind(addinfo);
154 for (cp = e->value; *cp; cp++)
156 if (strchr(" \t\r\n\f", *cp) && !use_var)
159 if (strchr("$?", e->value[0]))
161 wrbuf_write(vars, e->value + 1, cp - e->value - 1);
162 wrbuf_puts(vars, " ");
170 wrbuf_puts(addinfo, "\"");
174 wrbuf_json_write(addinfo,
175 term->u.general->buf, term->u.general->len);
178 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
180 case Z_Term_characterString:
181 wrbuf_json_puts(addinfo, term->u.characterString);
184 wrbuf_puts(addinfo, "\"");
187 wrbuf_puts(addinfo, "<");
191 wrbuf_json_write(addinfo,
192 term->u.general->buf, term->u.general->len);
195 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
197 case Z_Term_characterString:
198 wrbuf_json_puts(addinfo, term->u.characterString);
201 wrbuf_puts(addinfo, ">");
208 term->u.general->buf, term->u.general->len);
211 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
213 case Z_Term_characterString:
214 wrbuf_puts(addinfo, term->u.characterString);
219 wrbuf_printf(addinfo, "?v%d", *var_no);
222 wrbuf_putc(addinfo, '%');
227 wrbuf_putc(addinfo, *cp);
229 wrbuf_puts(res, wrbuf_cstr(addinfo));
235 static int rpn_structure(yaz_sparql_t s, WRBUF addinfo,
236 WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent,
240 if (q->which == Z_RPNStructure_complex)
243 Z_Complex *c = q->u.complex;
244 Z_Operator *op = c->roperator;
245 if (op->which == Z_Operator_and)
247 r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no);
250 wrbuf_puts(res, " .\n");
251 return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no);
253 else if (op->which == Z_Operator_or)
255 for (i = 0; i < indent; i++)
256 wrbuf_puts(res, " ");
257 wrbuf_puts(res, " {\n");
258 r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no);
261 wrbuf_puts(res, "\n");
262 for (i = 0; i < indent; i++)
263 wrbuf_puts(res, " ");
264 wrbuf_puts(res, " } UNION {\n");
265 r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no);
266 wrbuf_puts(res, "\n");
267 for (i = 0; i < indent; i++)
268 wrbuf_puts(res, " ");
269 wrbuf_puts(res, " }");
274 return YAZ_BIB1_OPERATOR_UNSUPP;
279 Z_Operand *op = q->u.simple;
280 if (op->which == Z_Operand_APT)
281 return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent,
284 return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
289 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
291 void (*pr)(const char *buf,
296 struct sparql_entry *e;
297 yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
298 int r = 0, errors = 0;
300 for (e = s->conf; e; e = e->next)
302 if (!strcmp(e->pattern, "prefix"))
304 yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
307 pr("PREFIX", client_data);
311 int token = yaz_tok_move(p);
312 if (token != YAZ_TOK_STRING)
314 pr(" ", client_data);
316 tok_str = yaz_tok_parse_string(p);
319 if (no > 0 && tok_str[0] != '<')
320 pr("<", client_data);
321 pr(tok_str, client_data);
322 if (no > 0 && tok_str[strlen(tok_str)-1] != '>')
323 pr(">", client_data);
327 pr("\n", client_data);
328 yaz_tok_parse_destroy(p);
330 else if (!strcmp(e->pattern, "criteria"))
334 else if (!strcmp(e->pattern, "criteria.optional"))
338 else if (!strncmp(e->pattern, "index.", 6))
342 else if (!strcmp(e->pattern, "form"))
346 else if (!strcmp(e->pattern, "modifier"))
355 for (e = s->conf; e; e = e->next)
357 if (!strcmp(e->pattern, "form"))
359 pr(e->value, client_data);
360 pr("\n", client_data);
363 pr("WHERE {\n", client_data);
364 for (e = s->conf; e; e = e->next)
366 if (!strcmp(e->pattern, "criteria"))
368 pr(" ", client_data);
369 pr(e->value, client_data);
370 pr(" .\n", client_data);
375 WRBUF res = wrbuf_alloc();
376 WRBUF vars = wrbuf_alloc();
378 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
381 WRBUF t_var = wrbuf_alloc();
382 for (e = s->conf; e; e = e->next)
384 if (!strcmp(e->pattern, "criteria.optional"))
387 size_t i = strlen(e->value), j;
389 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
392 while (i > 0 && !strchr("$?", e->value[i-1]))
397 wrbuf_write(t_var, e->value + i, j - i);
398 wrbuf_puts(t_var, " ");
399 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
403 pr(" ", client_data);
405 pr("OPTIONAL { ", client_data);
406 pr(e->value, client_data);
408 pr(" }", client_data);
409 pr(" .\n", client_data);
412 pr(wrbuf_cstr(res), client_data);
413 wrbuf_destroy(t_var);
418 pr("\n}\n", client_data);
420 for (e = s->conf; e; e = e->next)
422 if (!strcmp(e->pattern, "modifier"))
424 pr(e->value, client_data);
425 pr("\n", client_data);
428 yaz_tok_cfg_destroy(cfg);
430 return errors ? -1 : r;
436 * c-file-style: "Stroustrup"
437 * indent-tabs-mode: nil
439 * vim: shiftwidth=4 tabstop=8 expandtab