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