Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/pazpar2
[pazpar2-moved-to-github.git] / src / client.c
index d205bef..8890060 100644 (file)
@@ -108,6 +108,7 @@ struct client {
     struct session *session;
     char *pquery; // Current search
     char *cqlquery; // used for SRU targets only
+    char *addinfo; // diagnostic info for most resent error
     Odr_int hits;
     int record_offset;
     int maxrecs;
@@ -555,12 +556,15 @@ void client_got_records(struct client *cl)
     struct session *se = cl->session;
     if (se)
     {
-        client_unlock(cl);
-        session_alert_watch(se, SESSION_WATCH_SHOW);
-        session_alert_watch(se, SESSION_WATCH_BYTARGET);
-        session_alert_watch(se, SESSION_WATCH_TERMLIST);
-        session_alert_watch(se, SESSION_WATCH_RECORD);
-        client_lock(cl);
+        if (reclist_get_num_records(se->reclist) > 0)
+        {
+            client_unlock(cl);
+            session_alert_watch(se, SESSION_WATCH_SHOW);
+            session_alert_watch(se, SESSION_WATCH_BYTARGET);
+            session_alert_watch(se, SESSION_WATCH_TERMLIST);
+            session_alert_watch(se, SESSION_WATCH_RECORD);
+            client_lock(cl);
+        }
     }
 }
 
@@ -700,12 +704,37 @@ int client_has_facet(struct client *cl, const char *name)
     return 0;
 }
 
-void client_start_search(struct client *cl, const char *sort_strategy_and_spec,
-                         int increasing)
+static const char *get_strategy_plus_sort(struct client *l, const char *field)
+{
+    struct session_database *sdb = client_get_database(l);
+    struct setting *s;
+
+    const char *strategy_plus_sort = 0;
+    
+    for (s = sdb->settings[PZ_SORTMAP]; s; s = s->next)
+    {
+        char *p = strchr(s->name + 3, ':');
+        if (!p)
+        {
+            yaz_log(YLOG_WARN, "Malformed sortmap name: %s", s->name);
+            continue;
+        }
+        p++;
+        if (!strcmp(p, field))
+        {
+            strategy_plus_sort = s->value;
+            break;
+        }
+    }
+    return strategy_plus_sort;
+}
+
+void client_start_search(struct client *cl)
 {
     struct session_database *sdb = client_get_database(cl);
     struct connection *co = client_get_connection(cl);
     ZOOM_connection link = connection_get_link(co);
+    struct session *se = client_get_session(cl);
     ZOOM_resultset rs;
     const char *opt_piggyback   = session_setting_oneval(sdb, PZ_PIGGYBACK);
     const char *opt_queryenc    = session_setting_oneval(sdb, PZ_QUERYENCODING);
@@ -721,8 +750,6 @@ void client_start_search(struct client *cl, const char *sort_strategy_and_spec,
 
     assert(link);
 
-    cl->hits = 0;
-    cl->record_offset = 0;
     cl->diagnostic = 0;
 
     if (extra_args && *extra_args)
@@ -785,25 +812,43 @@ void client_start_search(struct client *cl, const char *sort_strategy_and_spec,
         
         ZOOM_query_prefix(q, cl->pquery);
     }
-    if (sort_strategy_and_spec &&
-        strlen(sort_strategy_and_spec) < 40 /* spec below */)
-    {
-        char spec[50], *p;
-        strcpy(spec, sort_strategy_and_spec);
-        p = strchr(spec, ':');
-        if (p)
+    if (se->sorted_results)
+    {   /* first entry is current sorting ! */
+        const char *sort_strategy_and_spec =
+            get_strategy_plus_sort(cl, se->sorted_results->field);
+        int increasing = se->sorted_results->increasing;
+        if (sort_strategy_and_spec && strlen(sort_strategy_and_spec) < 40)
         {
-            *p++ = '\0'; /* cut the string in two */
-            while (*p == ' ')
-                p++;
-            if (increasing)
-                strcat(p, " <");
-            else
-                strcat(p, " >");
-            yaz_log(YLOG_LOG, "applying %s %s", spec, p);
-            ZOOM_query_sortby2(q, spec, p);
+            char spec[50], *p;
+            strcpy(spec, sort_strategy_and_spec);
+            p = strchr(spec, ':');
+            if (p)
+            {
+                *p++ = '\0'; /* cut the string in two */
+                while (*p == ' ')
+                    p++;
+                if (increasing)
+                    strcat(p, " <");
+                else
+                    strcat(p, " >");
+                yaz_log(YLOG_LOG, "applying %s %s", spec, p);
+                ZOOM_query_sortby2(q, spec, p);
+            }
+        }
+        else
+        {
+            /* no native sorting.. If this is not the first search, then
+               skip it entirely */
+            if (se->sorted_results->next)
+            {
+                ZOOM_query_destroy(q);
+                client_set_state_nb(cl, Client_Idle);
+                return;
+            }
         }
     }
+    cl->hits = 0;
+    cl->record_offset = 0;
     rs = ZOOM_connection_search(link, q);
     ZOOM_query_destroy(q);
     ZOOM_resultset_destroy(cl->resultset);
@@ -818,6 +863,7 @@ struct client *client_create(const char *id)
     cl->startrecs = 0;
     cl->pquery = 0;
     cl->cqlquery = 0;
+    cl->addinfo = 0;
     cl->database = 0;
     cl->connection = 0;
     cl->session = 0;
@@ -869,6 +915,8 @@ int client_destroy(struct client *c)
             c->pquery = 0;
             xfree(c->cqlquery);
             c->cqlquery = 0;
+            xfree(c->addinfo);
+            c->addinfo = 0;
             xfree(c->id);
             assert(!c->connection);
             facet_limits_destroy(c->facet_limits);
@@ -1260,13 +1308,20 @@ int client_get_num_records(struct client *cl)
     return cl->record_offset;
 }
 
-void client_set_diagnostic(struct client *cl, int diagnostic)
+void client_set_diagnostic(struct client *cl, int diagnostic,
+                           const char *addinfo)
 {
     cl->diagnostic = diagnostic;
+    xfree(cl->addinfo);
+    cl->addinfo = 0;
+    if (addinfo)
+        cl->addinfo = xstrdup(addinfo);
 }
 
-int client_get_diagnostic(struct client *cl)
+int client_get_diagnostic(struct client *cl, const char **addinfo)
 {
+    if (addinfo)
+        *addinfo = cl->addinfo;
     return cl->diagnostic;
 }