+ memcpy (&sysno, rinfo+1, sizeof(sysno));
+ }
+ else
+ {
+ if (action == 2 || action == 3) /* fail if delete or update */
+ {
+ if (zebra_end_trans(zh) != ZEBRA_OK)
+ yaz_log(YLOG_WARN, "zebra_end_trans failed");
+ zebra_setError(zh, YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED,
+ "Cannot delete/update record: does not exist");
+ return ZEBRA_FAIL;
+ }
+ action = 1; /* make it an insert (if it's an update).. */
+ }
+ res = buffer_extract_record (zh, rec_buf, rec_len,
+ action == 3 ? 1 : 0 /* delete flag */,
+ 0, /* test mode */
+ 0, /* recordType */
+ &sysno,
+ 0, /* match */
+ 0, /* fname */
+ 0, /* force update */
+ 1 /* allow update */
+ );
+ if (res == ZEBRA_FAIL)
+ {
+ zebra_setError(zh, YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED,
+ "Unable to parse record");
+ }
+ if (action == 1)
+ {
+ dict_insert_ord(zh->reg->matchDict, db_ord, recid_z,
+ sizeof(sysno), &sysno);
+ }
+ else if (action == 3)
+ {
+ dict_delete_ord(zh->reg->matchDict, db_ord, recid_z);
+ }
+ if (zebra_end_trans(zh) != ZEBRA_OK)
+ {
+ yaz_log(YLOG_WARN, "zebra_end_trans failed");
+ res = ZEBRA_FAIL;
+ }
+ return res;
+}
+
+int delete_w_handle(const char *info, void *handle)
+{
+ ZebraHandle zh = (ZebraHandle) handle;
+ ISAM_P pos;
+ ASSERTZH;
+
+ if (*info == sizeof(pos))
+ {
+ memcpy (&pos, info+1, sizeof(pos));
+ isamb_unlink(zh->reg->isamb, pos);
+ }
+ return 0;
+}
+
+static int delete_SU_handle(void *handle, int ord)
+{
+ ZebraHandle zh = (ZebraHandle) handle;
+ char ord_buf[20];
+ int ord_len;
+
+ ord_len = key_SU_encode (ord, ord_buf);
+ ord_buf[ord_len] = '\0';
+
+ assert (zh->reg->isamb);
+ dict_delete_subtree(zh->reg->dict, ord_buf,
+ zh, delete_w_handle);
+ return 0;
+}
+
+ZEBRA_RES zebra_drop_database(ZebraHandle zh, const char *db)
+{
+ ZEBRA_RES ret = ZEBRA_OK;
+
+ yaz_log(log_level, "zebra_drop_database %s", db);
+ ZEBRA_CHECK_HANDLE(zh);
+
+ if (zebra_select_database (zh, db) == ZEBRA_FAIL)
+ return ZEBRA_FAIL;
+ if (zebra_begin_trans (zh, 1) == ZEBRA_FAIL)
+ return ZEBRA_FAIL;
+ if (zh->reg->isamb)
+ {
+ int db_ord;
+ zebraExplain_curDatabase (zh->reg->zei, db);
+ db_ord = zebraExplain_get_database_ord(zh->reg->zei);
+ dict_delete_subtree_ord(zh->reg->matchDict, db_ord,
+ 0 /* handle */, 0 /* func */);
+ zebraExplain_trav_ord(zh->reg->zei, zh, delete_SU_handle);
+ zebraExplain_removeDatabase(zh->reg->zei, zh);
+ }
+ else
+ {
+ yaz_log(YLOG_WARN, "drop database only supported for isam:b");
+ zebra_setError(zh, YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED,
+ "drop database only supported for isam:b");
+ ret = ZEBRA_FAIL;
+ }
+ if (zebra_end_trans (zh) != ZEBRA_OK)
+ {
+ yaz_log(YLOG_WARN, "zebra_end_trans failed");
+ ret = ZEBRA_FAIL;
+ }
+ return ret;
+}
+
+ZEBRA_RES zebra_create_database (ZebraHandle zh, const char *db)
+{
+ yaz_log(log_level, "zebra_create_database %s", db);
+ ZEBRA_CHECK_HANDLE(zh);
+ assert(db);
+
+ if (zebra_select_database (zh, db) == ZEBRA_FAIL)
+ return ZEBRA_FAIL;
+ if (zebra_begin_trans (zh, 1))
+ return ZEBRA_FAIL;
+
+ /* announce database */
+ if (zebraExplain_newDatabase (zh->reg->zei, db, 0
+ /* explainDatabase */))
+ {
+ if (zebra_end_trans (zh) != ZEBRA_OK)
+ {
+ yaz_log(YLOG_WARN, "zebra_end_trans failed");
+ }
+ zebra_setError(zh, YAZ_BIB1_ES_IMMEDIATE_EXECUTION_FAILED, db);
+ return ZEBRA_FAIL;
+ }
+ return zebra_end_trans (zh);
+}
+
+int zebra_string_norm (ZebraHandle zh, unsigned reg_id,
+ const char *input_str, int input_len,
+ char *output_str, int output_len)
+{
+ WRBUF wrbuf;
+ ASSERTZH;
+ assert(input_str);
+ assert(output_str);
+ yaz_log(log_level, "zebra_string_norm ");
+
+ if (!zh->reg->zebra_maps)
+ return -1;
+ wrbuf = zebra_replace(zh->reg->zebra_maps, reg_id, "",
+ input_str, input_len);
+ if (!wrbuf)