]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
zap charray
[openldap] / servers / slapd / back-bdb / filterindex.c
1 /* filterindex.c - generate the list of candidate entries from a filter */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14 #include "idl.h"
15
16 static int presence_candidates(
17         Backend *be,
18         AttributeDescription *desc,
19         ID *ids );
20
21 static int equality_candidates(
22         Backend *be,
23         AttributeAssertion *ava,
24         ID *ids,
25         ID *tmp );
26 static int approx_candidates(
27         Backend *be,
28         AttributeAssertion *ava,
29         ID *ids,
30         ID *tmp );
31 static int substring_candidates(
32         Backend *be,
33         SubstringsAssertion *sub,
34         ID *ids,
35         ID *tmp );
36
37 static int list_candidates(
38         Backend *be,
39         Filter *flist,
40         int ftype,
41         ID *ids,
42         ID *tmp,
43         ID *stack );
44
45 int
46 bdb_filter_candidates(
47         Backend *be,
48         Filter  *f,
49         ID *ids,
50         ID *tmp,
51         ID *stack )
52 {
53         int rc = -1;
54 #ifdef NEW_LOGGING
55         LDAP_LOG ( INDEX, ENTRY, "=> bdb_filter_candidates\n", 0, 0, 0 );
56 #else
57         Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
58 #endif
59
60         switch ( f->f_choice ) {
61         case SLAPD_FILTER_DN_ONE:
62 #ifdef NEW_LOGGING
63                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN ONE\n", 0, 0, 0 );
64 #else
65                 Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
66 #endif
67                 rc = bdb_dn2idl( be, f->f_dn, DN_ONE_PREFIX, ids );
68                 if( rc == DB_NOTFOUND ) {
69                         BDB_IDL_ZERO( ids );
70                         rc = 0;
71                 }
72                 break;
73
74         case SLAPD_FILTER_DN_SUBTREE:
75 #ifdef NEW_LOGGING
76                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN SUBTREE\n", 0, 0, 0 );
77 #else
78                 Debug( LDAP_DEBUG_FILTER, "\tDN SUBTREE\n", 0, 0, 0 );
79 #endif
80                 rc = bdb_dn2idl( be, f->f_dn, DN_SUBTREE_PREFIX, ids );
81                 break;
82
83         case LDAP_FILTER_PRESENT:
84 #ifdef NEW_LOGGING
85                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tPRESENT\n", 0, 0, 0 );
86 #else
87                 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
88 #endif
89                 rc = presence_candidates( be, f->f_desc, ids );
90                 break;
91
92         case LDAP_FILTER_EQUALITY:
93 #ifdef NEW_LOGGING
94                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tEQUALITY\n", 0, 0, 0 );
95 #else
96                 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
97 #endif
98                 rc = equality_candidates( be, f->f_ava, ids, tmp );
99                 break;
100
101         case LDAP_FILTER_APPROX:
102 #ifdef NEW_LOGGING
103                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAPPROX\n", 0, 0, 0 );
104 #else
105                 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
106 #endif
107                 rc = approx_candidates( be, f->f_ava, ids, tmp );
108                 break;
109
110         case LDAP_FILTER_SUBSTRINGS:
111 #ifdef NEW_LOGGING
112                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tSUBSTRINGS\n", 0, 0, 0 );
113 #else
114                 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
115 #endif
116                 rc = substring_candidates( be, f->f_sub, ids, tmp );
117                 break;
118
119         case LDAP_FILTER_GE:
120                 /* no GE index, use pres */
121 #ifdef NEW_LOGGING
122                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tGE\n", 0, 0, 0 );
123 #else
124                 Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
125 #endif
126                 rc = presence_candidates( be, f->f_ava->aa_desc, ids );
127                 break;
128
129         case LDAP_FILTER_LE:
130                 /* no LE index, use pres */
131 #ifdef NEW_LOGGING
132                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tLE\n", 0, 0, 0 );
133 #else
134                 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
135 #endif
136                 rc = presence_candidates( be, f->f_ava->aa_desc, ids );
137                 break;
138
139         case LDAP_FILTER_NOT:
140                 /* no indexing to support NOT filters */
141 #ifdef NEW_LOGGING
142                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tNOT\n",0, 0, 0 );
143 #else
144                 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
145 #endif
146                 break;
147
148         case LDAP_FILTER_AND:
149 #ifdef NEW_LOGGING
150                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAND\n", 0, 0, 0 );
151 #else
152                 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
153 #endif
154                 rc = list_candidates( be, 
155                         f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
156                 break;
157
158         case LDAP_FILTER_OR:
159 #ifdef NEW_LOGGING
160                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tOR\n", 0, 0, 0 );
161 #else
162                 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
163 #endif
164                 rc = list_candidates( be, 
165                         f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
166                 break;
167
168         default:
169 #ifdef NEW_LOGGING
170                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tUNKNOWN\n", 0, 0, 0 );
171 #else
172                 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
173                         (unsigned long) f->f_choice, 0, 0 );
174 #endif
175         }
176
177 #ifdef NEW_LOGGING
178         LDAP_LOG ( INDEX, RESULTS, 
179                 "=> bdb_filter_candidates: id=%ld first=%ld last=%ld\n", 
180                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ));
181 #else
182         Debug( LDAP_DEBUG_FILTER,
183                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
184                 (long) ids[0],
185                 (long) BDB_IDL_FIRST( ids ),
186                 (long) BDB_IDL_LAST( ids ) );
187 #endif
188
189         return rc;
190 }
191
192 static int
193 list_candidates(
194         Backend *be,
195         Filter  *flist,
196         int             ftype,
197         ID *ids,
198         ID *tmp,
199         ID *save )
200 {
201         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
202         int rc = 0;
203         Filter  *f;
204
205 #ifdef NEW_LOGGING
206         LDAP_LOG ( INDEX, ARGS, "=> bdb_list_candidates: 0x%x\n", ftype, 0 , 0 );
207 #else
208         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
209 #endif
210
211         if ( ftype == LDAP_FILTER_OR ) {
212                 BDB_IDL_ALL( bdb, save );
213                 BDB_IDL_ZERO( ids );
214         } else {
215                 BDB_IDL_CPY( save, ids );
216         }
217
218         for ( f = flist; f != NULL; f = f->f_next ) {
219                 rc = bdb_filter_candidates( be, f, save, tmp,
220                         save+BDB_IDL_UM_SIZE );
221
222                 if ( rc != 0 ) {
223                         if ( ftype == LDAP_FILTER_AND ) {
224                                 rc = 0;
225                                 continue;
226                         }
227                         break;
228                 }
229                 
230                 if ( ftype == LDAP_FILTER_AND ) {
231                         bdb_idl_intersection( ids, save );
232                         if( BDB_IDL_IS_ZERO( ids ) )
233                                 break;
234                 } else {
235                         bdb_idl_union( ids, save );
236                         BDB_IDL_ALL( bdb, save );
237                 }
238         }
239
240         if( rc ) {
241 #ifdef NEW_LOGGING
242                 LDAP_LOG ( INDEX, RESULTS, 
243                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
244                         (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
245                         (long) BDB_IDL_LAST( ids ) );
246 #else
247                 Debug( LDAP_DEBUG_FILTER,
248                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
249                         (long) ids[0],
250                         (long) BDB_IDL_FIRST(ids),
251                         (long) BDB_IDL_LAST(ids) );
252 #endif
253
254         } else {
255 #ifdef NEW_LOGGING
256                 LDAP_LOG ( INDEX, ARGS, "<= bdb_list_candidates: rc=%d\n", rc, 0, 0 );
257 #else
258                 Debug( LDAP_DEBUG_FILTER,
259                         "<= bdb_list_candidates: undefined rc=%d\n",
260                         rc, 0, 0 );
261 #endif
262         }
263
264         return rc;
265 }
266
267 static int
268 presence_candidates(
269         Backend *be,
270         AttributeDescription *desc,
271         ID *ids )
272 {
273         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
274         DB *db;
275         int rc;
276         slap_mask_t mask;
277         struct berval prefix = {0};
278
279 #ifdef NEW_LOGGING
280         LDAP_LOG ( INDEX, ENTRY, "=> bdb_presence_candidates\n", 0, 0, 0 );
281 #else
282         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates\n", 0, 0, 0 );
283 #endif
284
285         if( desc == slap_schema.si_ad_objectClass ) {
286                 BDB_IDL_ALL( bdb, ids );
287                 return 0;
288         }
289
290         rc = bdb_index_param( be, desc, LDAP_FILTER_PRESENT,
291                 &db, &mask, &prefix );
292
293         if( rc != LDAP_SUCCESS ) {
294 #ifdef NEW_LOGGING
295                 LDAP_LOG ( INDEX, RESULTS, 
296                         "=> bdb_presence_candidates: index_parm returned=%d\n", rc, 0, 0 );
297 #else
298                 Debug( LDAP_DEBUG_TRACE,
299                         "<= bdb_presence_candidates: index_param returned=%d\n",
300                         rc, 0, 0 );
301 #endif
302                 return 0;
303         }
304
305         if( db == NULL ) {
306                 /* not indexed */
307 #ifdef NEW_LOGGING
308                 LDAP_LOG(INDEX, RESULTS, 
309                         "<= bdb_presence_candidates: not indexed\n", 0, 0, 0 );
310 #else
311                 Debug( LDAP_DEBUG_TRACE,
312                         "<= bdb_presence_candidates: not indexed\n",
313                         0, 0, 0 );
314 #endif
315                 return 0;
316         }
317
318         if( prefix.bv_val == NULL ) {
319 #ifdef NEW_LOGGING
320                 LDAP_LOG(INDEX, RESULTS, 
321                         "<= bdb_presence_candidates: no prefix\n", 0, 0, 0 );
322 #else
323                 Debug( LDAP_DEBUG_TRACE,
324                         "<= bdb_presence_candidates: no prefix\n",
325                         0, 0, 0 );
326 #endif
327                 return 0;
328         }
329
330         rc = bdb_key_read( be, db, NULL, &prefix, ids );
331
332         if( rc == DB_NOTFOUND ) {
333                 BDB_IDL_ZERO( ids );
334                 rc = 0;
335         } else if( rc != LDAP_SUCCESS ) {
336 #ifdef NEW_LOGGING
337                 LDAP_LOG ( INDEX, RESULTS, 
338                         "<= bdb_presence_candidates: key read failed (%d)\n", rc, 0, 0 );
339 #else
340                 Debug( LDAP_DEBUG_TRACE,
341                         "<= bdb_presense_candidates: key read failed (%d)\n",
342                         rc, 0, 0 );
343 #endif
344                 goto done;
345         }
346
347 #ifdef NEW_LOGGING
348         LDAP_LOG ( INDEX, RESULTS, 
349                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
350                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long)BDB_IDL_LAST( ids ) );
351 #else
352         Debug(LDAP_DEBUG_TRACE,
353                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
354                 (long) ids[0],
355                 (long) BDB_IDL_FIRST(ids),
356                 (long) BDB_IDL_LAST(ids) );
357 #endif
358
359 done:
360         return rc;
361 }
362
363 static int
364 equality_candidates(
365         Backend *be,
366         AttributeAssertion *ava,
367         ID *ids,
368         ID *tmp )
369 {
370         DB      *db;
371         int i;
372         int rc;
373         slap_mask_t mask;
374         struct berval prefix = {0};
375         struct berval *keys = NULL;
376         MatchingRule *mr;
377
378 #ifdef NEW_LOGGING
379         LDAP_LOG ( INDEX, ENTRY, "=> equality_candidates\n", 0, 0, 0 );
380 #else
381         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates\n", 0, 0, 0 );
382 #endif
383
384         rc = bdb_index_param( be, ava->aa_desc, LDAP_FILTER_EQUALITY,
385                 &db, &mask, &prefix );
386
387         if( rc != LDAP_SUCCESS ) {
388 #ifdef NEW_LOGGING
389                 LDAP_LOG ( INDEX, RESULTS, 
390                         "=> bdb_equality_candidates: index_param failed (%d)\n", rc, 0, 0);
391 #else
392                 Debug( LDAP_DEBUG_ANY,
393                         "<= bdb_equality_candidates: index_param failed (%d)\n",
394                         rc, 0, 0 );
395 #endif
396                 return rc;
397         }
398
399         if ( db == NULL ) {
400 #ifdef NEW_LOGGING
401                 LDAP_LOG(INDEX, RESULTS, 
402                         "=> bdb_equality_candidates: not indexed\n", 0, 0, 0 );
403 #else
404                 Debug( LDAP_DEBUG_ANY,
405                         "<= bdb_equality_candidates: not indexed\n", 0, 0, 0 );
406 #endif
407                 return -1;
408         }
409
410         mr = ava->aa_desc->ad_type->sat_equality;
411         if( !mr ) {
412                 return -1;
413         }
414
415         if( !mr->smr_filter ) {
416                 return -1;
417         }
418
419         rc = (mr->smr_filter)(
420                 LDAP_FILTER_EQUALITY,
421                 mask,
422                 ava->aa_desc->ad_type->sat_syntax,
423                 mr,
424                 &prefix,
425                 &ava->aa_value,
426                 &keys );
427
428         if( rc != LDAP_SUCCESS ) {
429 #ifdef NEW_LOGGING
430                 LDAP_LOG ( INDEX, RESULTS, 
431                         "=> bdb_equality_candidates: MR filter failed (%d)\n", rc, 0, 0);
432 #else
433                 Debug( LDAP_DEBUG_TRACE,
434                         "<= bdb_equality_candidates: MR filter failed (%d)\n",
435                         rc, 0, 0 );
436 #endif
437                 return rc;
438         }
439
440         if( keys == NULL ) {
441 #ifdef NEW_LOGGING
442                 LDAP_LOG ( INDEX, RESULTS, 
443                         "=> bdb_equality_candidates: no keys\n", 0, 0, 0 );
444 #else
445                 Debug( LDAP_DEBUG_TRACE,
446                         "<= bdb_equality_candidates: no keys\n",
447                         0, 0, 0 );
448 #endif
449                 return 0;
450         }
451
452         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
453                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
454
455                 if( rc == DB_NOTFOUND ) {
456                         BDB_IDL_ZERO( ids );
457                         rc = 0;
458                 } else if( rc != LDAP_SUCCESS ) {
459 #ifdef NEW_LOGGING
460                         LDAP_LOG ( INDEX, RESULTS, 
461                                 "<= bdb_equality_candidates: key read failed (%d)\n", rc, 0, 0);
462 #else
463                         Debug( LDAP_DEBUG_TRACE,
464                                 "<= bdb_equality_candidates key read failed (%d)\n",
465                                 rc, 0, 0 );
466 #endif
467                         break;
468                 }
469
470                 if( BDB_IDL_IS_ZERO( tmp ) ) {
471 #ifdef NEW_LOGGING
472                         LDAP_LOG ( INDEX, RESULTS, "=> bdb_equality_candidates: NULL\n", 0, 0, 0);
473 #else
474                         Debug( LDAP_DEBUG_TRACE,
475                                 "<= bdb_equality_candidates NULL\n",
476                                 0, 0, 0 );
477 #endif
478                         BDB_IDL_ZERO( ids );
479                         break;
480                 }
481
482                 bdb_idl_intersection( ids, tmp );
483
484                 if( BDB_IDL_IS_ZERO( ids ) )
485                         break;
486         }
487
488         ber_bvarray_free( keys );
489
490 #ifdef NEW_LOGGING
491         LDAP_LOG ( INDEX, RESULTS, 
492                 "<= bdb_equality_candidates: id=%ld first=%ld last=%ld\n", 
493                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
494                 (long) BDB_IDL_LAST( ids ) );
495 #else
496         Debug( LDAP_DEBUG_TRACE,
497                 "<= bdb_equality_candidates id=%ld, first=%ld, last=%ld\n",
498                 (long) ids[0],
499                 (long) BDB_IDL_FIRST(ids),
500                 (long) BDB_IDL_LAST(ids) );
501 #endif
502         return( rc );
503 }
504
505
506 static int
507 approx_candidates(
508         Backend *be,
509         AttributeAssertion *ava,
510         ID *ids,
511         ID *tmp )
512 {
513         DB      *db;
514         int i;
515         int rc;
516         slap_mask_t mask;
517         struct berval prefix = {0};
518         struct berval *keys = NULL;
519         MatchingRule *mr;
520
521 #ifdef NEW_LOGGING
522         LDAP_LOG ( INDEX, ENTRY, "=> bdb_approx_candidates\n", 0, 0, 0 );
523 #else
524         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates\n", 0, 0, 0 );
525 #endif
526
527         rc = bdb_index_param( be, ava->aa_desc, LDAP_FILTER_APPROX,
528                 &db, &mask, &prefix );
529
530         if( rc != LDAP_SUCCESS ) {
531 #ifdef NEW_LOGGING
532                 LDAP_LOG ( INDEX, RESULTS, 
533                         "<= bdb_approx_candidates: index_param failed (%d)\n", rc, 0, 0 );
534 #else
535                 Debug( LDAP_DEBUG_ANY,
536                         "<= bdb_approx_candidates: index_param failed (%d)\n",
537                         rc, 0, 0 );
538 #endif
539                 return rc;
540         }
541
542         if ( db == NULL ) {
543 #ifdef NEW_LOGGING
544                 LDAP_LOG(INDEX, RESULTS, 
545                         "<= bdb_approx_candidates: not indexed\n",0, 0, 0 );
546 #else
547                 Debug( LDAP_DEBUG_ANY,
548                         "<= bdb_approx_candidates: not indexed\n", 0, 0, 0 );
549 #endif
550                 return -1;
551         }
552
553         mr = ava->aa_desc->ad_type->sat_approx;
554         if( !mr ) {
555                 /* no approx matching rule, try equality matching rule */
556                 mr = ava->aa_desc->ad_type->sat_equality;
557         }
558
559         if( !mr ) {
560                 return -1;
561         }
562
563         if( !mr->smr_filter ) {
564                 return -1;
565         }
566
567         rc = (mr->smr_filter)(
568                 LDAP_FILTER_APPROX,
569                 mask,
570                 ava->aa_desc->ad_type->sat_syntax,
571                 mr,
572                 &prefix,
573                 &ava->aa_value,
574                 &keys );
575
576         if( rc != LDAP_SUCCESS ) {
577 #ifdef NEW_LOGGING
578                 LDAP_LOG ( INDEX, RESULTS, 
579                         "<= bdb_approx_candidates: MR filter failed (%d)\n", rc, 0, 0 );
580 #else
581                 Debug( LDAP_DEBUG_TRACE,
582                         "<= bdb_approx_candidates: (%s) MR filter failed (%d)\n",
583                         prefix.bv_val, rc, 0 );
584 #endif
585                 return rc;
586         }
587
588         if( keys == NULL ) {
589 #ifdef NEW_LOGGING
590                 LDAP_LOG ( INDEX, RESULTS, 
591                         "<= bdb_approx_candidates: no keys (%s)\n", prefix.bv_val, 0, 0 );
592 #else
593                 Debug( LDAP_DEBUG_TRACE,
594                         "<= bdb_approx_candidates: no keys (%s)\n",
595                         prefix.bv_val, 0, 0 );
596 #endif
597                 return 0;
598         }
599
600         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
601                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
602
603                 if( rc == DB_NOTFOUND ) {
604                         BDB_IDL_ZERO( ids );
605                         rc = 0;
606                         break;
607                 } else if( rc != LDAP_SUCCESS ) {
608 #ifdef NEW_LOGGING
609                 LDAP_LOG ( INDEX, RESULTS, 
610                         "<= bdb_approx_candidates: key read failed (%d)\n", rc, 0, 0);
611 #else
612                         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates key read failed (%d)\n",
613                                 rc, 0, 0 );
614 #endif
615                         break;
616                 }
617
618                 if( BDB_IDL_IS_ZERO( tmp ) ) {
619 #ifdef NEW_LOGGING
620                         LDAP_LOG ( INDEX, RESULTS, 
621                                 "<= bdb_approx_candidates: NULL\n", 0, 0, 0 );
622 #else
623                         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates NULL\n",
624                                 0, 0, 0 );
625 #endif
626                         BDB_IDL_ZERO( ids );
627                         break;
628                 }
629
630                 bdb_idl_intersection( ids, tmp );
631
632                 if( BDB_IDL_IS_ZERO( ids ) )
633                         break;
634         }
635
636         ber_bvarray_free( keys );
637
638 #ifdef NEW_LOGGING
639         LDAP_LOG ( INDEX, RESULTS, 
640                 "<= bdb_approx_candidates: id=%ld first=%ld last=%ld\n", 
641                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
642                 (long) BDB_IDL_LAST( ids ) );
643 #else
644         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
645                 (long) ids[0],
646                 (long) BDB_IDL_FIRST(ids),
647                 (long) BDB_IDL_LAST(ids) );
648 #endif
649         return( rc );
650 }
651
652 static int
653 substring_candidates(
654         Backend *be,
655         SubstringsAssertion     *sub,
656         ID *ids,
657         ID *tmp )
658 {
659         DB      *db;
660         int i;
661         int rc;
662         slap_mask_t mask;
663         struct berval prefix = {0};
664         struct berval *keys = NULL;
665         MatchingRule *mr;
666
667 #ifdef NEW_LOGGING
668         LDAP_LOG ( INDEX, ENTRY, "=> bdb_substring_candidates\n", 0, 0, 0 );
669 #else
670         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates\n", 0, 0, 0 );
671 #endif
672
673         rc = bdb_index_param( be, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
674                 &db, &mask, &prefix );
675
676         if( rc != LDAP_SUCCESS ) {
677 #ifdef NEW_LOGGING
678                 LDAP_LOG ( INDEX, RESULTS, 
679                         "<= bdb_substring_candidates: index_param failed (%d)\n", rc, 0, 0);
680 #else
681                 Debug( LDAP_DEBUG_ANY,
682                         "<= bdb_substring_candidates: index_param failed (%d)\n",
683                         rc, 0, 0 );
684 #endif
685                 return rc;
686         }
687
688         if ( db == NULL ) {
689 #ifdef NEW_LOGGING
690                 LDAP_LOG ( INDEX, RESULTS, 
691                         "<= bdb_substring_candidates: not indexed\n", 0, 0, 0 );
692 #else
693                 Debug( LDAP_DEBUG_ANY,
694                         "<= bdb_substring_candidates not indexed\n",
695                         0, 0, 0 );
696 #endif
697                 return -1;
698         }
699
700         mr = sub->sa_desc->ad_type->sat_substr;
701
702         if( !mr ) {
703                 return -1;
704         }
705
706         if( !mr->smr_filter ) {
707                 return -1;
708         }
709
710         rc = (mr->smr_filter)(
711                 LDAP_FILTER_SUBSTRINGS,
712                 mask,
713                 sub->sa_desc->ad_type->sat_syntax,
714                 mr,
715                 &prefix,
716                 sub,
717                 &keys );
718
719         if( rc != LDAP_SUCCESS ) {
720 #ifdef NEW_LOGGING
721                 LDAP_LOG ( INDEX, RESULTS, 
722                         "<= bdb_substring_candidates: (%s) MR filter failed (%d)\n", 
723                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
724 #else
725                 Debug( LDAP_DEBUG_TRACE,
726                         "<= bdb_substring_candidates: (%s) MR filter failed (%d)\n",
727                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
728 #endif
729                 return rc;
730         }
731
732         if( keys == NULL ) {
733 #ifdef NEW_LOGGING
734                 LDAP_LOG ( INDEX, RESULTS, 
735                         "<= bdb_substring_candidates: (%d) MR filter failed (%s)\n", 
736                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
737 #else
738                 Debug( LDAP_DEBUG_TRACE,
739                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
740                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
741 #endif
742                 return 0;
743         }
744
745         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
746                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
747
748                 if( rc == DB_NOTFOUND ) {
749                         BDB_IDL_ZERO( ids );
750                         rc = 0;
751                         break;
752                 } else if( rc != LDAP_SUCCESS ) {
753 #ifdef NEW_LOGGING
754                         LDAP_LOG ( INDEX, RESULTS, 
755                                 "<= bdb_substring_candidates: key read failed (%d)\n", rc, 0,0);
756 #else
757                         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates key read failed (%d)\n",
758                                 rc, 0, 0 );
759 #endif
760                         break;
761                 }
762
763                 if( BDB_IDL_IS_ZERO( tmp ) ) {
764 #ifdef NEW_LOGGING
765                         LDAP_LOG ( INDEX, RESULTS, 
766                                 "<= bdb_substring_candidates: NULL \n", 0, 0, 0 );
767 #else
768                         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates NULL\n",
769                                 0, 0, 0 );
770 #endif
771                         BDB_IDL_ZERO( ids );
772                         break;
773                 }
774
775                 bdb_idl_intersection( ids, tmp );
776
777                 if( BDB_IDL_IS_ZERO( ids ) )
778                         break;
779         }
780
781         ber_bvarray_free( keys );
782
783 #ifdef NEW_LOGGING
784         LDAP_LOG ( INDEX, RESULTS, 
785                 "<= bdb_substring_candidates: id=%ld first=%ld last=%ld\n",
786                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
787                 (long) BDB_IDL_LAST( ids ) );
788 #else
789         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates %ld, first=%ld, last=%ld\n",
790                 (long) ids[0],
791                 (long) BDB_IDL_FIRST(ids),
792                 (long) BDB_IDL_LAST(ids) );
793 #endif
794         return( 0 );
795 }
796