11 #include <yaz/diagbib1.h>
15 #include "zebra_perl.h"
16 #include "zebra_api_ext.h"
18 #include <yaz/pquery.h>
19 #include <yaz/sortspec.h>
21 void data1_print_tree(data1_handle dh, data1_node *n, FILE *out) {
22 data1_pr_tree(dh, n, stdout);
25 int zebra_get_shadow_enable (ZebraHandle zh) {
26 return (zh->shadow_enable);
29 void zebra_set_shadow_enable (ZebraHandle zh, int value) {
30 zh->shadow_enable = value;
33 void init_recordGroup (recordGroup *rg) {
35 rg->databaseName = NULL;
38 rg->recordType = NULL;
39 rg->flagStoreData = -1;
40 rg->flagStoreKeys = -1;
42 rg->databaseNamePath = 0;
43 rg->explainDatabase = 0;
44 rg->fileVerboseLimit = 100000;
49 /* This is from extract.c... it seems useful, when extract_rec_in mem is
50 called... and in general... Should be moved to somewhere else */
51 void res_get_recordGroup (ZebraHandle zh,
57 if (!rGroup->groupName || !*rGroup->groupName)
60 sprintf (gprefix, "%s.", rGroup->groupName);
62 /* determine file type - depending on extension */
63 if (!rGroup->recordType) {
64 sprintf (ext_res, "%srecordType.%s", gprefix, ext);
65 if (!(rGroup->recordType = res_get (zh->res, ext_res))) {
66 sprintf (ext_res, "%srecordType", gprefix);
67 rGroup->recordType = res_get (zh->res, ext_res);
70 /* determine match criteria */
71 if (!rGroup->recordId) {
72 sprintf (ext_res, "%srecordId.%s", gprefix, ext);
73 if (!(rGroup->recordId = res_get (zh->res, ext_res))) {
74 sprintf (ext_res, "%srecordId", gprefix);
75 rGroup->recordId = res_get (zh->res, ext_res);
79 /* determine database name */
80 if (!rGroup->databaseName) {
81 sprintf (ext_res, "%sdatabase.%s", gprefix, ext);
82 if (!(rGroup->databaseName = res_get (zh->res, ext_res))) {
83 sprintf (ext_res, "%sdatabase", gprefix);
84 rGroup->databaseName = res_get (zh->res, ext_res);
87 if (!rGroup->databaseName)
88 rGroup->databaseName = "Default";
90 /* determine if explain database */
91 sprintf (ext_res, "%sexplainDatabase", gprefix);
92 rGroup->explainDatabase =
93 atoi (res_get_def (zh->res, ext_res, "0"));
96 if (rGroup->flagStoreData == -1) {
98 sprintf (ext_res, "%sstoreData.%s", gprefix, ext);
99 if (!(sval = res_get (zh->res, ext_res))) {
100 sprintf (ext_res, "%sstoreData", gprefix);
101 sval = res_get (zh->res, ext_res);
104 rGroup->flagStoreData = atoi (sval);
106 if (rGroup->flagStoreData == -1) rGroup->flagStoreData = 0;
109 if (rGroup->flagStoreKeys == -1) {
112 sprintf (ext_res, "%sstoreKeys.%s", gprefix, ext);
113 sval = res_get (zh->res, ext_res);
115 sprintf (ext_res, "%sstoreKeys", gprefix);
116 sval = res_get (zh->res, ext_res);
118 if (!sval) sval = res_get (zh->res, "storeKeys");
119 if (sval) rGroup->flagStoreKeys = atoi (sval);
121 if (rGroup->flagStoreKeys == -1) rGroup->flagStoreKeys = 0;
125 /* ---------------------------------------------------------------------------
126 Record insert(=update), delete
128 If sysno is provided, then it's used to identify the reocord.
129 If not, and match_criteria is provided, then sysno is guessed
130 If not, and a record is provided, then sysno is got from there
134 int zebra_update_record (ZebraHandle zh,
135 struct recordGroup *rGroup,
136 int sysno, const char *match, const char *fname,
137 const char *buf, int buf_size)
142 if (buf_size < 1) buf_size = strlen(buf);
144 res=bufferExtractRecord (zh, buf, buf_size, rGroup,
153 int zebra_delete_record (ZebraHandle zh,
154 struct recordGroup *rGroup,
155 int sysno, const char *match, const char *fname,
156 const char *buf, int buf_size)
160 if (buf_size < 1) buf_size = strlen(buf);
162 res=bufferExtractRecord (zh, buf, buf_size, rGroup,
170 /* ---------------------------------------------------------------------------
173 zebra_search_RPN is the same as zebra_search_rpn, except that read locking
174 is not mandatory. (it's repeatable now, also in zebraapi.c)
177 void zebra_search_RPN (ZebraHandle zh, ODR decode, ODR stream,
178 Z_RPNQuery *query, const char *setname, int *hits)
183 if (zebra_begin_read (zh))
185 resultSetAddRPN (zh, decode, stream, query,
186 zh->num_basenames, zh->basenames, setname);
193 int zebra_search_PQF (ZebraHandle zh,
194 ODR odr_input, ODR odr_output,
195 const char *pqf_query,
201 query = p_query_rpn (odr_input, PROTO_Z3950, pqf_query);
204 logf (LOG_WARN, "bad query %s\n", pqf_query);
205 odr_reset (odr_input);
208 zebra_search_RPN (zh, odr_input, odr_output, query, setname, &hits);
210 odr_reset (odr_input);
211 odr_reset (odr_output);
216 void zebra_scan_PQF (ZebraHandle zh,
219 const char *pqf_query)
221 Z_AttributesPlusTerm *zapt;
224 oid_value attributeset;
225 ZebraScanEntry *entries;
229 "scan req: pos:%d, num:%d, partial:%d",
230 so->position, so->num_entries, so->is_partial);
232 zapt = p_query_scan (stream, PROTO_Z3950, &attrsetid, pqf_query);
234 oidname = yaz_z3950oid_to_str (attrsetid, &class);
235 logf (LOG_DEBUG, "Attributreset: %s", oidname);
236 attributeset = oid_getvalbyname(oidname);
239 logf (LOG_WARN, "bad query %s\n", pqf_query);
244 so->entries = (ScanEntry *)
245 odr_malloc (stream, sizeof(so->entries) * (so->num_entries));
248 zebra_scan (zh, stream, zapt, attributeset,
249 &so->position, &so->num_entries,
250 (ZebraScanEntry **) &so->entries, &so->is_partial);
253 "scan res: pos:%d, num:%d, partial:%d",
254 so->position, so->num_entries, so->is_partial);
257 ScanEntry *getScanEntry(ScanObj *so, int pos) {
258 return (&so->entries[pos-1]);
261 /* ---------------------------------------------------------------------------
263 2 phase retrieval - I didn't manage to return array of blessed references
264 to wrapped structures... it's feasible, but I'll need some time
268 void record_retrieve(RetrievalObj *ro,
270 RetrievalRecord *res,
276 RetrievalRecordBuf *buf =
277 (RetrievalRecordBuf *) odr_malloc(stream, sizeof(*buf));
279 res->errCode = ro->records[i].errCode;
280 res->errString = ro->records[i].errString;
281 res->position = ro->records[i].position;
282 res->base = ro->records[i].base;
283 res->format = ro->records[i].format;
285 res->buf->len = ro->records[i].len;
286 res->buf->buf = ro->records[i].buf;
290 /* most of the code here was copied from yaz-client */
291 void records_retrieve(ZebraHandle zh,
295 const char *a_schema,
296 const char *a_format,
301 static enum oid_value recordsyntax = VAL_SUTRS;
302 static enum oid_value schema = VAL_NONE;
303 static Z_ElementSetNames *elementSetNames = 0;
304 static Z_RecordComposition compo;
305 static Z_ElementSetNames esn;
306 static char what[100];
312 if (from < 1) from = 1;
313 if (from > to) to = from;
314 res->noOfRecords = to - from + 1;
316 res->records = odr_malloc (stream,
317 sizeof(*res->records) * (res->noOfRecords));
319 for (i = 0; i<res->noOfRecords; i++) res->records[i].position = from+i;
321 if (!a_eset || !*a_eset) {
324 strcpy(what, a_eset);
325 esn.which = Z_ElementSetNames_generic;
326 esn.u.generic = what;
327 elementSetNames = &esn;
330 if (!a_schema || !*a_schema) {
333 schema = oid_getvalbyname (a_schema);
334 if (schema == VAL_NONE) {
335 logf(LOG_WARN,"unknown schema '%s'",a_schema);
340 if (!a_format || !*a_format) {
341 recordsyntax = VAL_SUTRS;
343 recordsyntax = oid_getvalbyname (a_format);
344 if (recordsyntax == VAL_NONE) {
345 logf(LOG_WARN,"unknown record syntax '%s', using SUTRS",a_schema);
346 recordsyntax = VAL_SUTRS;
350 if (schema != VAL_NONE) {
353 prefschema.proto = PROTO_Z3950;
354 prefschema.oclass = CLASS_SCHEMA;
355 prefschema.value = schema;
357 compo.which = Z_RecordComp_complex;
358 compo.u.complex = (Z_CompSpec *)
359 odr_malloc(stream, sizeof(*compo.u.complex));
360 compo.u.complex->selectAlternativeSyntax = (bool_t *)
361 odr_malloc(stream, sizeof(bool_t));
362 *compo.u.complex->selectAlternativeSyntax = 0;
364 compo.u.complex->generic = (Z_Specification *)
365 odr_malloc(stream, sizeof(*compo.u.complex->generic));
366 compo.u.complex->generic->schema = (Odr_oid *)
367 odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
369 if (!compo.u.complex->generic->schema) {
370 /* OID wasn't a schema! Try record syntax instead. */
371 prefschema.oclass = CLASS_RECSYN;
372 compo.u.complex->generic->schema = (Odr_oid *)
373 odr_oiddup(stream, oid_ent_to_oid(&prefschema, oid));
376 if (!elementSetNames) {
377 compo.u.complex->generic->elementSpec = 0;
379 compo.u.complex->generic->elementSpec = (Z_ElementSpec *)
380 odr_malloc(stream, sizeof(Z_ElementSpec));
381 compo.u.complex->generic->elementSpec->which =
382 Z_ElementSpec_elementSetName;
383 compo.u.complex->generic->elementSpec->u.elementSetName =
384 elementSetNames->u.generic;
386 compo.u.complex->num_dbSpecific = 0;
387 compo.u.complex->dbSpecific = 0;
388 compo.u.complex->num_recordSyntax = 0;
389 compo.u.complex->recordSyntax = 0;
391 else if (elementSetNames) {
392 compo.which = Z_RecordComp_simple;
393 compo.u.simple = elementSetNames;
396 if (compo.which == -1) {
397 api_records_retrieve (zh, stream, setname,
400 res->noOfRecords, res->records);
402 api_records_retrieve (zh, stream, setname,
405 res->noOfRecords, res->records);
410 /* almost the same as zebra_records_retrieve ... but how did it work?
411 I mean for multiple records ??? CHECK ??? */
412 void api_records_retrieve (ZebraHandle zh, ODR stream,
413 const char *setname, Z_RecordComposition *comp,
414 oid_value input_format, int num_recs,
415 ZebraRetrievalRecord *recs)
423 zh->errString = odr_strdup (stream, setname);
429 if (zebra_begin_read (zh))
432 pos_array = (int *) xmalloc (num_recs * sizeof(*pos_array));
433 for (i = 0; i<num_recs; i++)
434 pos_array[i] = recs[i].position;
435 poset = zebraPosSetCreate (zh, setname, num_recs, pos_array);
438 logf (LOG_DEBUG, "zebraPosSetCreate error");
440 zh->errString = nmem_strdup (stream->mem, setname);
444 for (i = 0; i<num_recs; i++)
449 recs[i].format = VAL_SUTRS;
450 recs[i].len = strlen(poset[i].term);
451 recs[i].buf = poset[i].term;
452 recs[i].base = poset[i].db;
455 else if (poset[i].sysno)
457 /* changed here ??? CHECK ??? */
460 zebra_record_fetch (zh, poset[i].sysno, poset[i].score,
461 stream, input_format, comp,
466 recs[i].buf = (char *) odr_malloc(stream,recs[i].len);
467 memcpy(recs[i].buf, b, recs[i].len);
468 recs[i].errString = NULL;
474 sprintf (num_str, "%d", pos_array[i]);
476 zh->errString = odr_strdup (stream, num_str);
481 zebraPosSetDestroy (zh, poset, num_recs);
488 /* ---------------------------------------------------------------------------
489 Sort - a simplified interface, with optional read locks.
491 int sort (ZebraHandle zh,
493 const char *sort_spec,
494 const char *output_setname,
495 const char **input_setnames
498 int num_input_setnames = 0;
500 Z_SortKeySpecList *sort_sequence = yaz_sort_spec (stream, sort_spec);
502 /* we can do this, since the typemap code for char** will
503 put a NULL at the end of list */
504 while (input_setnames[num_input_setnames]) num_input_setnames++;
506 if (zebra_begin_read (zh))
509 resultSetSort (zh, stream->mem, num_input_setnames, input_setnames,
510 output_setname, sort_sequence, &sort_status);
513 return (sort_status);