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