+ int ret = 0;
+ ZOOM_package *p = 0;
+ struct zoom_db *db;
+ int i, number;
+ WRBUF ext_type_str = next_token_new_wrbuf(args);
+
+ if (!ext_type_str)
+ {
+ printf("es: missing type "
+ "(itemorder, create, drop, commit, update, xmlupdate)\n");
+ return 1;
+ }
+ for (number = 0, db = sh->list; db; db = db->next)
+ if (db->con)
+ number++;
+
+ p = xmalloc(sizeof(*p) * number);
+
+ for (i = 0, db = sh->list; db; db = db->next)
+ if (db->con)
+ {
+ p[i] = ZOOM_connection_package(db->con, 0);
+ ZOOM_package_send(p[i], ext_type_str ? wrbuf_cstr(ext_type_str):0);
+ i++;
+ }
+
+ process_events(sh);
+
+ for (i = 0, db = sh->list; db; db = db->next)
+ {
+ int error;
+ const char *errmsg, *addinfo, *dset;
+ /* display errors if any */
+ if (!db->con)
+ continue;
+ if ((error = ZOOM_connection_error_x(db->con, &errmsg, &addinfo,
+ &dset)))
+ {
+ printf("%s error: %s (%s:%d) %s\n",
+ ZOOM_connection_option_get(db->con, "host"), errmsg,
+ dset, error, addinfo);
+ ret = 1;
+ }
+ else if (p[i])
+ {
+ const char *v;
+ printf("ok\n");
+ v = ZOOM_package_option_get(p[i], "targetReference");
+ if (v)
+ printf("targetReference: %s\n", v);
+ v = ZOOM_package_option_get(p[i], "xmlUpdateDoc");
+ if (v)
+ printf("xmlUpdateDoc: %s\n", v);
+ }
+ ZOOM_package_destroy(p[i]);
+ i++;
+ }
+ if (ext_type_str)
+ wrbuf_destroy(ext_type_str);
+ xfree(p);
+ return ret;
+}
+
+static int cmd_debug(struct zoom_sh *sh, const char **args)
+{
+ yaz_log_init_level(YLOG_ALL);
+ return 0;
+}
+
+static void display_search_result(struct zoom_db *db)
+{
+ const char *v;
+ int num;
+
+ v = ZOOM_resultset_option_get(db->res, "searchresult.size");
+ if (v && (num = atoi(v)))
+ {
+ int i;
+ printf("SearchResult-1:");
+ for (i = 0; i < num; i++)
+ {
+ const char *v;
+ char str[60];
+
+ if (i)
+ printf(",");
+
+ sprintf(str, "searchresult.%d.id", i);
+ v = ZOOM_resultset_option_get(db->res, str);
+ if (v)
+ printf(" id=%s", v);
+
+ sprintf(str, "searchresult.%d.subquery.term", i);
+ v = ZOOM_resultset_option_get(db->res, str);
+ if (v)
+ printf(" term=%s", v);
+
+ sprintf(str, "searchresult.%d.count", i);
+ v = ZOOM_resultset_option_get(db->res, str);
+ if (v)
+ printf(" cnt=%s", v);
+ }
+ printf("\n");
+ }
+}
+
+static int cmd_search(struct zoom_sh *sh, const char **args)
+{
+ ZOOM_query s;
+ const char *query_str = *args;
+ int ret = 0;
+ struct zoom_db *db;
+
+ s = ZOOM_query_create();
+ while (*query_str == ' ')
+ query_str++;
+ if (memcmp(query_str, "cql:", 4) == 0)
+ {
+ ZOOM_query_cql(s, query_str + 4);
+ }
+ else if (ZOOM_query_prefix(s, query_str))
+ {
+ printf("Bad PQF: %s\n", query_str);
+ ZOOM_query_destroy(s);
+ return 1;
+ }
+ if (sh->strategy && wrbuf_len(sh->strategy) && wrbuf_len(sh->criteria))
+ {
+ int r = ZOOM_query_sortby2(s, wrbuf_cstr(sh->strategy),
+ wrbuf_cstr(sh->criteria));
+ if (r)
+ {
+ if (r == -1)
+ printf("Bad sortby strategy: %s\n", wrbuf_cstr(sh->strategy));
+ else
+ printf("Bad sortby criteria: %s\n", wrbuf_cstr(sh->criteria));
+ ZOOM_query_destroy(s);
+ return 1;
+ }
+ printf("sortby added\n");
+ }
+ for (db = sh->list; db; db = db->next)
+ {
+ if (db->con)
+ {
+ ZOOM_resultset_destroy(db->res);
+ db->res = ZOOM_connection_search(db->con, s);
+ }
+ }
+ ZOOM_query_destroy(s);
+
+ process_events(sh);
+
+ for (db = sh->list; db; db = db->next)
+ {
+ int error;
+ const char *errmsg, *addinfo, *dset;
+ /* display errors if any */
+ if (!db->con)
+ continue;
+ if ((error = ZOOM_connection_error_x(db->con, &errmsg, &addinfo,
+ &dset)))
+ {
+ printf("%s error: %s (%s:%d) %s\n",
+ ZOOM_connection_option_get(db->con, "host"), errmsg,
+ dset, error, addinfo);
+ ret = 1;
+ }
+ else if (db->res)
+ {
+ /* OK, no major errors. Look at the result count */
+ int start = ZOOM_options_get_int(sh->options, "start", 0);
+ int count = ZOOM_options_get_int(sh->options, "count", 0);
+ int facet_num;
+
+ printf("%s: %lld hits\n", ZOOM_connection_option_get(db->con,
+ "host"),
+ (long long int) ZOOM_resultset_size(db->res));
+
+ facet_num = ZOOM_resultset_facets_size(db->res);
+ if (facet_num)
+ {
+ ZOOM_facet_field *facets = ZOOM_resultset_facets(db->res);
+ int facet_idx;
+ for (facet_idx = 0; facet_idx < facet_num; facet_idx++)
+ {
+ const char *name = ZOOM_facet_field_name(facets[facet_idx]);
+ size_t term_idx;
+ size_t term_num = ZOOM_facet_field_term_count(facets[facet_idx]);
+ printf("facet: %s\n", name);
+ for (term_idx = 0; term_idx < term_num; term_idx++ )
+ {
+ int freq;
+ const char *term =
+ ZOOM_facet_field_get_term(facets[facet_idx], term_idx, &freq);
+ printf("term: %s %d\n", term, freq);
+ }
+ }
+ }
+ display_search_result(db);
+ /* and display */
+ display_records(db->con, db->res, start, count, "render");
+ }
+ }
+ return ret;
+}
+
+static int cmd_scan(struct zoom_sh *sh, const char **args)
+{
+ const char *query_str = *args;
+ ZOOM_query query = ZOOM_query_create();
+ int i, number;
+ int ret = 0;
+ ZOOM_scanset *s = 0;
+ struct zoom_db *db;
+
+ while (*query_str == ' ')
+ query_str++;
+
+ if (memcmp(query_str, "cql:", 4) == 0)
+ {
+ ZOOM_query_cql(query, query_str + 4);
+ }
+ else if (ZOOM_query_prefix(query, query_str))
+ {
+ printf("Bad PQF: %s\n", query_str);
+ ZOOM_query_destroy(query);
+ return 1;
+ }
+
+ for (number = 0, db = sh->list; db; db = db->next)
+ if (db->con)
+ number++;
+
+ s = xmalloc(sizeof(*s) * number);
+
+ for (i = 0, db = sh->list; db; db = db->next)
+ if (db->con)
+ s[i++] = ZOOM_connection_scan1(db->con, query);
+
+ ZOOM_query_destroy(query);
+
+ process_events(sh);
+
+ for (i = 0, db = sh->list; db; db = db->next)
+ {
+ int error;
+ const char *errmsg, *addinfo, *dset;
+ /* display errors if any */
+ if (!db->con)
+ continue;
+ if ((error = ZOOM_connection_error_x(db->con, &errmsg, &addinfo,
+ &dset)))
+ {
+ printf("%s error: %s (%s:%d) %s\n",
+ ZOOM_connection_option_get(db->con, "host"), errmsg,
+ dset, error, addinfo);
+ ret = 1;
+ }
+ if (s[i])
+ {
+ size_t p, sz = ZOOM_scanset_size(s[i]);
+ for (p = 0; p < sz; p++)
+ {
+ size_t occ = 0;
+ size_t len = 0;
+ const char *term = ZOOM_scanset_display_term(s[i], p,
+ &occ, &len);
+ printf("%.*s %lld\n", (int) len, term, (long long int) occ);
+ }
+ ZOOM_scanset_destroy(s[i]);
+ }
+ i++;
+ }
+ xfree(s);
+ return ret;
+}
+
+static int cmd_sortby(struct zoom_sh *sh, const char **args)
+{
+ WRBUF strategy;
+ const char *criteria;
+ if (!(strategy = next_token_new_wrbuf(args)))
+ {
+ printf("missing argument argument: strategy and criteria\n");
+ return 1;
+ }
+ criteria = *args;
+ while (*criteria == ' ')
+ criteria++;
+ wrbuf_destroy(sh->strategy);
+ sh->strategy = strategy;
+
+ wrbuf_rewind(sh->criteria);
+ wrbuf_puts(sh->criteria, criteria);
+ return 0;
+}
+
+static int cmd_sort(struct zoom_sh *sh, const char **args)
+{
+ const char *sort_spec = *args;
+ int ret = 0;
+ struct zoom_db *db;
+
+ while (*sort_spec == ' ')
+ sort_spec++;
+
+ for (db = sh->list; db; db = db->next)
+ if (db->res)
+ ZOOM_resultset_sort(db->res, "yaz", sort_spec);
+ process_events(sh);
+ return ret;
+}
+
+static int cmd_help(struct zoom_sh *sh, const char **args)
+{
+ printf("connect <zurl>\n");
+ printf("search <pqf>\n");
+ printf("sortby <strategy> <criteria>\n");
+ printf("show [<start> [<count> [<type]]]\n");
+ printf("facets\n");
+ printf("scan <term>\n");
+ printf("quit\n");
+ printf("close <zurl>\n");
+ printf("ext <type>\n");
+ printf("set <option> [<value>]\n");
+ printf("get <option>\n");
+ printf("shell cmdline\n");
+ printf("\n");
+ printf("options:\n");
+ printf(" start\n");
+ printf(" count\n");
+ printf(" databaseName\n");
+ printf(" preferredRecordSyntax\n");
+ printf(" proxy\n");
+ printf(" elementSetName\n");
+ printf(" maximumRecordSize\n");
+ printf(" preferredRecordSize\n");
+ printf(" async\n");
+ printf(" piggyback\n");
+ printf(" group\n");
+ printf(" user\n");
+ printf(" password\n");
+ printf(" implementationName\n");
+ printf(" charset\n");
+ printf(" lang\n");
+ printf(" timeout\n");
+ printf(" facets\n");
+ printf(" extraArgs\n");
+ printf(" suggestions\n");
+ return 0;
+}
+
+static int cmd_connect(struct zoom_sh *sh, const char **args)
+{
+ int ret = 0;