88b4880b488e96a711df31de868eaa5dd13f1176
[idzebra-moved-to-github.git] / index / zsets.c
1 /*
2  * Copyright (C) 1994-1998, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: zsets.c,v $
7  * Revision 1.14  1998-02-10 16:39:15  adam
8  * Minor change.
9  *
10  * Revision 1.13  1998/02/10 12:03:06  adam
11  * Implemented Sort.
12  *
13  * Revision 1.12  1997/09/25 14:57:36  adam
14  * Windows NT port.
15  *
16  * Revision 1.11  1996/12/23 15:30:46  adam
17  * Work on truncation.
18  * Bug fix: result sets weren't deleted after server shut down.
19  *
20  * Revision 1.10  1995/10/30 15:08:08  adam
21  * Bug fixes.
22  *
23  * Revision 1.9  1995/10/17  18:02:14  adam
24  * New feature: databases. Implemented as prefix to words in dictionary.
25  *
26  * Revision 1.8  1995/10/10  13:59:25  adam
27  * Function rset_open changed its wflag parameter to general flags.
28  *
29  * Revision 1.7  1995/10/06  14:38:01  adam
30  * New result set method: r_score.
31  * Local no (sysno) and score is transferred to retrieveCtrl.
32  *
33  * Revision 1.6  1995/09/28  09:19:49  adam
34  * xfree/xmalloc used everywhere.
35  * Extract/retrieve method seems to work for text records.
36  *
37  * Revision 1.5  1995/09/27  16:17:32  adam
38  * More work on retrieve.
39  *
40  * Revision 1.4  1995/09/07  13:58:36  adam
41  * New parameter: result-set file descriptor (RSFD) to support multiple
42  * positions within the same result-set.
43  * Boolean operators: and, or, not implemented.
44  * Result-set references.
45  *
46  * Revision 1.3  1995/09/06  16:11:19  adam
47  * Option: only one word key per file.
48  *
49  * Revision 1.2  1995/09/06  10:33:04  adam
50  * More work on present. Some log messages removed.
51  *
52  * Revision 1.1  1995/09/05  15:28:40  adam
53  * More work on search engine.
54  *
55  */
56 #include <stdio.h>
57 #include <assert.h>
58 #ifdef WINDOWS
59 #include <io.h>
60 #else
61 #include <unistd.h>
62 #endif
63
64 #include "zserver.h"
65 #include <rstemp.h>
66
67 #define SORT_IDX_ENTRYSIZE 64
68 #define ZSET_SORT_MAX_LEVEL 3
69
70 struct zset_sort_entry {
71     int sysno;
72     char buf[ZSET_SORT_MAX_LEVEL][SORT_IDX_ENTRYSIZE];
73 };
74
75 struct zset_sort_info {
76     int max_entries;
77     int num_entries;
78     struct zset_sort_entry **entries;
79 };
80
81 void resultSetSortReset (struct zset_sort_info **si)
82 {
83     int i;
84     if (!*si)
85         return ;
86     for (i = 0; i<(*si)->num_entries; i++)
87         xfree ((*si)->entries[i]);
88     xfree ((*si)->entries);
89     xfree (*si);
90     *si = NULL;
91 }
92
93 ZServerSet *resultSetAdd (ZServerInfo *zi, const char *name, int ov, RSET rset)
94 {
95     ZServerSet *s;
96
97     for (s = zi->sets; s; s = s->next)
98         if (!strcmp (s->name, name))
99         {
100             logf (LOG_DEBUG, "updating result set %s", name);
101             if (!ov)
102                 return NULL;
103             resultSetSortReset (&s->sort_info);
104             rset_delete (s->rset);
105             s->rset = rset;
106             return s;
107         }
108     logf (LOG_DEBUG, "adding result set %s", name);
109     s = xmalloc (sizeof(*s));
110     s->next = zi->sets;
111     zi->sets = s;
112     s->name = xmalloc (strlen(name)+1);
113     strcpy (s->name, name);
114     s->rset = rset;
115     s->sort_info = NULL;
116     return s;
117 }
118
119 ZServerSet *resultSetGet (ZServerInfo *zi, const char *name)
120 {
121     ZServerSet *s;
122
123     for (s = zi->sets; s; s = s->next)
124         if (!strcmp (s->name, name))
125             return s;
126     return NULL;
127 }
128
129     
130 void resultSetDestroy (ZServerInfo *zi)
131 {
132     ZServerSet *s, *s1;
133
134     for (s = zi->sets; s; s = s1)
135     {
136         s1 = s->next;
137         resultSetSortReset (&s->sort_info);
138         rset_delete (s->rset);
139         xfree (s->name);
140         xfree (s);
141     }
142     zi->sets = NULL;
143 }
144
145 ZServerSetSysno *resultSetSysnoGet (ZServerInfo *zi, const char *name, 
146                                     int num, int *positions)
147 {
148     ZServerSet *sset;
149     ZServerSetSysno *sr;
150     RSET rset;
151     int i;
152     struct zset_sort_info *sort_info;
153
154     if (!(sset = resultSetGet (zi, name)))
155         return NULL;
156     if (!(rset = sset->rset))
157         return NULL;
158     sr = xmalloc (sizeof(*sr) * num);
159     for (i = 0; i<num; i++)
160     {
161         sr[i].sysno = 0;
162         sr[i].score = -1;
163     }
164     sort_info = sset->sort_info;
165     if (sort_info)
166     {
167         int position;
168
169         for (i = 0; i<num; i++)
170         {
171             position = positions[i];
172             if (position <= sort_info->num_entries)
173             {
174                 logf (LOG_DEBUG, "got pos=%d (sorted)", position);
175                 sr[i].sysno = sort_info->entries[position-1]->sysno;
176             }
177         }
178     }
179     /* did we really get all entries using sort ? */
180     for (i = 0; i<num; i++)
181     {
182         if (!sr[i].sysno)
183             break;
184     }
185     if (i < num) /* nope, get the rest, unsorted - sorry */
186     {
187         int position = 0;
188         int num_i = 0;
189         int psysno = 0;
190         RSFD rfd;
191         struct it_key key;
192
193         if (sort_info)
194             position = sort_info->num_entries;
195         while (num_i < num && positions[num_i] < position)
196             num_i++;
197         rfd = rset_open (rset, RSETF_READ|RSETF_SORT_RANK);
198         while (num_i < num && rset_read (rset, rfd, &key))
199         {
200             if (key.sysno != psysno)
201             {
202                 psysno = key.sysno;
203                 if (sort_info)
204                 {
205                     /* determine we alreay have this in our set */
206                     for (i = sort_info->num_entries; --i >= 0; )
207                         if (psysno == sort_info->entries[i]->sysno)
208                             break;
209                     if (i >= 0)
210                         continue;
211                 }
212                 position++;
213                 assert (num_i < num);
214                 if (position == positions[num_i])
215                 {
216                     sr[num_i].sysno = psysno;
217                     logf (LOG_DEBUG, "got pos=%d (unsorted)", position);
218                     rset_score (rset, rfd, &sr[num_i].score);
219                     num_i++;
220                 }
221             }
222         }
223         rset_close (rset, rfd);
224     }
225     return sr;
226 }
227
228 void resultSetSysnoDel (ZServerInfo *zi, ZServerSetSysno *records, int num)
229 {
230     xfree (records);
231 }
232
233 struct sortKey {
234     int relation;
235     int attrUse;
236 };
237
238 void resultSetInsertSort (ZServerInfo *zi, ZServerSet *sset,
239                           struct sortKey *criteria, int num_criteria,
240                           int sysno)
241 {
242     struct zset_sort_entry this_entry;
243     struct zset_sort_entry *new_entry = NULL;
244     struct zset_sort_info *sort_info = sset->sort_info;
245     int i, j;
246
247     sortIdx_sysno (zi->sortIdx, sysno);
248     for (i = 0; i<num_criteria; i++)
249     {
250         sortIdx_type (zi->sortIdx, criteria[i].attrUse);
251         sortIdx_read (zi->sortIdx, this_entry.buf[i]);
252     }
253     i = sort_info->num_entries;
254     while (--i >= 0)
255     {
256         int rel = 0;
257         for (j = 0; j<num_criteria; j++)
258         {
259             rel = memcmp (this_entry.buf[j], sort_info->entries[i]->buf[j],
260                           SORT_IDX_ENTRYSIZE);
261             if (rel)
262                 break;
263         }       
264         if (rel)
265         {
266             if (criteria[j].relation == 'D')
267                 if (rel > 0)
268                     break;
269             if (criteria[j].relation == 'A')
270                 if (rel < 0)
271                     break;
272         }
273     }
274     j = sort_info->max_entries-1;
275     if (i == j)
276         return;
277     ++i;
278     new_entry = sort_info->entries[j];
279     while (j != i)
280     {
281         sort_info->entries[j] = sort_info->entries[j-1];
282         --j;
283     }
284     sort_info->entries[j] = new_entry;
285     assert (new_entry);
286     if (sort_info->num_entries != sort_info->max_entries)
287         (sort_info->num_entries)++;
288     for (i = 0; i<num_criteria; i++)
289         memcpy (new_entry->buf[i], this_entry.buf[i], SORT_IDX_ENTRYSIZE);
290     new_entry->sysno = sysno;
291 }
292         
293 int resultSetSort (ZServerInfo *zi, bend_sort_rr *rr)
294 {
295     ZServerSet *sset;
296     RSET rset;
297     int i, psysno = 0;
298     struct it_key key;
299     struct sortKey sort_criteria[3];
300     int num_criteria;
301     RSFD rfd;
302
303     if (rr->num_input_setnames == 0)
304     {
305         rr->errcode = 208;
306         return 0;
307     }
308     if (rr->num_input_setnames > 1)
309     {
310         rr->errcode = 230;
311         return 0;
312     }
313     sset = resultSetGet (zi, rr->input_setnames[0]);
314     if (!sset)
315     {
316         rr->errcode = 30;
317         rr->errstring =  rr->input_setnames[0];
318         return 0;
319     }
320     if (!(rset = sset->rset))
321     {
322         rr->errcode = 30;
323         rr->errstring =  rr->input_setnames[0];
324         return 0;
325     }
326     num_criteria = rr->sort_sequence->num_specs;
327     if (num_criteria > 3)
328         num_criteria = 3;
329     for (i = 0; i < num_criteria; i++)
330     {
331         Z_SortKeySpec *sks = rr->sort_sequence->specs[i];
332         Z_SortKey *sk;
333
334         if (*sks->sortRelation == Z_SortRelation_ascending)
335             sort_criteria[i].relation = 'A';
336         else if (*sks->sortRelation == Z_SortRelation_descending)
337             sort_criteria[i].relation = 'D';
338         else
339         {
340             rr->errcode = 214;
341             return 0;
342         }
343         if (sks->sortElement->which == Z_SortElement_databaseSpecific)
344         {
345             rr->errcode = 210;
346             return 0;
347         }
348         else if (sks->sortElement->which != Z_SortElement_generic)
349         {
350             rr->errcode = 237;
351             return 0;
352         }       
353         sk = sks->sortElement->u.generic;
354         switch (sk->which)
355         {
356         case Z_SortKey_sortField:
357             logf (LOG_DEBUG, "Sort: key %d is of type sortField", i+1);
358             rr->errcode = 207;
359             return 0;
360         case Z_SortKey_elementSpec:
361             logf (LOG_DEBUG, "Sort: key %d is of type elementSpec", i+1);
362             return 0;
363         case Z_SortKey_sortAttributes:
364             logf (LOG_DEBUG, "Sort: key %d is of type sortAttributes", i+1);
365             sort_criteria[i].attrUse =
366                 zebra_maps_sort (zi->zebra_maps, sk->u.sortAttributes);
367             logf (LOG_DEBUG, "use value = %d", sort_criteria[i].attrUse);
368             if (sort_criteria[i].attrUse == -1)
369             {
370                 rr->errcode = 116;
371                 return 0;
372             }
373             if (sortIdx_type (zi->sortIdx, sort_criteria[i].attrUse))
374             {
375                 rr->errcode = 207;
376                 return 0;
377             }
378             break;
379         }
380     }
381     if (strcmp (rr->output_setname, rr->input_setnames[0]))
382     {
383         rset = rset_dup (rset);
384         sset = resultSetAdd (zi, rr->output_setname, 1, rset);
385     }
386     resultSetSortReset (&sset->sort_info);
387
388     sset->sort_info = xmalloc (sizeof(*sset->sort_info));
389     sset->sort_info->max_entries = 100;
390     sset->sort_info->num_entries = 0;
391     sset->sort_info->entries =  xmalloc (sizeof(*sset->sort_info->entries) * 
392                                          sset->sort_info->max_entries);
393     for (i = 0; i<sset->sort_info->max_entries; i++)
394         sset->sort_info->entries[i] =
395             xmalloc (sizeof(*sset->sort_info->entries[i]));
396
397
398     rfd = rset_open (rset, RSETF_READ|RSETF_SORT_SYSNO);
399     while (rset_read (rset, rfd, &key))
400     {
401         if (key.sysno != psysno)
402         {
403             psysno = key.sysno;
404             resultSetInsertSort (zi, sset,
405                                  sort_criteria, num_criteria, psysno);
406         }
407     }
408     rset_close (rset, rfd);
409
410     rr->errcode = 0;
411     rr->sort_status = Z_SortStatus_success;
412     
413     return 0;
414 }
415