]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
ae75380ab99df26caf3563bec9131c43a7aedd69
[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-2003 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 = 0;
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                 { struct bdb_info *bdb = (struct bdb_info *) be->be_private;
147                 BDB_IDL_ALL( bdb, ids );
148                 }
149                 break;
150
151         case LDAP_FILTER_AND:
152 #ifdef NEW_LOGGING
153                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAND\n", 0, 0, 0 );
154 #else
155                 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
156 #endif
157                 rc = list_candidates( be, 
158                         f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
159                 break;
160
161         case LDAP_FILTER_OR:
162 #ifdef NEW_LOGGING
163                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tOR\n", 0, 0, 0 );
164 #else
165                 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
166 #endif
167                 rc = list_candidates( be, 
168                         f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
169                 break;
170
171         default:
172 #ifdef NEW_LOGGING
173                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tUNKNOWN\n", 0, 0, 0 );
174 #else
175                 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
176                         (unsigned long) f->f_choice, 0, 0 );
177 #endif
178                 /* Must not return NULL, otherwise extended filters break */
179                 { struct bdb_info *bdb = (struct bdb_info *) be->be_private;
180                 BDB_IDL_ALL( bdb, ids );
181                 }
182         }
183
184 #ifdef NEW_LOGGING
185         LDAP_LOG ( INDEX, RESULTS, 
186                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n", 
187                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ));
188 #else
189         Debug( LDAP_DEBUG_FILTER,
190                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
191                 (long) ids[0],
192                 (long) BDB_IDL_FIRST( ids ),
193                 (long) BDB_IDL_LAST( ids ) );
194 #endif
195
196         return rc;
197 }
198
199 static int
200 list_candidates(
201         Backend *be,
202         Filter  *flist,
203         int             ftype,
204         ID *ids,
205         ID *tmp,
206         ID *save )
207 {
208         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
209         int rc = 0;
210         Filter  *f;
211
212 #ifdef NEW_LOGGING
213         LDAP_LOG ( INDEX, ARGS, "=> bdb_list_candidates: 0x%x\n", ftype, 0 , 0 );
214 #else
215         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
216 #endif
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                         if ( f == flist ) {
232                                 BDB_IDL_CPY( ids, save );
233                         } else {
234                                 bdb_idl_intersection( ids, save );
235                         }
236                         if( BDB_IDL_IS_ZERO( ids ) )
237                                 break;
238                 } else {
239                         if ( f == flist ) {
240                                 BDB_IDL_CPY( ids, save );
241                         } else {
242                                 bdb_idl_union( ids, save );
243                         }
244                 }
245         }
246
247         if( rc == LDAP_SUCCESS ) {
248 #ifdef NEW_LOGGING
249                 LDAP_LOG ( INDEX, RESULTS, 
250                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
251                         (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
252                         (long) BDB_IDL_LAST( ids ) );
253 #else
254                 Debug( LDAP_DEBUG_FILTER,
255                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
256                         (long) ids[0],
257                         (long) BDB_IDL_FIRST(ids),
258                         (long) BDB_IDL_LAST(ids) );
259 #endif
260
261         } else {
262 #ifdef NEW_LOGGING
263                 LDAP_LOG ( INDEX, ARGS, "<= bdb_list_candidates: rc=%d\n", rc, 0, 0 );
264 #else
265                 Debug( LDAP_DEBUG_FILTER,
266                         "<= bdb_list_candidates: undefined rc=%d\n",
267                         rc, 0, 0 );
268 #endif
269         }
270
271         return rc;
272 }
273
274 static int
275 presence_candidates(
276         Backend *be,
277         AttributeDescription *desc,
278         ID *ids )
279 {
280         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
281         DB *db;
282         int rc;
283         slap_mask_t mask;
284         struct berval prefix = {0, NULL};
285
286 #ifdef NEW_LOGGING
287         LDAP_LOG ( INDEX, ENTRY, "=> bdb_presence_candidates (%s)\n", 
288                         desc->ad_cname.bv_val, 0, 0 );
289 #else
290         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
291                         desc->ad_cname.bv_val, 0, 0 );
292 #endif
293
294         if( desc == slap_schema.si_ad_objectClass ) {
295                 BDB_IDL_ALL( bdb, ids );
296                 return 0;
297         }
298
299         rc = bdb_index_param( be, desc, LDAP_FILTER_PRESENT,
300                 &db, &mask, &prefix );
301
302         if( rc != LDAP_SUCCESS ) {
303 #ifdef NEW_LOGGING
304                 LDAP_LOG ( INDEX, RESULTS, 
305                         "<= bdb_presence_candidates: (%s) index_param "
306                         "returned=%d\n",
307                         desc->ad_cname.bv_val, rc, 0 );
308 #else
309                 Debug( LDAP_DEBUG_TRACE,
310                         "<= bdb_presence_candidates: (%s) index_param "
311                         "returned=%d\n",
312                         desc->ad_cname.bv_val, rc, 0 );
313 #endif
314                 return 0;
315         }
316
317         if( db == NULL ) {
318                 /* not indexed */
319 #ifdef NEW_LOGGING
320                 LDAP_LOG(INDEX, RESULTS, 
321                         "<= bdb_presence_candidates: (%s) not indexed\n",
322                         desc->ad_cname.bv_val, 0, 0 );
323 #else
324                 Debug( LDAP_DEBUG_TRACE,
325                         "<= bdb_presence_candidates: (%s) not indexed\n",
326                         desc->ad_cname.bv_val, 0, 0 );
327 #endif
328                 return 0;
329         }
330
331         if( prefix.bv_val == NULL ) {
332 #ifdef NEW_LOGGING
333                 LDAP_LOG(INDEX, RESULTS, 
334                         "<= bdb_presence_candidates: (%s) no prefix\n",
335                         desc->ad_cname.bv_val, 0, 0 );
336 #else
337                 Debug( LDAP_DEBUG_TRACE,
338                         "<= bdb_presence_candidates: (%s) no prefix\n",
339                         desc->ad_cname.bv_val, 0, 0 );
340 #endif
341                 return 0;
342         }
343
344         rc = bdb_key_read( be, db, NULL, &prefix, ids );
345
346         if( rc == DB_NOTFOUND ) {
347                 BDB_IDL_ZERO( ids );
348                 rc = 0;
349         } else if( rc != LDAP_SUCCESS ) {
350 #ifdef NEW_LOGGING
351                 LDAP_LOG ( INDEX, RESULTS, 
352                         "<= bdb_presence_candidates: (%s) "
353                         "key read failed (%d)\n",
354                         desc->ad_cname.bv_val, rc, 0 );
355 #else
356                 Debug( LDAP_DEBUG_TRACE,
357                         "<= bdb_presense_candidates: (%s) "
358                         "key read failed (%d)\n",
359                         desc->ad_cname.bv_val, rc, 0 );
360 #endif
361                 goto done;
362         }
363
364 #ifdef NEW_LOGGING
365         LDAP_LOG ( INDEX, RESULTS, 
366                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
367                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long)BDB_IDL_LAST( ids ) );
368 #else
369         Debug(LDAP_DEBUG_TRACE,
370                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
371                 (long) ids[0],
372                 (long) BDB_IDL_FIRST(ids),
373                 (long) BDB_IDL_LAST(ids) );
374 #endif
375
376 done:
377         return rc;
378 }
379
380 static int
381 equality_candidates(
382         Backend *be,
383         AttributeAssertion *ava,
384         ID *ids,
385         ID *tmp )
386 {
387         DB      *db;
388         int i;
389         int rc;
390         slap_mask_t mask;
391         struct berval prefix = {0, NULL};
392         struct berval *keys = NULL;
393         MatchingRule *mr;
394
395 #ifdef NEW_LOGGING
396         LDAP_LOG ( INDEX, ENTRY, "=> bdb_equality_candidates (%s)\n",
397                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
398 #else
399         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
400                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
401 #endif
402
403         rc = bdb_index_param( be, ava->aa_desc, LDAP_FILTER_EQUALITY,
404                 &db, &mask, &prefix );
405
406         if( rc != LDAP_SUCCESS ) {
407 #ifdef NEW_LOGGING
408                 LDAP_LOG ( INDEX, RESULTS, 
409                         "<= bdb_equality_candidates: (%s) "
410                         "index_param failed (%d)\n", 
411                         ava->aa_desc->ad_cname.bv_val, rc, 0);
412 #else
413                 Debug( LDAP_DEBUG_ANY,
414                         "<= bdb_equality_candidates: (%s) "
415                         "index_param failed (%d)\n",
416                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
417 #endif
418                 return rc;
419         }
420
421         if ( db == NULL ) {
422 #ifdef NEW_LOGGING
423                 LDAP_LOG(INDEX, RESULTS, 
424                         "<= bdb_equality_candidates: (%s) not indexed\n", 
425                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
426 #else
427                 Debug( LDAP_DEBUG_ANY,
428                         "<= bdb_equality_candidates: (%s) not indexed\n", 
429                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
430 #endif
431                 return -1;
432         }
433
434         mr = ava->aa_desc->ad_type->sat_equality;
435         if( !mr ) {
436                 return -1;
437         }
438
439         if( !mr->smr_filter ) {
440                 return -1;
441         }
442
443         rc = (mr->smr_filter)(
444                 LDAP_FILTER_EQUALITY,
445                 mask,
446                 ava->aa_desc->ad_type->sat_syntax,
447                 mr,
448                 &prefix,
449                 &ava->aa_value,
450                 &keys );
451
452         if( rc != LDAP_SUCCESS ) {
453 #ifdef NEW_LOGGING
454                 LDAP_LOG ( INDEX, RESULTS, 
455                         "<= bdb_equality_candidates: (%s, %s) "
456                         "MR filter failed (%d)\n",
457                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
458 #else
459                 Debug( LDAP_DEBUG_TRACE,
460                         "<= bdb_equality_candidates: (%s, %s) "
461                         "MR filter failed (%d)\n",
462                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
463 #endif
464                 return rc;
465         }
466
467         if( keys == NULL ) {
468 #ifdef NEW_LOGGING
469                 LDAP_LOG ( INDEX, RESULTS, 
470                         "<= bdb_equality_candidates: (%s) no keys\n", 
471                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
472 #else
473                 Debug( LDAP_DEBUG_TRACE,
474                         "<= bdb_equality_candidates: (%s) no keys\n",
475                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
476 #endif
477                 return 0;
478         }
479
480         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
481                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
482
483                 if( rc == DB_NOTFOUND ) {
484                         BDB_IDL_ZERO( ids );
485                         rc = 0;
486                 } else if( rc != LDAP_SUCCESS ) {
487 #ifdef NEW_LOGGING
488                         LDAP_LOG ( INDEX, RESULTS, 
489                                 "<= bdb_equality_candidates: (%s) "
490                                 "key read failed (%d)\n",
491                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
492 #else
493                         Debug( LDAP_DEBUG_TRACE,
494                                 "<= bdb_equality_candidates: (%s) "
495                                 "key read failed (%d)\n",
496                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
497 #endif
498                         break;
499                 }
500
501                 if( BDB_IDL_IS_ZERO( tmp ) ) {
502 #ifdef NEW_LOGGING
503                         LDAP_LOG ( INDEX, RESULTS,
504                                 "<= bdb_equality_candidates: (%s) NULL\n",
505                                 ava->aa_desc->ad_cname.bv_val, 0, 0);
506 #else
507                         Debug( LDAP_DEBUG_TRACE,
508                                 "<= bdb_equality_candidates: (%s) NULL\n", 
509                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
510 #endif
511                         BDB_IDL_ZERO( ids );
512                         break;
513                 }
514
515                 if ( i == 0 ) {
516                         BDB_IDL_CPY( ids, tmp );
517                 } else {
518                         bdb_idl_intersection( ids, tmp );
519                 }
520
521                 if( BDB_IDL_IS_ZERO( ids ) )
522                         break;
523         }
524
525         ber_bvarray_free( keys );
526
527 #ifdef NEW_LOGGING
528         LDAP_LOG ( INDEX, RESULTS, 
529                 "<= bdb_equality_candidates: id=%ld first=%ld last=%ld\n", 
530                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
531                 (long) BDB_IDL_LAST( ids ) );
532 #else
533         Debug( LDAP_DEBUG_TRACE,
534                 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
535                 (long) ids[0],
536                 (long) BDB_IDL_FIRST(ids),
537                 (long) BDB_IDL_LAST(ids) );
538 #endif
539         return( rc );
540 }
541
542
543 static int
544 approx_candidates(
545         Backend *be,
546         AttributeAssertion *ava,
547         ID *ids,
548         ID *tmp )
549 {
550         DB      *db;
551         int i;
552         int rc;
553         slap_mask_t mask;
554         struct berval prefix = {0, NULL};
555         struct berval *keys = NULL;
556         MatchingRule *mr;
557
558 #ifdef NEW_LOGGING
559         LDAP_LOG ( INDEX, ENTRY, "=> bdb_approx_candidates (%s)\n",
560                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
561 #else
562         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
563                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
564 #endif
565
566         rc = bdb_index_param( be, ava->aa_desc, LDAP_FILTER_APPROX,
567                 &db, &mask, &prefix );
568
569         if( rc != LDAP_SUCCESS ) {
570 #ifdef NEW_LOGGING
571                 LDAP_LOG ( INDEX, RESULTS, 
572                         "<= bdb_approx_candidates: (%s) "
573                         "index_param failed (%d)\n",
574                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
575 #else
576                 Debug( LDAP_DEBUG_ANY,
577                         "<= bdb_approx_candidates: (%s) "
578                         "index_param failed (%d)\n",
579                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
580 #endif
581                 return rc;
582         }
583
584         if ( db == NULL ) {
585 #ifdef NEW_LOGGING
586                 LDAP_LOG(INDEX, RESULTS, 
587                         "<= bdb_approx_candidates: (%s) not indexed\n",
588                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
589 #else
590                 Debug( LDAP_DEBUG_ANY,
591                         "<= bdb_approx_candidates: (%s) not indexed\n",
592                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
593 #endif
594                 return -1;
595         }
596
597         mr = ava->aa_desc->ad_type->sat_approx;
598         if( !mr ) {
599                 /* no approx matching rule, try equality matching rule */
600                 mr = ava->aa_desc->ad_type->sat_equality;
601         }
602
603         if( !mr ) {
604                 return -1;
605         }
606
607         if( !mr->smr_filter ) {
608                 return -1;
609         }
610
611         rc = (mr->smr_filter)(
612                 LDAP_FILTER_APPROX,
613                 mask,
614                 ava->aa_desc->ad_type->sat_syntax,
615                 mr,
616                 &prefix,
617                 &ava->aa_value,
618                 &keys );
619
620         if( rc != LDAP_SUCCESS ) {
621 #ifdef NEW_LOGGING
622                 LDAP_LOG ( INDEX, RESULTS, 
623                         "<= bdb_approx_candidates: (%s, %s) "
624                         "MR filter failed (%d)\n",
625                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
626 #else
627                 Debug( LDAP_DEBUG_TRACE,
628                         "<= bdb_approx_candidates: (%s, %s) "
629                         "MR filter failed (%d)\n",
630                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
631 #endif
632                 return rc;
633         }
634
635         if( keys == NULL ) {
636 #ifdef NEW_LOGGING
637                 LDAP_LOG ( INDEX, RESULTS, 
638                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
639                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
640 #else
641                 Debug( LDAP_DEBUG_TRACE,
642                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
643                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
644 #endif
645                 return 0;
646         }
647
648         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
649                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
650
651                 if( rc == DB_NOTFOUND ) {
652                         BDB_IDL_ZERO( ids );
653                         rc = 0;
654                         break;
655                 } else if( rc != LDAP_SUCCESS ) {
656 #ifdef NEW_LOGGING
657                         LDAP_LOG ( INDEX, RESULTS, 
658                                 "<= bdb_approx_candidates: (%s) "
659                                 "key read failed (%d)\n",
660                                 ava->aa_desc->ad_cname.bv_val, rc, 0);
661 #else
662                         Debug( LDAP_DEBUG_TRACE,
663                                 "<= bdb_approx_candidates: (%s) "
664                                 "key read failed (%d)\n",
665                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
666 #endif
667                         break;
668                 }
669
670                 if( BDB_IDL_IS_ZERO( tmp ) ) {
671 #ifdef NEW_LOGGING
672                         LDAP_LOG ( INDEX, RESULTS, 
673                                 "<= bdb_approx_candidates: (%s) NULL\n",
674                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
675 #else
676                         Debug( LDAP_DEBUG_TRACE,
677                                 "<= bdb_approx_candidates: (%s) NULL\n",
678                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
679 #endif
680                         BDB_IDL_ZERO( ids );
681                         break;
682                 }
683
684                 if ( i == 0 ) {
685                         BDB_IDL_CPY( ids, tmp );
686                 } else {
687                         bdb_idl_intersection( ids, tmp );
688                 }
689
690                 if( BDB_IDL_IS_ZERO( ids ) )
691                         break;
692         }
693
694         ber_bvarray_free( keys );
695
696 #ifdef NEW_LOGGING
697         LDAP_LOG ( INDEX, RESULTS, 
698                 "<= bdb_approx_candidates: id=%ld first=%ld last=%ld\n", 
699                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
700                 (long) BDB_IDL_LAST( ids ) );
701 #else
702         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
703                 (long) ids[0],
704                 (long) BDB_IDL_FIRST(ids),
705                 (long) BDB_IDL_LAST(ids) );
706 #endif
707         return( rc );
708 }
709
710 static int
711 substring_candidates(
712         Backend *be,
713         SubstringsAssertion     *sub,
714         ID *ids,
715         ID *tmp )
716 {
717         DB      *db;
718         int i;
719         int rc;
720         slap_mask_t mask;
721         struct berval prefix = {0, NULL};
722         struct berval *keys = NULL;
723         MatchingRule *mr;
724
725 #ifdef NEW_LOGGING
726         LDAP_LOG ( INDEX, ENTRY, "=> bdb_substring_candidates (%s)\n",
727                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
728 #else
729         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
730                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
731 #endif
732
733         rc = bdb_index_param( be, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
734                 &db, &mask, &prefix );
735
736         if( rc != LDAP_SUCCESS ) {
737 #ifdef NEW_LOGGING
738                 LDAP_LOG ( INDEX, RESULTS, 
739                         "<= bdb_substring_candidates: (%s) "
740                         "index_param failed (%d)\n",
741                         sub->sa_desc->ad_cname.bv_val, rc, 0);
742 #else
743                 Debug( LDAP_DEBUG_ANY,
744                         "<= bdb_substring_candidates: (%s) "
745                         "index_param failed (%d)\n",
746                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
747 #endif
748                 return rc;
749         }
750
751         if ( db == NULL ) {
752 #ifdef NEW_LOGGING
753                 LDAP_LOG ( INDEX, RESULTS, 
754                         "<= bdb_substring_candidates: (%s) not indexed\n",
755                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
756 #else
757                 Debug( LDAP_DEBUG_ANY,
758                         "<= bdb_substring_candidates: (%s) not indexed\n",
759                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
760 #endif
761                 return -1;
762         }
763
764         mr = sub->sa_desc->ad_type->sat_substr;
765
766         if( !mr ) {
767                 return -1;
768         }
769
770         if( !mr->smr_filter ) {
771                 return -1;
772         }
773
774         rc = (mr->smr_filter)(
775                 LDAP_FILTER_SUBSTRINGS,
776                 mask,
777                 sub->sa_desc->ad_type->sat_syntax,
778                 mr,
779                 &prefix,
780                 sub,
781                 &keys );
782
783         if( rc != LDAP_SUCCESS ) {
784 #ifdef NEW_LOGGING
785                 LDAP_LOG ( INDEX, RESULTS, 
786                         "<= bdb_substring_candidates: (%s) "
787                         "MR filter failed (%d)\n", 
788                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
789 #else
790                 Debug( LDAP_DEBUG_TRACE,
791                         "<= bdb_substring_candidates: (%s) "
792                         "MR filter failed (%d)\n",
793                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
794 #endif
795                 return rc;
796         }
797
798         if( keys == NULL ) {
799 #ifdef NEW_LOGGING
800                 LDAP_LOG ( INDEX, RESULTS, 
801                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
802                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
803 #else
804                 Debug( LDAP_DEBUG_TRACE,
805                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
806                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
807 #endif
808                 return 0;
809         }
810
811         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
812                 rc = bdb_key_read( be, db, NULL, &keys[i], tmp );
813
814                 if( rc == DB_NOTFOUND ) {
815                         BDB_IDL_ZERO( ids );
816                         rc = 0;
817                         break;
818                 } else if( rc != LDAP_SUCCESS ) {
819 #ifdef NEW_LOGGING
820                         LDAP_LOG ( INDEX, RESULTS, 
821                                 "<= bdb_substring_candidates: (%s) "
822                                 "key read failed (%d)\n",
823                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
824 #else
825                         Debug( LDAP_DEBUG_TRACE,
826                                 "<= bdb_substring_candidates: (%s) "
827                                 "key read failed (%d)\n",
828                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
829 #endif
830                         break;
831                 }
832
833                 if( BDB_IDL_IS_ZERO( tmp ) ) {
834 #ifdef NEW_LOGGING
835                         LDAP_LOG ( INDEX, RESULTS, 
836                                 "<= bdb_substring_candidates: (%s) NULL\n",
837                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
838 #else
839                         Debug( LDAP_DEBUG_TRACE,
840                                 "<= bdb_substring_candidates: (%s) NULL\n",
841                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
842 #endif
843                         BDB_IDL_ZERO( ids );
844                         break;
845                 }
846
847                 if ( i == 0 ) {
848                         BDB_IDL_CPY( ids, tmp );
849                 } else {
850                         bdb_idl_intersection( ids, tmp );
851                 }
852
853                 if( BDB_IDL_IS_ZERO( ids ) )
854                         break;
855         }
856
857         ber_bvarray_free( keys );
858
859 #ifdef NEW_LOGGING
860         LDAP_LOG ( INDEX, RESULTS, 
861                 "<= bdb_substring_candidates: id=%ld first=%ld last=%ld\n",
862                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
863                 (long) BDB_IDL_LAST( ids ) );
864 #else
865         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
866                 (long) ids[0],
867                 (long) BDB_IDL_FIRST(ids),
868                 (long) BDB_IDL_LAST(ids) );
869 #endif
870         return( 0 );
871 }
872