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