11 #include <yaz/diagbib1.h>
15 #include "zebra_perl.h"
16 #include "zebra_api_ext.h"
18 #include <yaz/pquery.h>
20 #include <yaz/sortspec.h>
22 void data1_print_tree(data1_handle dh, data1_node *n, FILE *out) {
23 data1_pr_tree(dh, n, stdout);
26 int zebra_get_shadow_enable (ZebraHandle zh) {
27 return (zh->shadow_enable);
30 void zebra_set_shadow_enable (ZebraHandle zh, int value) {
31 zh->shadow_enable = value;
34 void init_recordGroup (recordGroup *rg) {
36 rg->databaseName = NULL;
39 rg->recordType = NULL;
40 rg->flagStoreData = -1;
41 rg->flagStoreKeys = -1;
43 rg->databaseNamePath = 0;
44 rg->explainDatabase = 0;
45 rg->fileVerboseLimit = 100000;
50 /* This is from extract.c... it seems useful, when extract_rec_in mem is
51 called... and in general... Should be moved to somewhere else */
52 void res_get_recordGroup (ZebraHandle zh,
58 if (!rGroup->groupName || !*rGroup->groupName)
61 sprintf (gprefix, "%s.", rGroup->groupName);
63 /* determine file type - depending on extension */
64 if (!rGroup->recordType) {
65 sprintf (ext_res, "%srecordType.%s", gprefix, ext);
66 if (!(rGroup->recordType = res_get (zh->res, ext_res))) {
67 sprintf (ext_res, "%srecordType", gprefix);
68 rGroup->recordType = res_get (zh->res, ext_res);
71 /* determine match criteria */
72 if (!rGroup->recordId) {
73 sprintf (ext_res, "%srecordId.%s", gprefix, ext);
74 if (!(rGroup->recordId = res_get (zh->res, ext_res))) {
75 sprintf (ext_res, "%srecordId", gprefix);
76 rGroup->recordId = res_get (zh->res, ext_res);
80 /* determine database name */
81 if (!rGroup->databaseName) {
82 sprintf (ext_res, "%sdatabase.%s", gprefix, ext);
83 if (!(rGroup->databaseName = res_get (zh->res, ext_res))) {
84 sprintf (ext_res, "%sdatabase", gprefix);
85 rGroup->databaseName = res_get (zh->res, ext_res);
88 if (!rGroup->databaseName)
89 rGroup->databaseName = "Default";
91 /* determine if explain database */
92 sprintf (ext_res, "%sexplainDatabase", gprefix);
93 rGroup->explainDatabase =
94 atoi (res_get_def (zh->res, ext_res, "0"));
97 if (rGroup->flagStoreData == -1) {
99 sprintf (ext_res, "%sstoreData.%s", gprefix, ext);
100 if (!(sval = res_get (zh->res, ext_res))) {
101 sprintf (ext_res, "%sstoreData", gprefix);
102 sval = res_get (zh->res, ext_res);
105 rGroup->flagStoreData = atoi (sval);
107 if (rGroup->flagStoreData == -1) rGroup->flagStoreData = 0;
110 if (rGroup->flagStoreKeys == -1) {
113 sprintf (ext_res, "%sstoreKeys.%s", gprefix, ext);
114 sval = res_get (zh->res, ext_res);
116 sprintf (ext_res, "%sstoreKeys", gprefix);
117 sval = res_get (zh->res, ext_res);
119 if (!sval) sval = res_get (zh->res, "storeKeys");
120 if (sval) rGroup->flagStoreKeys = atoi (sval);
122 if (rGroup->flagStoreKeys == -1) rGroup->flagStoreKeys = 0;
126 int zebra_trans_processed(ZebraTransactionStatus s) {
127 return (s.processed);
130 /* ---------------------------------------------------------------------------
131 Record insert(=update), delete
133 If sysno is provided, then it's used to identify the reocord.
134 If not, and match_criteria is provided, then sysno is guessed
135 If not, and a record is provided, then sysno is got from there
138 int zebra_update_record (ZebraHandle zh,
139 struct recordGroup *rGroup,
140 const char *recordType,
141 int sysno, const char *match, const char *fname,
142 const char *buf, int buf_size)
147 if (buf_size < 1) buf_size = strlen(buf);
149 zebra_begin_trans(zh);
150 res=bufferExtractRecord (zh, buf, buf_size, rGroup,
160 int zebra_delete_record (ZebraHandle zh,
161 struct recordGroup *rGroup,
162 const char *recordType,
163 int sysno, const char *match, const char *fname,
164 const char *buf, int buf_size)
168 if (buf_size < 1) buf_size = strlen(buf);
170 zebra_begin_trans(zh);
171 res=bufferExtractRecord (zh, buf, buf_size, rGroup,
181 /* ---------------------------------------------------------------------------
184 zebra_search_RPN is the same as zebra_search_rpn, except that read locking
185 is not mandatory. (it's repeatable now, also in zebraapi.c)
188 void zebra_search_RPN (ZebraHandle zh, ODR decode, ODR stream,
189 Z_RPNQuery *query, const char *setname, int *hits)
194 if (zebra_begin_read (zh))
196 resultSetAddRPN (zh, decode, stream, query,
197 zh->num_basenames, zh->basenames, setname);
204 int zebra_search_PQF (ZebraHandle zh,
205 ODR odr_input, ODR odr_output,
206 const char *pqf_query,
212 query = p_query_rpn (odr_input, PROTO_Z3950, pqf_query);
215 logf (LOG_WARN, "bad query %s\n", pqf_query);
216 odr_reset (odr_input);
219 zebra_search_RPN (zh, odr_input, odr_output, query, setname, &hits);
221 odr_reset (odr_input);
222 odr_reset (odr_output);
227 int zebra_cql2pqf (cql_transform_t ct,
228 const char *query, char *res, int len) {
231 const char *addinfo = "";
232 CQL_parser cp = cql_parser_create();
234 if (status = cql_parser_string(cp, query)) {
235 cql_parser_destroy(cp);
239 if (cql_transform_buf(ct, cql_parser_result(cp), res, len)) {
240 status = cql_transform_error(ct, &addinfo);
241 logf (LOG_WARN,"Transform error %d %s\n", status, addinfo ? addinfo : "");
242 cql_parser_destroy(cp);
246 cql_parser_destroy(cp);
250 void zebra_scan_PQF (ZebraHandle zh,
253 const char *pqf_query)
255 Z_AttributesPlusTerm *zapt;
258 oid_value attributeset;
259 ZebraScanEntry *entries;
263 "scan req: pos:%d, num:%d, partial:%d",
264 so->position, so->num_entries, so->is_partial);
266 zapt = p_query_scan (stream, PROTO_Z3950, &attrsetid, pqf_query);
268 oidname = yaz_z3950oid_to_str (attrsetid, &class);
269 logf (LOG_DEBUG, "Attributreset: %s", oidname);
270 attributeset = oid_getvalbyname(oidname);
273 logf (LOG_WARN, "bad query %s\n", pqf_query);
278 so->entries = (scanEntry *)
279 odr_malloc (stream, sizeof(so->entries) * (so->num_entries));
282 zebra_scan (zh, stream, zapt, attributeset,
283 &so->position, &so->num_entries,
284 (ZebraScanEntry **) &so->entries, &so->is_partial);
287 "scan res: pos:%d, num:%d, partial:%d",
288 so->position, so->num_entries, so->is_partial);
291 scanEntry *getScanEntry(ScanObj *so, int pos) {
292 return (&so->entries[pos-1]);
295 /* ---------------------------------------------------------------------------
297 2 phase retrieval - I didn't manage to return array of blessed references
298 to wrapped structures... it's feasible, but I'll need some time
302 void record_retrieve(RetrievalObj *ro,
304 RetrievalRecord *res,
310 RetrievalRecordBuf *buf =
311 (RetrievalRecordBuf *) odr_malloc(stream, sizeof(*buf));
313 res->errCode = ro->records[i].errCode;
314 if (ro->records[i].errString) {
315 res->errString = odr_strdup(stream, ro->records[i].errString);
319 res->position = ro->records[i].position;
320 res->base = ro->records[i].base;
321 res->format = (char *)
322 yaz_z3950_oid_value_to_str(ro->records[i].format, CLASS_RECSYN);
324 res->buf->len = ro->records[i].len;
325 res->buf->buf = ro->records[i].buf;
326 res->score = ro->records[i].score;
327 res->sysno = ro->records[i].sysno;
331 /* most of the code here was copied from yaz-client */
332 void records_retrieve(ZebraHandle zh,
336 const char *a_schema,
337 const char *a_format,
342 static enum oid_value recordsyntax = VAL_SUTRS;
343 static enum oid_value schema = VAL_NONE;
344 static Z_ElementSetNames *elementSetNames = 0;
345 static Z_RecordComposition compo;
346 static Z_ElementSetNames esn;
347 static char what[100];
353 if (from < 1) from = 1;
354 if (from > to) to = from;
355 res->noOfRecords = to - from + 1;
357 res->records = odr_malloc (stream,
358 sizeof(*res->records) * (res->noOfRecords));
360 for (i = 0; i<res->noOfRecords; i++) res->records[i].position = from+i;
362 if (!a_eset || !*a_eset) {
365 strcpy(what, a_eset);
366 esn.which = Z_ElementSetNames_generic;
367 esn.u.generic = what;
368 elementSetNames = &esn;
371 if (!a_schema || !*a_schema) {
374 schema = oid_getvalbyname (a_schema);
375 if (schema == VAL_NONE) {
376 logf(LOG_WARN,"unknown schema '%s'",a_schema);
381 if (!a_format || !*a_format) {
382 recordsyntax = VAL_SUTRS;
384 recordsyntax = oid_getvalbyname (a_format);
385 if (recordsyntax == VAL_NONE) {
386 logf(LOG_WARN,"unknown record syntax '%s', using SUTRS",a_schema);
387 recordsyntax = VAL_SUTRS;
391 if (schema != VAL_NONE) {
394 prefschema.proto = PROTO_Z3950;
395 prefschema.oclass = CLASS_SCHEMA;
396 prefschema.value = schema;
398 compo.which = Z_RecordComp_complex;
399 compo.u.complex = (Z_CompSpec *)
400 odr_malloc(stream, sizeof(*compo.u.complex));
401 compo.u.complex->selectAlternativeSyntax = (bool_t *)
402 odr_malloc(stream, sizeof(bool_t));
403 *compo.u.complex->selectAlternativeSyntax = 0;
405 compo.u.complex->generic = (Z_Specification *)
406 odr_malloc(stream, sizeof(*compo.u.complex->generic));
407 compo.u.complex->generic->which = Z_Schema_oid;
408 compo.u.complex->generic->schema.oid = (Odr_oid *)
409 odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
410 if (!compo.u.complex->generic->schema.oid)
412 /* OID wasn't a schema! Try record syntax instead. */
413 prefschema.oclass = CLASS_RECSYN;
414 compo.u.complex->generic->schema.oid = (Odr_oid *)
415 odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
417 if (!elementSetNames)
418 compo.u.complex->generic->elementSpec = 0;
421 compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
422 odr_malloc(stream, sizeof(Z_ElementSpec));
423 compo.u.complex->generic->elementSpec->which =
424 Z_ElementSpec_elementSetName;
425 compo.u.complex->generic->elementSpec->u.elementSetName =
426 elementSetNames->u.generic;
428 compo.u.complex->num_dbSpecific = 0;
429 compo.u.complex->dbSpecific = 0;
430 compo.u.complex->num_recordSyntax = 0;
431 compo.u.complex->recordSyntax = 0;
433 else if (elementSetNames) {
434 compo.which = Z_RecordComp_simple;
435 compo.u.simple = elementSetNames;
438 if (compo.which == -1) {
439 api_records_retrieve (zh, stream, setname,
442 res->noOfRecords, res->records);
444 api_records_retrieve (zh, stream, setname,
447 res->noOfRecords, res->records);
452 int zebra_trans_no (ZebraHandle zh) {
453 return (zh->trans_no);
456 /* almost the same as zebra_records_retrieve ... but how did it work?
457 I mean for multiple records ??? CHECK ??? */
458 void api_records_retrieve (ZebraHandle zh, ODR stream,
459 const char *setname, Z_RecordComposition *comp,
460 oid_value input_format, int num_recs,
461 ZebraRetrievalRecord *recs)
469 zh->errString = odr_strdup (stream, setname);
475 if (zebra_begin_read (zh))
478 pos_array = (int *) xmalloc (num_recs * sizeof(*pos_array));
479 for (i = 0; i<num_recs; i++)
480 pos_array[i] = recs[i].position;
481 poset = zebraPosSetCreate (zh, setname, num_recs, pos_array);
484 logf (LOG_DEBUG, "zebraPosSetCreate error");
486 zh->errString = nmem_strdup (stream->mem, setname);
490 for (i = 0; i<num_recs; i++)
495 recs[i].format = VAL_SUTRS;
496 recs[i].len = strlen(poset[i].term);
497 recs[i].buf = poset[i].term;
498 recs[i].base = poset[i].db;
502 else if (poset[i].sysno)
504 /* changed here ??? CHECK ??? */
507 zebra_record_fetch (zh, poset[i].sysno, poset[i].score,
508 stream, input_format, comp,
513 recs[i].buf = (char *) odr_malloc(stream,recs[i].len);
514 memcpy(recs[i].buf, b, recs[i].len);
515 recs[i].errString = 0; /* Hmmm !!! we should get this */
516 recs[i].sysno = poset[i].sysno;
517 recs[i].score = poset[i].score;
523 sprintf (num_str, "%d", pos_array[i]);
525 zh->errString = odr_strdup (stream, num_str);
530 zebraPosSetDestroy (zh, poset, num_recs);
537 /* ---------------------------------------------------------------------------
538 Sort - a simplified interface, with optional read locks.
540 int sort (ZebraHandle zh,
542 const char *sort_spec,
543 const char *output_setname,
544 const char **input_setnames
547 int num_input_setnames = 0;
549 Z_SortKeySpecList *sort_sequence = yaz_sort_spec (stream, sort_spec);
550 if (!sort_sequence) {
551 logf(LOG_WARN,"invalid sort specs '%s'", sort_spec);
556 /* we can do this, since the typemap code for char** will
557 put a NULL at the end of list */
558 while (input_setnames[num_input_setnames]) num_input_setnames++;
560 if (zebra_begin_read (zh))
563 resultSetSort (zh, stream->mem, num_input_setnames, input_setnames,
564 output_setname, sort_sequence, &sort_status);
567 return (sort_status);