Fixed addinfo passing. Index type 's' is sort for absent index rules.
[idzebra-moved-to-github.git] / index / retrieve.c
index aed2060..4ff8586 100644 (file)
@@ -194,7 +194,7 @@ static int parse_zebra_elem(const char *elem,
 }
 
 
-int zebra_special_sort_fetch(
+static int sort_fetch(
     struct special_fetch_s *fi, const char *elemsetname,
     const Odr_oid *input_format,
     const Odr_oid **output_format,
@@ -717,6 +717,212 @@ static struct term_collect *term_collect_create(zebra_strmap_t sm,
     return col;
 }
 
+static int perform_facet_sort(ZebraHandle zh, int no_ord, int *ord_array,
+                              zebra_strmap_t *map_array,
+                              int num_recs, ZebraMetaRecord *poset)
+{
+    int rec_i;
+    WRBUF w = wrbuf_alloc();
+    int ord_i;
+
+    for (ord_i = 0; ord_i < no_ord; ord_i++)
+    {
+        for (rec_i = 0; rec_i < num_recs; rec_i++)
+        {
+            if (!poset[rec_i].sysno)
+                continue;
+            
+            zebra_sort_sysno(zh->reg->sort_index, poset[rec_i].sysno);
+            zebra_sort_type(zh->reg->sort_index, ord_array[ord_i]);
+            
+            wrbuf_rewind(w);
+            if (zebra_sort_read(zh->reg->sort_index, w))
+            {
+                zebra_strmap_t sm = map_array[ord_i];
+                int off = 0;
+                while (off != wrbuf_len(w))
+                {
+                    const char *str = wrbuf_buf(w) + off;
+                    int *freq = zebra_strmap_lookup(sm, str, 0, 0);
+                    if (freq)
+                        (*freq)++;
+                    else
+                    {
+                        int v = 1;
+                        zebra_strmap_add(sm, str, &v, sizeof v);
+                    }
+                    off += strlen(str)+1;
+                }
+            }
+        }
+    }
+    wrbuf_destroy(w);
+    return 0;
+}
+
+
+static int perform_facet_index(ZebraHandle zh,
+                               struct special_fetch_s *fi,
+                               int no_ord, int *ord_array,
+                               zebra_strmap_t *map_array,
+                               int num_recs, ZebraMetaRecord *poset,
+                               struct index_spec *spec_list)
+{
+    int max_chunks = 2;
+    int rec_i;
+    res_get_int(zh->res, "facetMaxChunks", &max_chunks);
+
+    for (rec_i = 0; rec_i < num_recs; rec_i++)
+    {
+        int ret;
+        int j;
+        zint sysnos[MAX_SYSNOS_PER_RECORD];
+        int no_sysnos = MAX_SYSNOS_PER_RECORD;
+        if (!poset[rec_i].sysno)
+            continue;
+        ret = zebra_result_recid_to_sysno(zh, fi->setname,
+                                          poset[rec_i].sysno,
+                                          sysnos, &no_sysnos);
+        assert(no_sysnos > 0);
+        yaz_log(YLOG_DEBUG, "Analyzing rec=%d ISAM sysno=" ZINT_FORMAT " chunks=%d",
+                rec_i, poset[rec_i].sysno, no_sysnos);
+        for (j = 0; j < no_sysnos && j < max_chunks; j++)
+        {
+            size_t slen;
+            const char *str;
+            struct it_key key_in;
+            Record rec = rec_get(zh->reg->records, sysnos[j]);
+            zebra_rec_keys_t keys = zebra_rec_keys_open();
+            zebra_rec_keys_set_buf(keys, rec->info[recInfo_delKeys],
+                                   rec->size[recInfo_delKeys], 0);
+            
+            yaz_log(YLOG_DEBUG, "rec %d " ZINT_FORMAT " %s", 
+                    j, sysnos[j], zebra_rec_keys_empty(keys) ? "empty" : "non-empty");
+            if (zebra_rec_keys_rewind(keys))
+            {
+                while (zebra_rec_keys_read(keys, &str, &slen, &key_in))
+                {
+                    int ord_i;
+                    struct index_spec *spec;
+                    for (spec = spec_list, ord_i = 0; ord_i < no_ord; 
+                         ord_i++, spec = spec->next)
+                    {
+                        int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
+                        if (ord == ord_array[ord_i] && 
+                            str[0] != FIRST_IN_FIELD_CHAR)
+                        {
+                            int *freq;
+                            zebra_strmap_t sm = map_array[ord_i];
+                            
+                            freq = zebra_strmap_lookup(sm, str, 0, 0);
+                            if (freq)
+                                (*freq)++;
+                            else
+                            {
+                                int v = 1;
+                                zebra_strmap_add(sm, str, &v, sizeof v);
+                            }
+                        }
+                    }
+                }
+            }
+            zebra_rec_keys_close(keys);
+            rec_free(&rec);
+        }
+    }
+    return 0;
+}
+
+static int perform_facet(ZebraHandle zh,  
+                         struct special_fetch_s *fi,
+                         WRBUF result,
+                         int num_recs, ZebraMetaRecord *poset,
+                         struct index_spec *spec_list,
+                         int no_ord, int *ord_array,
+                         int use_xml,
+                         zinfo_index_category_t cat)
+{
+    int i;
+    int ret = 0;
+    WRBUF wr = result;
+    struct index_spec *spec;
+    yaz_timing_t timing = yaz_timing_create();
+    zebra_strmap_t *map_array
+        = nmem_malloc(fi->nmem, sizeof *map_array * no_ord);
+    for (i = 0; i < no_ord; i++)
+        map_array[i] = zebra_strmap_create();
+
+    if (cat == zinfo_index_category_sort)
+        perform_facet_sort(zh, no_ord, ord_array, map_array,
+                           num_recs, poset);
+    else
+        perform_facet_index(zh, fi, no_ord, ord_array, map_array,
+                            num_recs, poset, spec_list);
+    yaz_timing_stop(timing);
+    yaz_log(YLOG_LOG, "facet first phase real=%4.2f cat=%s",
+            yaz_timing_get_real(timing),
+            (cat == zinfo_index_category_sort) ? "sort" : "index");
+    yaz_timing_start(timing);
+    for (spec = spec_list, i = 0; i < no_ord; i++, spec = spec->next)
+    {
+        int j;
+        NMEM nmem = nmem_create();
+        struct term_collect *col;
+        int no_collect_terms = 20;
+        
+        if (spec->extra)
+            no_collect_terms = atoi(spec->extra);
+        if (no_collect_terms < 1)
+            no_collect_terms = 1;
+        col = term_collect_create(map_array[i], no_collect_terms, nmem);
+        term_collect_freq(zh, col, no_collect_terms, ord_array[i],
+                          resultSetRef(zh, fi->setname));
+        
+        if (use_xml)
+            wrbuf_printf(wr, "  <facet type=\"%s\" index=\"%s\">\n",
+                         spec->index_type, spec->index_name);
+        else
+            wrbuf_printf(wr, "facet %s %s\n",
+                         spec->index_type, spec->index_name);
+        for (j = 0; j < no_collect_terms; j++)
+        {
+            if (col[j].term)
+            {
+                char dst_buf[IT_MAX_WORD];
+                zebra_term_untrans(zh, spec->index_type, dst_buf, col[j].term);
+                if (use_xml)
+                {
+                    wrbuf_printf(wr, "    <term coccur=\"%d\"", col[j].oc);
+                    if (col[j].set_occur)
+                        wrbuf_printf(wr, " occur=\"" ZINT_FORMAT "\"", 
+                                     col[j].set_occur);
+                    wrbuf_printf(wr, ">");
+                    wrbuf_xmlputs(wr, dst_buf);
+                    wrbuf_printf(wr, "</term>\n");
+                }
+                else
+                {
+                    wrbuf_printf(wr, "term %d", col[j].oc);
+                    if (col[j].set_occur)
+                        wrbuf_printf(wr, " " ZINT_FORMAT, 
+                                     col[j].set_occur);
+                    wrbuf_printf(wr, ": %s\n", dst_buf);
+                }
+            }
+        }
+        if (use_xml)
+            wrbuf_puts(wr, "  </facet>\n");
+        nmem_destroy(nmem);
+    }
+    for (i = 0; i < no_ord; i++)
+        zebra_strmap_destroy(map_array[i]);
+    yaz_timing_stop(timing);
+    yaz_log(YLOG_LOG, "facet second phase real=%4.2f",
+            yaz_timing_get_real(timing));
+    yaz_timing_destroy(&timing);
+    return ret;
+}
+
 static int facet_fetch(
     struct special_fetch_s *fi, const char *elemsetname,
     const Odr_oid *input_format,
@@ -726,19 +932,18 @@ static int facet_fetch(
     zint *pos_array;
     int i;
     int num_recs = 10; /* number of records to analyze */
-    int max_chunks = 2;
     ZebraMetaRecord *poset;
     ZEBRA_RES ret = ZEBRA_OK;
     int *ord_array;
-    WRBUF wr = result;
     int use_xml = 0;
     int no_ord = 0;
     struct index_spec *spec, *spec_list;
     int error;
     ZebraHandle zh = fi->zh;
+    /* whether sort or index based */
+    zinfo_index_category_t cat = zinfo_index_category_sort;
 
     res_get_int(zh->res, "facetNumRecs", &num_recs);
-    res_get_int(zh->res, "facetMaxChunks", &max_chunks);
 
     /* see if XML is required for response */
     if (oid_oidcmp(input_format, yaz_oid_recsyn_xml) == 0)
@@ -758,20 +963,38 @@ static int facet_fetch(
         no_ord++;
     }
 
+    /* try to see if all specs are sort based.. If not, try the
+       index based ones */
     ord_array = nmem_malloc(fi->nmem, sizeof(*ord_array) * no_ord);
 
     for (spec = spec_list, i = 0; spec; spec = spec->next, i++)
     {
         int ord = zebraExplain_lookup_attr_str(zh->reg->zei,
-                                               zinfo_index_category_index,
+                                               zinfo_index_category_sort,
                                                spec->index_type,
                                                spec->index_name);
         if (ord == -1)
+            break;
+        ord_array[i] = ord;
+    }
+    if (spec)
+    {
+        cat = zinfo_index_category_index;
+        for (spec = spec_list, i = 0; spec; spec = spec->next, i++)
         {
-            return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+            int ord = zebraExplain_lookup_attr_str(zh->reg->zei,
+                                                   zinfo_index_category_index,
+                                                   spec->index_type,
+                                                   spec->index_name);
+            if (ord == -1)
+                break;
+            ord_array[i] = ord;
+            
         }
-        ord_array[i] = ord;
     }
+    if (spec)
+        return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_;
+
     pos_array = (zint *) nmem_malloc(fi->nmem, num_recs * sizeof(*pos_array));
     for (i = 0; i < num_recs; i++)
        pos_array[i] = i+1;
@@ -783,134 +1006,15 @@ static int facet_fetch(
     }
     else
     {
-        yaz_timing_t timing = yaz_timing_create();
-        zebra_strmap_t *map_array
-            = nmem_malloc(fi->nmem, sizeof *map_array * no_ord);
-        for (i = 0; i < no_ord; i++)
-            map_array[i] = zebra_strmap_create();
-
-        for (i = 0; i < num_recs; i++)
-        {
-            int j;
-            zint sysnos[MAX_SYSNOS_PER_RECORD];
-            int no_sysnos = MAX_SYSNOS_PER_RECORD;
-            if (!poset[i].sysno)
-                continue;
-            ret = zebra_result_recid_to_sysno(zh, fi->setname,
-                                              poset[i].sysno,
-                                              sysnos, &no_sysnos);
-            assert(no_sysnos > 0);
-            yaz_log(YLOG_DEBUG, "Analyzing rec=%d ISAM sysno=" ZINT_FORMAT " chunks=%d",
-                    i, poset[i].sysno, no_sysnos);
-            for (j = 0; j < no_sysnos && j < max_chunks; j++)
-            {
-                size_t slen;
-                const char *str;
-                struct it_key key_in;
-                Record rec = rec_get(zh->reg->records, sysnos[j]);
-                zebra_rec_keys_t keys = zebra_rec_keys_open();
-                zebra_rec_keys_set_buf(keys, rec->info[recInfo_delKeys],
-                                       rec->size[recInfo_delKeys], 0);
-
-                yaz_log(YLOG_DEBUG, "rec %d " ZINT_FORMAT " %s", 
-                        j, sysnos[j], zebra_rec_keys_empty(keys) ? "empty" : "non-empty");
-                if (zebra_rec_keys_rewind(keys))
-                {
-                    while (zebra_rec_keys_read(keys, &str, &slen, &key_in))
-                    {
-                        int i;
-                        struct index_spec *spec;
-                        for (spec = spec_list, i = 0; i < no_ord; 
-                             i++, spec = spec->next)
-                        {
-                            int ord = CAST_ZINT_TO_INT(key_in.mem[0]);
-                            if (ord == ord_array[i] && 
-                                str[0] != FIRST_IN_FIELD_CHAR)
-                            {
-                                int *freq;
-                                zebra_strmap_t sm = map_array[i];
-                                
-                                freq = zebra_strmap_lookup(sm, str, 0, 0);
-                                if (freq)
-                                    (*freq)++;
-                                else
-                                {
-                                    int v = 1;
-                                    zebra_strmap_add(sm, str, &v, sizeof v);
-                                }
-                            }
-                        }
-                    }
-                }
-                zebra_rec_keys_close(keys);
-                rec_free(&rec);
-            }
-        }
-        yaz_timing_stop(timing);
-        yaz_log(YLOG_LOG, "facet first phase real=%4.2f",
-                yaz_timing_get_real(timing));
-        yaz_timing_start(timing);
         if (use_xml)
-            wrbuf_puts(wr, "<facets>\n");
-        for (spec = spec_list, i = 0; i < no_ord; i++, spec = spec->next)
         {
-            int j;
-            NMEM nmem = nmem_create();
-            struct term_collect *col;
-            int no_collect_terms = 20;
-
-            if (spec->extra)
-                no_collect_terms = atoi(spec->extra);
-            if (no_collect_terms < 1)
-                no_collect_terms = 1;
-            col = term_collect_create(map_array[i], no_collect_terms, nmem);
-            term_collect_freq(zh, col, no_collect_terms, ord_array[i],
-                              resultSetRef(zh, fi->setname));
-            
-            if (use_xml)
-                wrbuf_printf(wr, "  <facet type=\"%s\" index=\"%s\">\n",
-                             spec->index_type, spec->index_name);
-            else
-                wrbuf_printf(wr, "facet %s %s\n",
-                             spec->index_type, spec->index_name);
-            for (j = 0; j < no_collect_terms; j++)
-            {
-                if (col[j].term)
-                {
-                    char dst_buf[IT_MAX_WORD];
-                    zebra_term_untrans(zh, spec->index_type, dst_buf, col[j].term);
-                    if (use_xml)
-                    {
-                        wrbuf_printf(wr, "    <term coccur=\"%d\"", col[j].oc);
-                        if (col[j].set_occur)
-                            wrbuf_printf(wr, " occur=\"" ZINT_FORMAT "\"", 
-                                         col[j].set_occur);
-                        wrbuf_printf(wr, ">");
-                        wrbuf_xmlputs(wr, dst_buf);
-                        wrbuf_printf(wr, "</term>\n");
-                    }
-                    else
-                    {
-                        wrbuf_printf(wr, "term %d", col[j].oc);
-                        if (col[j].set_occur)
-                            wrbuf_printf(wr, " " ZINT_FORMAT, 
-                                         col[j].set_occur);
-                        wrbuf_printf(wr, ": %s\n", dst_buf);
-                    }
-                }
-            }
-            if (use_xml)
-                wrbuf_puts(wr, "  </facet>\n");
-            nmem_destroy(nmem);
+            wrbuf_printf(result, ZEBRA_XML_HEADER_STR ">\n");
         }
+        ret = perform_facet(zh, fi, result, num_recs, poset,
+                            spec_list, no_ord, ord_array, use_xml,
+                            cat);
         if (use_xml)
-            wrbuf_puts(wr, "</facets>\n");
-        for (i = 0; i < no_ord; i++)
-            zebra_strmap_destroy(map_array[i]);
-        yaz_timing_stop(timing);
-        yaz_log(YLOG_LOG, "facet second phase real=%4.2f",
-                yaz_timing_get_real(timing));
-        yaz_timing_destroy(&timing);
+            wrbuf_puts(result, "</record>\n");
     }
     *output_format = yaz_oid_recsyn_xml;
     zebra_meta_records_destroy(zh, poset, num_recs);
@@ -929,9 +1033,7 @@ static int zebra_special_fetch(
     ZebraHandle zh = fi->zh;
     zint sysno = fi->sysno;
     
-    /* set output variables before processing possible error states */
-    /* *rec_lenp = 0; */
-
+    /* processing zebra::facet */
     if (elemsetname && 0 == strncmp(elemsetname, "facet", 5))
     {
         return facet_fetch(fi, elemsetname + 5, 
@@ -946,24 +1048,23 @@ static int zebra_special_fetch(
                              result, addinfo);
     }
 
-    /* processing zebra::meta::sysno elemset without fetching binary data */
+    /* processing zebra::meta::sysno  */
     if (elemsetname && 0 == strcmp(elemsetname, "meta::sysno"))
     {
         int ret = 0;
-        WRBUF wrbuf = result;
         if (!oid_oidcmp(input_format, yaz_oid_recsyn_sutrs))
         {
-            wrbuf_printf(wrbuf, ZINT_FORMAT, fi->sysno);
+            wrbuf_printf(result, ZINT_FORMAT, fi->sysno);
             *output_format = input_format;
         } 
         else if (!oid_oidcmp(input_format, yaz_oid_recsyn_xml))
         {
-            wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
+            wrbuf_printf(result, ZEBRA_XML_HEADER_STR
                          " sysno=\"" ZINT_FORMAT "\"/>\n",
                          fi->sysno);
             *output_format = input_format;
         }
-        if (wrbuf_len(wrbuf) == 0)
+        else
             ret = YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
         return ret;
     }
@@ -971,7 +1072,7 @@ static int zebra_special_fetch(
     /* processing special elementsetname zebra::index:: for sort elements */
     if (elemsetname && 0 == strncmp(elemsetname, "index", 5))
     {
-        int ret = zebra_special_sort_fetch(
+        int ret = sort_fetch(
             fi, elemsetname + 5,
             input_format, output_format,
             result, addinfo);
@@ -1008,35 +1109,25 @@ static int zebra_special_fetch(
         return 0;
     }
 
-    /* only accept XML and SUTRS requests from now */
-    if (oid_oidcmp(input_format, yaz_oid_recsyn_xml)
-        && oid_oidcmp(input_format, yaz_oid_recsyn_sutrs))
-    {
-        yaz_log(YLOG_WARN, "unsupported format for element set zebra::%s", 
-                elemsetname);
-        return YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
-    }
-    
     /* processing special elementsetnames zebra::meta:: */
     if (elemsetname && 0 == strcmp(elemsetname, "meta"))
     {
         int ret = 0;
-        WRBUF wrbuf = result;
         RecordAttr *recordAttr = rec_init_attr(zh->reg->zei, rec); 
 
         if (!oid_oidcmp(input_format, yaz_oid_recsyn_xml))
         {
             *output_format = input_format;
             
-            wrbuf_printf(wrbuf, ZEBRA_XML_HEADER_STR
+            wrbuf_printf(result, ZEBRA_XML_HEADER_STR
                          " sysno=\"" ZINT_FORMAT "\"", sysno);
-            retrieve_puts_attr(wrbuf, "base", rec->info[recInfo_databaseName]);
-            retrieve_puts_attr(wrbuf, "file", rec->info[recInfo_filename]);
-            retrieve_puts_attr(wrbuf, "type", rec->info[recInfo_fileType]);
+            retrieve_puts_attr(result, "base", rec->info[recInfo_databaseName]);
+            retrieve_puts_attr(result, "file", rec->info[recInfo_filename]);
+            retrieve_puts_attr(result, "type", rec->info[recInfo_fileType]);
             if (fi->score >= 0)
-                retrieve_puts_attr_int(wrbuf, "score", fi->score);
+                retrieve_puts_attr_int(result, "score", fi->score);
            
-            wrbuf_printf(wrbuf,
+            wrbuf_printf(result,
                          " rank=\"" ZINT_FORMAT "\""
                          " size=\"%i\""
                          " set=\"zebra::%s\"/>\n",
@@ -1047,14 +1138,14 @@ static int zebra_special_fetch(
         else if (!oid_oidcmp(input_format, yaz_oid_recsyn_sutrs))
         {
             *output_format = input_format;
-            wrbuf_printf(wrbuf, "sysno " ZINT_FORMAT "\n", sysno);
-            retrieve_puts_str(wrbuf, "base", rec->info[recInfo_databaseName]);
-            retrieve_puts_str(wrbuf, "file", rec->info[recInfo_filename]);
-            retrieve_puts_str(wrbuf, "type", rec->info[recInfo_fileType]);
+            wrbuf_printf(result, "sysno " ZINT_FORMAT "\n", sysno);
+            retrieve_puts_str(result, "base", rec->info[recInfo_databaseName]);
+            retrieve_puts_str(result, "file", rec->info[recInfo_filename]);
+            retrieve_puts_str(result, "type", rec->info[recInfo_fileType]);
             if (fi->score >= 0)
-                retrieve_puts_int(wrbuf, "score", fi->score);
+                retrieve_puts_int(result, "score", fi->score);
 
-            wrbuf_printf(wrbuf,
+            wrbuf_printf(result,
                          "rank " ZINT_FORMAT "\n"
                          "size %i\n"
                          "set zebra::%s\n",
@@ -1062,8 +1153,8 @@ static int zebra_special_fetch(
                          recordAttr->recordSize,
                          elemsetname);
         }
-       if (wrbuf_len(wrbuf) == 0)
-            ret = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
+        else
+            ret = YAZ_BIB1_NO_SYNTAXES_AVAILABLE_FOR_THIS_REQUEST;
 
         rec_free(&rec);
         return ret;
@@ -1091,7 +1182,7 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
                        const Odr_oid *input_format, Z_RecordComposition *comp,
                        const Odr_oid **output_format,
                        char **rec_bufp, int *rec_lenp, char **basenamep,
-                       char **addinfo)
+                       WRBUF addinfo_w)
 {
     Record rec;
     char *fname, *file_type, *basename;
@@ -1111,7 +1202,6 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
 
     sysno = sysnos[0];
     *basenamep = 0;
-    *addinfo = 0;
     elemsetname = yaz_get_esn(comp);
 
     fetch_info.zh = zh;
@@ -1124,7 +1214,6 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
     if (elemsetname && 0 == strncmp(elemsetname, "zebra::", 7))
     {
         WRBUF result = wrbuf_alloc();
-        WRBUF addinfo_w = wrbuf_alloc();
         int r = zebra_special_fetch(&fetch_info, elemsetname + 7,
                                     input_format, output_format,
                                     result, addinfo_w);
@@ -1133,13 +1222,7 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
             *rec_bufp = odr_strdup(odr, wrbuf_cstr(result));
             *rec_lenp = wrbuf_len(result);
         }
-        else 
-        {
-            if (wrbuf_len(addinfo_w))
-                *addinfo = odr_strdup(odr, wrbuf_cstr(addinfo_w));
-        }
         wrbuf_destroy(result);
-        wrbuf_destroy(addinfo_w);
         return r;
     }
 
@@ -1193,12 +1276,8 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
         if (!(rt = recType_byName(zh->reg->recTypes, zh->res,
                                   file_type, &clientData)))
         {
-            char addinfo_str[100];
-
-            sprintf(addinfo_str, "Could not handle record type %.40s",
-                    file_type);
-                    
-            *addinfo = odr_strdup(odr, addinfo_str);
+            wrbuf_printf(addinfo_w, "Could not handle record type %.40s",
+                         file_type);
             return_code = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
         }
         else
@@ -1209,7 +1288,8 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname,
             *output_format = retrieveCtrl.output_format;
             *rec_bufp = (char *) retrieveCtrl.rec_buf;
             *rec_lenp = retrieveCtrl.rec_len;
-            *addinfo = retrieveCtrl.addinfo;
+            if (retrieveCtrl.addinfo)
+                wrbuf_puts(addinfo_w, retrieveCtrl.addinfo);
         }
 
         stream.destroy(&stream);