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