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