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