]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
Fix prev commit, cleanup fakeroot entry before freeing
[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-2007 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 #ifdef LDAP_COMP_MATCH
25 #include <component.h>
26 #endif
27
28 static int presence_candidates(
29         Operation *op,
30         u_int32_t locker,
31         AttributeDescription *desc,
32         ID *ids );
33
34 static int equality_candidates(
35         Operation *op,
36         u_int32_t locker,
37         AttributeAssertion *ava,
38         ID *ids,
39         ID *tmp );
40 static int inequality_candidates(
41         Operation *op,
42         u_int32_t locker,
43         AttributeAssertion *ava,
44         ID *ids,
45         ID *tmp,
46         int gtorlt );
47 static int approx_candidates(
48         Operation *op,
49         u_int32_t locker,
50         AttributeAssertion *ava,
51         ID *ids,
52         ID *tmp );
53 static int substring_candidates(
54         Operation *op,
55         u_int32_t locker,
56         SubstringsAssertion *sub,
57         ID *ids,
58         ID *tmp );
59
60 static int list_candidates(
61         Operation *op,
62         u_int32_t locker,
63         Filter *flist,
64         int ftype,
65         ID *ids,
66         ID *tmp,
67         ID *stack );
68
69 static int
70 ext_candidates(
71         Operation *op,
72                 u_int32_t locker,
73         MatchingRuleAssertion *mra,
74         ID *ids,
75         ID *tmp,
76         ID *stack);
77
78 #ifdef LDAP_COMP_MATCH
79 static int
80 comp_candidates (
81         Operation *op,
82         u_int32_t locker,
83         MatchingRuleAssertion *mra,
84         ComponentFilter *f,
85         ID *ids,
86         ID *tmp,
87         ID *stack);
88
89 static int
90 ava_comp_candidates (
91                 Operation *op,
92                 u_int32_t locker,
93                 AttributeAssertion *ava,
94                 AttributeAliasing *aa,
95                 ID *ids,
96                 ID *tmp,
97                 ID *stack);
98 #endif
99
100 int
101 bdb_filter_candidates(
102         Operation *op,
103         u_int32_t locker,
104         Filter  *f,
105         ID *ids,
106         ID *tmp,
107         ID *stack )
108 {
109         int rc = 0;
110 #ifdef LDAP_COMP_MATCH
111         AttributeAliasing *aa;
112 #endif
113         Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
114
115         if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
116                 BDB_IDL_ZERO( ids );
117                 goto out;
118         }
119
120         switch ( f->f_choice ) {
121         case SLAPD_FILTER_COMPUTED:
122                 switch( f->f_result ) {
123                 case SLAPD_COMPARE_UNDEFINED:
124                 /* This technically is not the same as FALSE, but it
125                  * certainly will produce no matches.
126                  */
127                 /* FALL THRU */
128                 case LDAP_COMPARE_FALSE:
129                         BDB_IDL_ZERO( ids );
130                         break;
131                 case LDAP_COMPARE_TRUE: {
132                         struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
133                         BDB_IDL_ALL( bdb, ids );
134                         } break;
135                 case LDAP_SUCCESS:
136                         /* this is a pre-computed scope, leave it alone */
137                         break;
138                 }
139                 break;
140         case LDAP_FILTER_PRESENT:
141                 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
142                 rc = presence_candidates( op, locker, f->f_desc, ids );
143                 break;
144
145         case LDAP_FILTER_EQUALITY:
146                 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
147 #ifdef LDAP_COMP_MATCH
148                 if ( is_aliased_attribute && ( aa = is_aliased_attribute ( f->f_ava->aa_desc ) ) ) {
149                         rc = ava_comp_candidates ( op, locker, f->f_ava, aa, ids, tmp, stack );
150                 }
151                 else
152 #endif
153                 {
154                         rc = equality_candidates( op, locker, f->f_ava, ids, tmp );
155                 }
156                 break;
157
158         case LDAP_FILTER_APPROX:
159                 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
160                 rc = approx_candidates( op, locker, f->f_ava, ids, tmp );
161                 break;
162
163         case LDAP_FILTER_SUBSTRINGS:
164                 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
165                 rc = substring_candidates( op, locker, f->f_sub, ids, tmp );
166                 break;
167
168         case LDAP_FILTER_GE:
169                 /* if no GE index, use pres */
170                 Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
171                 if( f->f_ava->aa_desc->ad_type->sat_ordering &&
172                         ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
173                         rc = inequality_candidates( op, locker, f->f_ava, ids, tmp, LDAP_FILTER_GE );
174                 else
175                         rc = presence_candidates( op, locker, f->f_ava->aa_desc, ids );
176                 break;
177
178         case LDAP_FILTER_LE:
179                 /* if no LE index, use pres */
180                 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
181                 if( f->f_ava->aa_desc->ad_type->sat_ordering &&
182                         ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
183                         rc = inequality_candidates( op, locker, f->f_ava, ids, tmp, LDAP_FILTER_LE );
184                 else
185                         rc = presence_candidates( op, locker, f->f_ava->aa_desc, ids );
186                 break;
187
188         case LDAP_FILTER_NOT:
189                 /* no indexing to support NOT filters */
190                 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
191                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
192                 BDB_IDL_ALL( bdb, ids );
193                 }
194                 break;
195
196         case LDAP_FILTER_AND:
197                 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
198                 rc = list_candidates( op, locker, 
199                         f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
200                 break;
201
202         case LDAP_FILTER_OR:
203                 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
204                 rc = list_candidates( op, locker,
205                         f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
206                 break;
207         case LDAP_FILTER_EXT:
208                 Debug( LDAP_DEBUG_FILTER, "\tEXT\n", 0, 0, 0 );
209                 rc = ext_candidates( op, locker, f->f_mra, ids, tmp, stack );
210                 break;
211         default:
212                 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
213                         (unsigned long) f->f_choice, 0, 0 );
214                 /* Must not return NULL, otherwise extended filters break */
215                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
216                 BDB_IDL_ALL( bdb, ids );
217                 }
218         }
219
220 out:
221         Debug( LDAP_DEBUG_FILTER,
222                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
223                 (long) ids[0],
224                 (long) BDB_IDL_FIRST( ids ),
225                 (long) BDB_IDL_LAST( ids ) );
226
227         return rc;
228 }
229
230 #ifdef LDAP_COMP_MATCH
231 static int
232 comp_list_candidates(
233         Operation *op,
234         u_int32_t locker,
235         MatchingRuleAssertion* mra,
236         ComponentFilter *flist,
237         int     ftype,
238         ID *ids,
239         ID *tmp,
240         ID *save )
241 {
242         int rc = 0;
243         ComponentFilter *f;
244
245         Debug( LDAP_DEBUG_FILTER, "=> comp_list_candidates 0x%x\n", ftype, 0, 0 );
246         for ( f = flist; f != NULL; f = f->cf_next ) {
247                 /* ignore precomputed scopes */
248                 if ( f->cf_choice == SLAPD_FILTER_COMPUTED &&
249                      f->cf_result == LDAP_SUCCESS ) {
250                         continue;
251                 }
252                 BDB_IDL_ZERO( save );
253                 rc = comp_candidates( op, locker, mra, f, save, tmp, save+BDB_IDL_UM_SIZE );
254
255                 if ( rc != 0 ) {
256                         if ( ftype == LDAP_COMP_FILTER_AND ) {
257                                 rc = 0;
258                                 continue;
259                         }
260                         break;
261                 }
262                 
263                 if ( ftype == LDAP_COMP_FILTER_AND ) {
264                         if ( f == flist ) {
265                                 BDB_IDL_CPY( ids, save );
266                         } else {
267                                 bdb_idl_intersection( ids, save );
268                         }
269                         if( BDB_IDL_IS_ZERO( ids ) )
270                                 break;
271                 } else {
272                         if ( f == flist ) {
273                                 BDB_IDL_CPY( ids, save );
274                         } else {
275                                 bdb_idl_union( ids, save );
276                         }
277                 }
278         }
279
280         if( rc == LDAP_SUCCESS ) {
281                 Debug( LDAP_DEBUG_FILTER,
282                         "<= comp_list_candidates: id=%ld first=%ld last=%ld\n",
283                         (long) ids[0],
284                         (long) BDB_IDL_FIRST(ids),
285                         (long) BDB_IDL_LAST(ids) );
286
287         } else {
288                 Debug( LDAP_DEBUG_FILTER,
289                         "<= comp_list_candidates: undefined rc=%d\n",
290                         rc, 0, 0 );
291         }
292
293         return rc;
294 }
295
296 static int
297 comp_equality_candidates (
298         Operation *op,
299         u_int32_t locker,
300         MatchingRuleAssertion *mra,
301         ComponentAssertion *ca,
302         ID *ids,
303         ID *tmp,
304         ID *stack)
305 {
306        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
307         DB      *db;
308         int i;
309         int rc;
310         slap_mask_t mask;
311         struct berval prefix = {0, NULL};
312         struct berval *keys = NULL;
313         MatchingRule *mr = mra->ma_rule;
314         Syntax *sat_syntax;
315         ComponentReference* cr_list, *cr;
316         AttrInfo *ai;
317
318         BDB_IDL_ALL( bdb, ids );
319
320         if ( !ca->ca_comp_ref )
321                 return 0;
322
323         ai = bdb_attr_mask( op->o_bd->be_private, mra->ma_desc );
324         if( ai ) {
325                 cr_list = ai->ai_cr;
326         }
327         else {
328                 return 0;
329         }
330         /* find a component reference to be indexed */
331         sat_syntax = ca->ca_ma_rule->smr_syntax;
332         for ( cr = cr_list ; cr ; cr = cr->cr_next ) {
333                 if ( cr->cr_string.bv_len == ca->ca_comp_ref->cr_string.bv_len &&
334                         strncmp( cr->cr_string.bv_val, ca->ca_comp_ref->cr_string.bv_val,cr->cr_string.bv_len ) == 0 )
335                         break;
336         }
337         
338         if ( !cr )
339                 return 0;
340
341         rc = bdb_index_param( op->o_bd, mra->ma_desc, LDAP_FILTER_EQUALITY,
342                 &db, &mask, &prefix );
343
344         if( rc != LDAP_SUCCESS ) {
345                 return 0;
346         }
347         if ( db == NULL ) {
348                 return 0;
349         }
350
351         if( !mr ) {
352                 return 0;
353         }
354
355         if( !mr->smr_filter ) {
356                 return 0;
357         }
358
359         rc = (ca->ca_ma_rule->smr_filter)(
360                 LDAP_FILTER_EQUALITY,
361                 cr->cr_indexmask,
362                 sat_syntax,
363                 ca->ca_ma_rule,
364                 &prefix,
365                 &ca->ca_ma_value,
366                 &keys, op->o_tmpmemctx );
367
368         if( rc != LDAP_SUCCESS ) {
369                 return 0;
370         }
371
372         if( keys == NULL ) {
373                 return 0;
374         }
375         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
376                 rc = bdb_key_read( op->o_bd, db, locker, &keys[i], tmp, NULL, 0 );
377
378                 if( rc == DB_NOTFOUND ) {
379                         BDB_IDL_ZERO( ids );
380                         rc = 0;
381                         break;
382                 } else if( rc != LDAP_SUCCESS ) {
383                         break;
384                 }
385
386                 if( BDB_IDL_IS_ZERO( tmp ) ) {
387                         BDB_IDL_ZERO( ids );
388                         break;
389                 }
390
391                 if ( i == 0 ) {
392                         BDB_IDL_CPY( ids, tmp );
393                 } else {
394                         bdb_idl_intersection( ids, tmp );
395                 }
396
397                 if( BDB_IDL_IS_ZERO( ids ) )
398                         break;
399         }
400         ber_bvarray_free_x( keys, op->o_tmpmemctx );
401
402         Debug( LDAP_DEBUG_TRACE,
403                 "<= comp_equality_candidates: id=%ld, first=%ld, last=%ld\n",
404                 (long) ids[0],
405                 (long) BDB_IDL_FIRST(ids),
406                 (long) BDB_IDL_LAST(ids) );
407         return( rc );
408 }
409
410 static int
411 ava_comp_candidates (
412         Operation *op,
413         u_int32_t locker,
414         AttributeAssertion *ava,
415         AttributeAliasing *aa,
416         ID *ids,
417         ID *tmp,
418         ID *stack )
419 {
420         MatchingRuleAssertion mra;
421         
422         mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
423         if ( !mra.ma_rule ) {
424                 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
425                 BDB_IDL_ALL( bdb, ids );
426                 return 0;
427         }
428         mra.ma_desc = aa->aa_aliased_ad;
429         mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
430         
431         return comp_candidates ( op, locker, &mra, ava->aa_cf, ids, tmp, stack );
432 }
433
434 static int
435 comp_candidates (
436         Operation *op,
437         u_int32_t locker,
438         MatchingRuleAssertion *mra,
439         ComponentFilter *f,
440         ID *ids,
441         ID *tmp,
442         ID *stack)
443 {
444         int     rc;
445
446         if ( !f ) return LDAP_PROTOCOL_ERROR;
447
448         Debug( LDAP_DEBUG_FILTER, "comp_candidates\n", 0, 0, 0 );
449         switch ( f->cf_choice ) {
450         case SLAPD_FILTER_COMPUTED:
451                 rc = f->cf_result;
452                 break;
453         case LDAP_COMP_FILTER_AND:
454                 rc = comp_list_candidates( op, locker, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
455                 break;
456         case LDAP_COMP_FILTER_OR:
457                 rc = comp_list_candidates( op, locker, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
458                 break;
459         case LDAP_COMP_FILTER_NOT:
460                 /* No component indexing supported for NOT filter */
461                 Debug( LDAP_DEBUG_FILTER, "\tComponent NOT\n", 0, 0, 0 );
462                 {
463                         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
464                         BDB_IDL_ALL( bdb, ids );
465                 }
466                 rc = LDAP_PROTOCOL_ERROR;
467                 break;
468         case LDAP_COMP_FILTER_ITEM:
469                 rc = comp_equality_candidates( op, locker, mra, f->cf_ca, ids, tmp, stack );
470                 break;
471         default:
472                 {
473                         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
474                         BDB_IDL_ALL( bdb, ids );
475                 }
476                 rc = LDAP_PROTOCOL_ERROR;
477         }
478
479         return( rc );
480 }
481 #endif
482
483 static int
484 ext_candidates(
485         Operation *op,
486                 u_int32_t locker,
487         MatchingRuleAssertion *mra,
488         ID *ids,
489         ID *tmp,
490         ID *stack)
491 {
492         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
493
494 #ifdef LDAP_COMP_MATCH
495         /*
496          * Currently Only Component Indexing for componentFilterMatch is supported
497          * Indexing for an extensible filter is not supported yet
498          */
499         if ( mra->ma_cf ) {
500                 return comp_candidates ( op, locker, mra, mra->ma_cf, ids, tmp, stack);
501         }
502 #endif
503         if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
504                 int rc;
505                 EntryInfo *ei;
506
507                 BDB_IDL_ZERO( ids );
508                 if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
509                         ei = NULL;
510                         rc = bdb_cache_find_ndn( op, NULL, &mra->ma_value, &ei );
511                         if ( rc == LDAP_SUCCESS )
512                                 bdb_idl_insert( ids, ei->bei_id );
513                         if ( ei )
514                                 bdb_cache_entryinfo_unlock( ei );
515                         return 0;
516                 } else if ( mra->ma_rule && mra->ma_rule->smr_match ==
517                         dnRelativeMatch && dnIsSuffix( &mra->ma_value,
518                                 op->o_bd->be_nsuffix )) {
519                         int scope;
520                         if ( mra->ma_rule == slap_schema.si_mr_dnSuperiorMatch ) {
521                                 struct berval pdn;
522                                 ei = NULL;
523                                 dnParent( &mra->ma_value, &pdn );
524                                 bdb_cache_find_ndn( op, NULL, &pdn, &ei );
525                                 if ( ei ) {
526                                         bdb_cache_entryinfo_unlock( ei );
527                                         while ( ei && ei->bei_id ) {
528                                                 bdb_idl_insert( ids, ei->bei_id );
529                                                 ei = ei->bei_parent;
530                                         }
531                                 }
532                                 return 0;
533                         }
534                         if ( mra->ma_rule == slap_schema.si_mr_dnSubtreeMatch )
535                                 scope = LDAP_SCOPE_SUBTREE;
536                         else if ( mra->ma_rule == slap_schema.si_mr_dnOneLevelMatch )
537                                 scope = LDAP_SCOPE_ONELEVEL;
538                         else if ( mra->ma_rule == slap_schema.si_mr_dnSubordinateMatch )
539                                 scope = LDAP_SCOPE_SUBORDINATE;
540                         else
541                                 scope = LDAP_SCOPE_BASE;
542                         if ( scope > LDAP_SCOPE_BASE ) {
543                                 ei = NULL;
544                                 rc = bdb_cache_find_ndn( op, NULL, &mra->ma_value, &ei );
545                                 if ( ei )
546                                         bdb_cache_entryinfo_unlock( ei );
547                                 if ( rc == LDAP_SUCCESS ) {
548                                         int sc = op->ors_scope;
549                                         op->ors_scope = scope;
550                                         rc = bdb_dn2idl( op, locker, &mra->ma_value, ei, ids,
551                                                 stack );
552                                 }
553                                 return 0;
554                         }
555                 }
556         }
557
558         BDB_IDL_ALL( bdb, ids );
559         return 0;
560 }
561
562 static int
563 list_candidates(
564         Operation *op,
565         u_int32_t locker,
566         Filter  *flist,
567         int             ftype,
568         ID *ids,
569         ID *tmp,
570         ID *save )
571 {
572         int rc = 0;
573         Filter  *f;
574
575         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
576         for ( f = flist; f != NULL; f = f->f_next ) {
577                 /* ignore precomputed scopes */
578                 if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
579                      f->f_result == LDAP_SUCCESS ) {
580                         continue;
581                 }
582                 BDB_IDL_ZERO( save );
583                 rc = bdb_filter_candidates( op, locker, f, save, tmp,
584                         save+BDB_IDL_UM_SIZE );
585
586                 if ( rc != 0 ) {
587                         if ( ftype == LDAP_FILTER_AND ) {
588                                 rc = 0;
589                                 continue;
590                         }
591                         break;
592                 }
593
594                 
595                 if ( ftype == LDAP_FILTER_AND ) {
596                         if ( f == flist ) {
597                                 BDB_IDL_CPY( ids, save );
598                         } else {
599                                 bdb_idl_intersection( ids, save );
600                         }
601                         if( BDB_IDL_IS_ZERO( ids ) )
602                                 break;
603                 } else {
604                         if ( f == flist ) {
605                                 BDB_IDL_CPY( ids, save );
606                         } else {
607                                 bdb_idl_union( ids, save );
608                         }
609                 }
610         }
611
612         if( rc == LDAP_SUCCESS ) {
613                 Debug( LDAP_DEBUG_FILTER,
614                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
615                         (long) ids[0],
616                         (long) BDB_IDL_FIRST(ids),
617                         (long) BDB_IDL_LAST(ids) );
618
619         } else {
620                 Debug( LDAP_DEBUG_FILTER,
621                         "<= bdb_list_candidates: undefined rc=%d\n",
622                         rc, 0, 0 );
623         }
624
625         return rc;
626 }
627
628 static int
629 presence_candidates(
630         Operation *op,
631         u_int32_t locker,
632         AttributeDescription *desc,
633         ID *ids )
634 {
635         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
636         DB *db;
637         int rc;
638         slap_mask_t mask;
639         struct berval prefix = {0, NULL};
640
641         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
642                         desc->ad_cname.bv_val, 0, 0 );
643
644         BDB_IDL_ALL( bdb, ids );
645
646         if( desc == slap_schema.si_ad_objectClass ) {
647                 return 0;
648         }
649
650         rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
651                 &db, &mask, &prefix );
652
653         if( rc != LDAP_SUCCESS ) {
654                 Debug( LDAP_DEBUG_TRACE,
655                         "<= bdb_presence_candidates: (%s) index_param "
656                         "returned=%d\n",
657                         desc->ad_cname.bv_val, rc, 0 );
658                 return 0;
659         }
660
661         if( db == NULL ) {
662                 /* not indexed */
663                 Debug( LDAP_DEBUG_TRACE,
664                         "<= bdb_presence_candidates: (%s) not indexed\n",
665                         desc->ad_cname.bv_val, 0, 0 );
666                 return 0;
667         }
668
669         if( prefix.bv_val == NULL ) {
670                 Debug( LDAP_DEBUG_TRACE,
671                         "<= bdb_presence_candidates: (%s) no prefix\n",
672                         desc->ad_cname.bv_val, 0, 0 );
673                 return -1;
674         }
675
676         rc = bdb_key_read( op->o_bd, db, locker, &prefix, ids, NULL, 0 );
677
678         if( rc == DB_NOTFOUND ) {
679                 BDB_IDL_ZERO( ids );
680                 rc = 0;
681         } else if( rc != LDAP_SUCCESS ) {
682                 Debug( LDAP_DEBUG_TRACE,
683                         "<= bdb_presense_candidates: (%s) "
684                         "key read failed (%d)\n",
685                         desc->ad_cname.bv_val, rc, 0 );
686                 goto done;
687         }
688
689         Debug(LDAP_DEBUG_TRACE,
690                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
691                 (long) ids[0],
692                 (long) BDB_IDL_FIRST(ids),
693                 (long) BDB_IDL_LAST(ids) );
694
695 done:
696         return rc;
697 }
698
699 static int
700 equality_candidates(
701         Operation *op,
702         u_int32_t locker,
703         AttributeAssertion *ava,
704         ID *ids,
705         ID *tmp )
706 {
707         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
708         DB      *db;
709         int i;
710         int rc;
711         slap_mask_t mask;
712         struct berval prefix = {0, NULL};
713         struct berval *keys = NULL;
714         MatchingRule *mr;
715
716         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
717                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
718
719         BDB_IDL_ALL( bdb, ids );
720
721         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
722                 &db, &mask, &prefix );
723
724         if( rc != LDAP_SUCCESS ) {
725                 Debug( LDAP_DEBUG_ANY,
726                         "<= bdb_equality_candidates: (%s) "
727                         "index_param failed (%d)\n",
728                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
729                 return 0;
730         }
731
732         if ( db == NULL ) {
733                 Debug( LDAP_DEBUG_ANY,
734                         "<= bdb_equality_candidates: (%s) not indexed\n", 
735                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
736                 return 0;
737         }
738
739         mr = ava->aa_desc->ad_type->sat_equality;
740         if( !mr ) {
741                 return 0;
742         }
743
744         if( !mr->smr_filter ) {
745                 return 0;
746         }
747
748         rc = (mr->smr_filter)(
749                 LDAP_FILTER_EQUALITY,
750                 mask,
751                 ava->aa_desc->ad_type->sat_syntax,
752                 mr,
753                 &prefix,
754                 &ava->aa_value,
755                 &keys, op->o_tmpmemctx );
756
757         if( rc != LDAP_SUCCESS ) {
758                 Debug( LDAP_DEBUG_TRACE,
759                         "<= bdb_equality_candidates: (%s, %s) "
760                         "MR filter failed (%d)\n",
761                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
762                 return 0;
763         }
764
765         if( keys == NULL ) {
766                 Debug( LDAP_DEBUG_TRACE,
767                         "<= bdb_equality_candidates: (%s) no keys\n",
768                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
769                 return 0;
770         }
771
772         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
773                 rc = bdb_key_read( op->o_bd, db, locker, &keys[i], tmp, NULL, 0 );
774
775                 if( rc == DB_NOTFOUND ) {
776                         BDB_IDL_ZERO( ids );
777                         rc = 0;
778                         break;
779                 } else if( rc != LDAP_SUCCESS ) {
780                         Debug( LDAP_DEBUG_TRACE,
781                                 "<= bdb_equality_candidates: (%s) "
782                                 "key read failed (%d)\n",
783                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
784                         break;
785                 }
786
787                 if( BDB_IDL_IS_ZERO( tmp ) ) {
788                         Debug( LDAP_DEBUG_TRACE,
789                                 "<= bdb_equality_candidates: (%s) NULL\n", 
790                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
791                         BDB_IDL_ZERO( ids );
792                         break;
793                 }
794
795                 if ( i == 0 ) {
796                         BDB_IDL_CPY( ids, tmp );
797                 } else {
798                         bdb_idl_intersection( ids, tmp );
799                 }
800
801                 if( BDB_IDL_IS_ZERO( ids ) )
802                         break;
803         }
804
805         ber_bvarray_free_x( keys, op->o_tmpmemctx );
806
807         Debug( LDAP_DEBUG_TRACE,
808                 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
809                 (long) ids[0],
810                 (long) BDB_IDL_FIRST(ids),
811                 (long) BDB_IDL_LAST(ids) );
812         return( rc );
813 }
814
815
816 static int
817 approx_candidates(
818         Operation *op,
819         u_int32_t locker,
820         AttributeAssertion *ava,
821         ID *ids,
822         ID *tmp )
823 {
824         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
825         DB      *db;
826         int i;
827         int rc;
828         slap_mask_t mask;
829         struct berval prefix = {0, NULL};
830         struct berval *keys = NULL;
831         MatchingRule *mr;
832
833         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
834                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
835
836         BDB_IDL_ALL( bdb, ids );
837
838         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
839                 &db, &mask, &prefix );
840
841         if( rc != LDAP_SUCCESS ) {
842                 Debug( LDAP_DEBUG_ANY,
843                         "<= bdb_approx_candidates: (%s) "
844                         "index_param failed (%d)\n",
845                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
846                 return 0;
847         }
848
849         if ( db == NULL ) {
850                 Debug( LDAP_DEBUG_ANY,
851                         "<= bdb_approx_candidates: (%s) not indexed\n",
852                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
853                 return 0;
854         }
855
856         mr = ava->aa_desc->ad_type->sat_approx;
857         if( !mr ) {
858                 /* no approx matching rule, try equality matching rule */
859                 mr = ava->aa_desc->ad_type->sat_equality;
860         }
861
862         if( !mr ) {
863                 return 0;
864         }
865
866         if( !mr->smr_filter ) {
867                 return 0;
868         }
869
870         rc = (mr->smr_filter)(
871                 LDAP_FILTER_APPROX,
872                 mask,
873                 ava->aa_desc->ad_type->sat_syntax,
874                 mr,
875                 &prefix,
876                 &ava->aa_value,
877                 &keys, op->o_tmpmemctx );
878
879         if( rc != LDAP_SUCCESS ) {
880                 Debug( LDAP_DEBUG_TRACE,
881                         "<= bdb_approx_candidates: (%s, %s) "
882                         "MR filter failed (%d)\n",
883                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
884                 return 0;
885         }
886
887         if( keys == NULL ) {
888                 Debug( LDAP_DEBUG_TRACE,
889                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
890                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
891                 return 0;
892         }
893
894         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
895                 rc = bdb_key_read( op->o_bd, db, locker, &keys[i], tmp, NULL, 0 );
896
897                 if( rc == DB_NOTFOUND ) {
898                         BDB_IDL_ZERO( ids );
899                         rc = 0;
900                         break;
901                 } else if( rc != LDAP_SUCCESS ) {
902                         Debug( LDAP_DEBUG_TRACE,
903                                 "<= bdb_approx_candidates: (%s) "
904                                 "key read failed (%d)\n",
905                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
906                         break;
907                 }
908
909                 if( BDB_IDL_IS_ZERO( tmp ) ) {
910                         Debug( LDAP_DEBUG_TRACE,
911                                 "<= bdb_approx_candidates: (%s) NULL\n",
912                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
913                         BDB_IDL_ZERO( ids );
914                         break;
915                 }
916
917                 if ( i == 0 ) {
918                         BDB_IDL_CPY( ids, tmp );
919                 } else {
920                         bdb_idl_intersection( ids, tmp );
921                 }
922
923                 if( BDB_IDL_IS_ZERO( ids ) )
924                         break;
925         }
926
927         ber_bvarray_free_x( keys, op->o_tmpmemctx );
928
929         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
930                 (long) ids[0],
931                 (long) BDB_IDL_FIRST(ids),
932                 (long) BDB_IDL_LAST(ids) );
933         return( rc );
934 }
935
936 static int
937 substring_candidates(
938         Operation *op,
939         u_int32_t locker,
940         SubstringsAssertion     *sub,
941         ID *ids,
942         ID *tmp )
943 {
944         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
945         DB      *db;
946         int i;
947         int rc;
948         slap_mask_t mask;
949         struct berval prefix = {0, NULL};
950         struct berval *keys = NULL;
951         MatchingRule *mr;
952
953         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
954                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
955
956         BDB_IDL_ALL( bdb, ids );
957
958         rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
959                 &db, &mask, &prefix );
960
961         if( rc != LDAP_SUCCESS ) {
962                 Debug( LDAP_DEBUG_ANY,
963                         "<= bdb_substring_candidates: (%s) "
964                         "index_param failed (%d)\n",
965                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
966                 return 0;
967         }
968
969         if ( db == NULL ) {
970                 Debug( LDAP_DEBUG_ANY,
971                         "<= bdb_substring_candidates: (%s) not indexed\n",
972                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
973                 return 0;
974         }
975
976         mr = sub->sa_desc->ad_type->sat_substr;
977
978         if( !mr ) {
979                 return 0;
980         }
981
982         if( !mr->smr_filter ) {
983                 return 0;
984         }
985
986         rc = (mr->smr_filter)(
987                 LDAP_FILTER_SUBSTRINGS,
988                 mask,
989                 sub->sa_desc->ad_type->sat_syntax,
990                 mr,
991                 &prefix,
992                 sub,
993                 &keys, op->o_tmpmemctx );
994
995         if( rc != LDAP_SUCCESS ) {
996                 Debug( LDAP_DEBUG_TRACE,
997                         "<= bdb_substring_candidates: (%s) "
998                         "MR filter failed (%d)\n",
999                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
1000                 return 0;
1001         }
1002
1003         if( keys == NULL ) {
1004                 Debug( LDAP_DEBUG_TRACE,
1005                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
1006                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
1007                 return 0;
1008         }
1009
1010         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
1011                 rc = bdb_key_read( op->o_bd, db, locker, &keys[i], tmp, NULL, 0 );
1012
1013                 if( rc == DB_NOTFOUND ) {
1014                         BDB_IDL_ZERO( ids );
1015                         rc = 0;
1016                         break;
1017                 } else if( rc != LDAP_SUCCESS ) {
1018                         Debug( LDAP_DEBUG_TRACE,
1019                                 "<= bdb_substring_candidates: (%s) "
1020                                 "key read failed (%d)\n",
1021                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
1022                         break;
1023                 }
1024
1025                 if( BDB_IDL_IS_ZERO( tmp ) ) {
1026                         Debug( LDAP_DEBUG_TRACE,
1027                                 "<= bdb_substring_candidates: (%s) NULL\n",
1028                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
1029                         BDB_IDL_ZERO( ids );
1030                         break;
1031                 }
1032
1033                 if ( i == 0 ) {
1034                         BDB_IDL_CPY( ids, tmp );
1035                 } else {
1036                         bdb_idl_intersection( ids, tmp );
1037                 }
1038
1039                 if( BDB_IDL_IS_ZERO( ids ) )
1040                         break;
1041         }
1042
1043         ber_bvarray_free_x( keys, op->o_tmpmemctx );
1044
1045         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
1046                 (long) ids[0],
1047                 (long) BDB_IDL_FIRST(ids),
1048                 (long) BDB_IDL_LAST(ids) );
1049         return( rc );
1050 }
1051
1052 static int
1053 inequality_candidates(
1054         Operation *op,
1055         u_int32_t locker,
1056         AttributeAssertion *ava,
1057         ID *ids,
1058         ID *tmp,
1059         int gtorlt )
1060 {
1061         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1062         DB      *db;
1063         int rc;
1064         slap_mask_t mask;
1065         struct berval prefix = {0, NULL};
1066         struct berval *keys = NULL;
1067         MatchingRule *mr;
1068         DBC * cursor = NULL;
1069
1070         Debug( LDAP_DEBUG_TRACE, "=> bdb_inequality_candidates (%s)\n",
1071                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1072
1073         BDB_IDL_ALL( bdb, ids );
1074
1075         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
1076                 &db, &mask, &prefix );
1077
1078         if( rc != LDAP_SUCCESS ) {
1079                 Debug( LDAP_DEBUG_ANY,
1080                         "<= bdb_inequality_candidates: (%s) "
1081                         "index_param failed (%d)\n",
1082                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
1083                 return 0;
1084         }
1085
1086         if ( db == NULL ) {
1087                 Debug( LDAP_DEBUG_ANY,
1088                         "<= bdb_inequality_candidates: (%s) not indexed\n", 
1089                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1090                 return 0;
1091         }
1092
1093         mr = ava->aa_desc->ad_type->sat_equality;
1094         if( !mr ) {
1095                 return 0;
1096         }
1097
1098         if( !mr->smr_filter ) {
1099                 return 0;
1100         }
1101
1102         rc = (mr->smr_filter)(
1103                 LDAP_FILTER_EQUALITY,
1104                 mask,
1105                 ava->aa_desc->ad_type->sat_syntax,
1106                 mr,
1107                 &prefix,
1108                 &ava->aa_value,
1109                 &keys, op->o_tmpmemctx );
1110
1111         if( rc != LDAP_SUCCESS ) {
1112                 Debug( LDAP_DEBUG_TRACE,
1113                         "<= bdb_inequality_candidates: (%s, %s) "
1114                         "MR filter failed (%d)\n",
1115                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
1116                 return 0;
1117         }
1118
1119         if( keys == NULL ) {
1120                 Debug( LDAP_DEBUG_TRACE,
1121                         "<= bdb_inequality_candidates: (%s) no keys\n",
1122                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1123                 return 0;
1124         }
1125
1126         BDB_IDL_ZERO( ids );
1127         while(1) {
1128                 rc = bdb_key_read( op->o_bd, db, locker, &keys[0], tmp, &cursor, gtorlt );
1129
1130                 if( rc == DB_NOTFOUND ) {
1131                         rc = 0;
1132                         break;
1133                 } else if( rc != LDAP_SUCCESS ) {
1134                         Debug( LDAP_DEBUG_TRACE,
1135                                "<= bdb_inequality_candidates: (%s) "
1136                                "key read failed (%d)\n",
1137                                ava->aa_desc->ad_cname.bv_val, rc, 0 );
1138                         break;
1139                 }
1140
1141                 if( BDB_IDL_IS_ZERO( tmp ) ) {
1142                         Debug( LDAP_DEBUG_TRACE,
1143                                "<= bdb_inequality_candidates: (%s) NULL\n", 
1144                                ava->aa_desc->ad_cname.bv_val, 0, 0 );
1145                         break;
1146                 }
1147
1148                 bdb_idl_union( ids, tmp );
1149
1150                 if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 &&
1151                         BDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) {
1152                         cursor->c_close( cursor );
1153                         break;
1154                 }
1155         }
1156         ber_bvarray_free_x( keys, op->o_tmpmemctx );
1157
1158         Debug( LDAP_DEBUG_TRACE,
1159                 "<= bdb_inequality_candidates: id=%ld, first=%ld, last=%ld\n",
1160                 (long) ids[0],
1161                 (long) BDB_IDL_FIRST(ids),
1162                 (long) BDB_IDL_LAST(ids) );
1163         return( rc );
1164 }