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