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