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, "\"");
191 term->u.general->buf, term->u.general->len);
194 wrbuf_printf(addinfo, ODR_INT_PRINTF, *term->u.numeric);
196 case Z_Term_characterString:
197 wrbuf_puts(addinfo, term->u.characterString);
202 wrbuf_printf(addinfo, "?v%d", *var_no);
205 wrbuf_putc(addinfo, '%');
210 wrbuf_putc(addinfo, *cp);
212 wrbuf_puts(res, wrbuf_cstr(addinfo));
218 static int rpn_structure(yaz_sparql_t s, WRBUF addinfo,
219 WRBUF res, WRBUF vars, Z_RPNStructure *q, int indent,
223 if (q->which == Z_RPNStructure_complex)
226 Z_Complex *c = q->u.complex;
227 Z_Operator *op = c->roperator;
228 if (op->which == Z_Operator_and)
230 r = rpn_structure(s, addinfo, res, vars, c->s1, indent, var_no);
233 wrbuf_puts(res, " .\n");
234 return rpn_structure(s, addinfo, res, vars, c->s2, indent, var_no);
236 else if (op->which == Z_Operator_or)
238 for (i = 0; i < indent; i++)
239 wrbuf_puts(res, " ");
240 wrbuf_puts(res, " {\n");
241 r = rpn_structure(s, addinfo, res, vars, c->s1, indent + 1, var_no);
244 wrbuf_puts(res, "\n");
245 for (i = 0; i < indent; i++)
246 wrbuf_puts(res, " ");
247 wrbuf_puts(res, " } UNION {\n");
248 r = rpn_structure(s, addinfo, res, vars, c->s2, indent + 1, var_no);
249 wrbuf_puts(res, "\n");
250 for (i = 0; i < indent; i++)
251 wrbuf_puts(res, " ");
252 wrbuf_puts(res, " }");
257 return YAZ_BIB1_OPERATOR_UNSUPP;
262 Z_Operand *op = q->u.simple;
263 if (op->which == Z_Operand_APT)
264 return apt(s, addinfo, res, vars, op->u.attributesPlusTerm, indent,
267 return YAZ_BIB1_RESULT_SET_UNSUPP_AS_A_SEARCH_TERM;
272 int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
274 void (*pr)(const char *buf,
279 struct sparql_entry *e;
280 yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
281 int r = 0, errors = 0;
283 for (e = s->conf; e; e = e->next)
285 if (!strcmp(e->pattern, "prefix"))
287 yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
290 pr("PREFIX", client_data);
294 int token = yaz_tok_move(p);
295 if (token != YAZ_TOK_STRING)
297 pr(" ", client_data);
299 tok_str = yaz_tok_parse_string(p);
302 if (no > 0 && tok_str[0] != '<')
303 pr("<", client_data);
304 pr(tok_str, client_data);
305 if (no > 0 && tok_str[strlen(tok_str)-1] != '>')
306 pr(">", client_data);
310 pr("\n", client_data);
311 yaz_tok_parse_destroy(p);
313 else if (!strcmp(e->pattern, "criteria"))
317 else if (!strcmp(e->pattern, "criteria.optional"))
321 else if (!strncmp(e->pattern, "index.", 6))
325 else if (!strcmp(e->pattern, "form"))
329 else if (!strcmp(e->pattern, "modifier"))
338 for (e = s->conf; e; e = e->next)
340 if (!strcmp(e->pattern, "form"))
342 pr(e->value, client_data);
343 pr("\n", client_data);
346 pr("WHERE {\n", client_data);
347 for (e = s->conf; e; e = e->next)
349 if (!strcmp(e->pattern, "criteria"))
351 pr(" ", client_data);
352 pr(e->value, client_data);
353 pr(" .\n", client_data);
358 WRBUF res = wrbuf_alloc();
359 WRBUF vars = wrbuf_alloc();
361 r = rpn_structure(s, addinfo, res, vars, q->RPNStructure, 0, &var_no);
364 WRBUF t_var = wrbuf_alloc();
365 for (e = s->conf; e; e = e->next)
367 if (!strcmp(e->pattern, "criteria.optional"))
370 size_t i = strlen(e->value), j;
372 while (i > 0 && strchr(" \t\r\n\f", e->value[i-1]))
375 while (i > 0 && !strchr("$?", e->value[i-1]))
380 wrbuf_write(t_var, e->value + i, j - i);
381 wrbuf_puts(t_var, " ");
382 if (strstr(wrbuf_cstr(vars), wrbuf_cstr(t_var)))
386 pr(" ", client_data);
388 pr("OPTIONAL { ", client_data);
389 pr(e->value, client_data);
391 pr(" }", client_data);
392 pr(" .\n", client_data);
395 pr(wrbuf_cstr(res), client_data);
396 wrbuf_destroy(t_var);
401 pr("\n}\n", client_data);
403 for (e = s->conf; e; e = e->next)
405 if (!strcmp(e->pattern, "modifier"))
407 pr(e->value, client_data);
408 pr("\n", client_data);
411 yaz_tok_cfg_destroy(cfg);
413 return errors ? -1 : r;
419 * c-file-style: "Stroustrup"
420 * indent-tabs-mode: nil
422 * vim: shiftwidth=4 tabstop=8 expandtab