]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
don't dereference NULL pointers
[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-2008 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         DB_TXN *rtxn,
31         AttributeDescription *desc,
32         ID *ids );
33
34 static int equality_candidates(
35         Operation *op,
36         DB_TXN *rtxn,
37         AttributeAssertion *ava,
38         ID *ids,
39         ID *tmp );
40 static int inequality_candidates(
41         Operation *op,
42         DB_TXN *rtxn,
43         AttributeAssertion *ava,
44         ID *ids,
45         ID *tmp,
46         int gtorlt );
47 static int approx_candidates(
48         Operation *op,
49         DB_TXN *rtxn,
50         AttributeAssertion *ava,
51         ID *ids,
52         ID *tmp );
53 static int substring_candidates(
54         Operation *op,
55         DB_TXN *rtxn,
56         SubstringsAssertion *sub,
57         ID *ids,
58         ID *tmp );
59
60 static int list_candidates(
61         Operation *op,
62         DB_TXN *rtxn,
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                 DB_TXN *rtxn,
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         DB_TXN *rtxn,
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                 DB_TXN *rtxn,
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         DB_TXN *rtxn,
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, rtxn, 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, rtxn, f->f_ava, aa, ids, tmp, stack );
150                 }
151                 else
152 #endif
153                 {
154                         rc = equality_candidates( op, rtxn, 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, rtxn, 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, rtxn, 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, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_GE );
174                 else
175                         rc = presence_candidates( op, rtxn, 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, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_LE );
184                 else
185                         rc = presence_candidates( op, rtxn, 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, rtxn, 
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, rtxn,
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, rtxn, 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         DB_TXN *rtxn,
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, rtxn, 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         DB_TXN *rtxn,
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
348         if( !mr ) {
349                 return 0;
350         }
351
352         if( !mr->smr_filter ) {
353                 return 0;
354         }
355
356         rc = (ca->ca_ma_rule->smr_filter)(
357                 LDAP_FILTER_EQUALITY,
358                 cr->cr_indexmask,
359                 sat_syntax,
360                 ca->ca_ma_rule,
361                 &prefix,
362                 &ca->ca_ma_value,
363                 &keys, op->o_tmpmemctx );
364
365         if( rc != LDAP_SUCCESS ) {
366                 return 0;
367         }
368
369         if( keys == NULL ) {
370                 return 0;
371         }
372         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
373                 rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
374
375                 if( rc == DB_NOTFOUND ) {
376                         BDB_IDL_ZERO( ids );
377                         rc = 0;
378                         break;
379                 } else if( rc != LDAP_SUCCESS ) {
380                         break;
381                 }
382
383                 if( BDB_IDL_IS_ZERO( tmp ) ) {
384                         BDB_IDL_ZERO( ids );
385                         break;
386                 }
387
388                 if ( i == 0 ) {
389                         BDB_IDL_CPY( ids, tmp );
390                 } else {
391                         bdb_idl_intersection( ids, tmp );
392                 }
393
394                 if( BDB_IDL_IS_ZERO( ids ) )
395                         break;
396         }
397         ber_bvarray_free_x( keys, op->o_tmpmemctx );
398
399         Debug( LDAP_DEBUG_TRACE,
400                 "<= comp_equality_candidates: id=%ld, first=%ld, last=%ld\n",
401                 (long) ids[0],
402                 (long) BDB_IDL_FIRST(ids),
403                 (long) BDB_IDL_LAST(ids) );
404         return( rc );
405 }
406
407 static int
408 ava_comp_candidates (
409         Operation *op,
410         DB_TXN *rtxn,
411         AttributeAssertion *ava,
412         AttributeAliasing *aa,
413         ID *ids,
414         ID *tmp,
415         ID *stack )
416 {
417         MatchingRuleAssertion mra;
418         
419         mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
420         if ( !mra.ma_rule ) {
421                 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
422                 BDB_IDL_ALL( bdb, ids );
423                 return 0;
424         }
425         mra.ma_desc = aa->aa_aliased_ad;
426         mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
427         
428         return comp_candidates ( op, rtxn, &mra, ava->aa_cf, ids, tmp, stack );
429 }
430
431 static int
432 comp_candidates (
433         Operation *op,
434         DB_TXN *rtxn,
435         MatchingRuleAssertion *mra,
436         ComponentFilter *f,
437         ID *ids,
438         ID *tmp,
439         ID *stack)
440 {
441         int     rc;
442
443         if ( !f ) return LDAP_PROTOCOL_ERROR;
444
445         Debug( LDAP_DEBUG_FILTER, "comp_candidates\n", 0, 0, 0 );
446         switch ( f->cf_choice ) {
447         case SLAPD_FILTER_COMPUTED:
448                 rc = f->cf_result;
449                 break;
450         case LDAP_COMP_FILTER_AND:
451                 rc = comp_list_candidates( op, rtxn, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
452                 break;
453         case LDAP_COMP_FILTER_OR:
454                 rc = comp_list_candidates( op, rtxn, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
455                 break;
456         case LDAP_COMP_FILTER_NOT:
457                 /* No component indexing supported for NOT filter */
458                 Debug( LDAP_DEBUG_FILTER, "\tComponent NOT\n", 0, 0, 0 );
459                 {
460                         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
461                         BDB_IDL_ALL( bdb, ids );
462                 }
463                 rc = LDAP_PROTOCOL_ERROR;
464                 break;
465         case LDAP_COMP_FILTER_ITEM:
466                 rc = comp_equality_candidates( op, rtxn, mra, f->cf_ca, ids, tmp, stack );
467                 break;
468         default:
469                 {
470                         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
471                         BDB_IDL_ALL( bdb, ids );
472                 }
473                 rc = LDAP_PROTOCOL_ERROR;
474         }
475
476         return( rc );
477 }
478 #endif
479
480 static int
481 ext_candidates(
482         Operation *op,
483                 DB_TXN *rtxn,
484         MatchingRuleAssertion *mra,
485         ID *ids,
486         ID *tmp,
487         ID *stack)
488 {
489         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
490
491 #ifdef LDAP_COMP_MATCH
492         /*
493          * Currently Only Component Indexing for componentFilterMatch is supported
494          * Indexing for an extensible filter is not supported yet
495          */
496         if ( mra->ma_cf ) {
497                 return comp_candidates ( op, rtxn, mra, mra->ma_cf, ids, tmp, stack);
498         }
499 #endif
500         if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
501                 int rc;
502                 EntryInfo *ei;
503
504                 BDB_IDL_ZERO( ids );
505                 if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
506                         ei = NULL;
507                         rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
508                         if ( rc == LDAP_SUCCESS )
509                                 bdb_idl_insert( ids, ei->bei_id );
510                         if ( ei )
511                                 bdb_cache_entryinfo_unlock( ei );
512                         return 0;
513                 } else if ( mra->ma_rule && mra->ma_rule->smr_match ==
514                         dnRelativeMatch && dnIsSuffix( &mra->ma_value,
515                                 op->o_bd->be_nsuffix )) {
516                         int scope;
517                         if ( mra->ma_rule == slap_schema.si_mr_dnSuperiorMatch ) {
518                                 struct berval pdn;
519                                 ei = NULL;
520                                 dnParent( &mra->ma_value, &pdn );
521                                 bdb_cache_find_ndn( op, rtxn, &pdn, &ei );
522                                 if ( ei ) {
523                                         bdb_cache_entryinfo_unlock( ei );
524                                         while ( ei && ei->bei_id ) {
525                                                 bdb_idl_insert( ids, ei->bei_id );
526                                                 ei = ei->bei_parent;
527                                         }
528                                 }
529                                 return 0;
530                         }
531                         if ( mra->ma_rule == slap_schema.si_mr_dnSubtreeMatch )
532                                 scope = LDAP_SCOPE_SUBTREE;
533                         else if ( mra->ma_rule == slap_schema.si_mr_dnOneLevelMatch )
534                                 scope = LDAP_SCOPE_ONELEVEL;
535                         else if ( mra->ma_rule == slap_schema.si_mr_dnSubordinateMatch )
536                                 scope = LDAP_SCOPE_SUBORDINATE;
537                         else
538                                 scope = LDAP_SCOPE_BASE;
539                         if ( scope > LDAP_SCOPE_BASE ) {
540                                 ei = NULL;
541                                 rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
542                                 if ( ei )
543                                         bdb_cache_entryinfo_unlock( ei );
544                                 if ( rc == LDAP_SUCCESS ) {
545                                         int sc = op->ors_scope;
546                                         op->ors_scope = scope;
547                                         rc = bdb_dn2idl( op, rtxn, &mra->ma_value, ei, ids,
548                                                 stack );
549                                         op->ors_scope = sc;
550                                 }
551                                 return 0;
552                         }
553                 }
554         }
555
556         BDB_IDL_ALL( bdb, ids );
557         return 0;
558 }
559
560 static int
561 list_candidates(
562         Operation *op,
563         DB_TXN *rtxn,
564         Filter  *flist,
565         int             ftype,
566         ID *ids,
567         ID *tmp,
568         ID *save )
569 {
570         int rc = 0;
571         Filter  *f;
572
573         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
574         for ( f = flist; f != NULL; f = f->f_next ) {
575                 /* ignore precomputed scopes */
576                 if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
577                      f->f_result == LDAP_SUCCESS ) {
578                         continue;
579                 }
580                 BDB_IDL_ZERO( save );
581                 rc = bdb_filter_candidates( op, rtxn, f, save, tmp,
582                         save+BDB_IDL_UM_SIZE );
583
584                 if ( rc != 0 ) {
585                         if ( ftype == LDAP_FILTER_AND ) {
586                                 rc = 0;
587                                 continue;
588                         }
589                         break;
590                 }
591
592                 
593                 if ( ftype == LDAP_FILTER_AND ) {
594                         if ( f == flist ) {
595                                 BDB_IDL_CPY( ids, save );
596                         } else {
597                                 bdb_idl_intersection( ids, save );
598                         }
599                         if( BDB_IDL_IS_ZERO( ids ) )
600                                 break;
601                 } else {
602                         if ( f == flist ) {
603                                 BDB_IDL_CPY( ids, save );
604                         } else {
605                                 bdb_idl_union( ids, save );
606                         }
607                 }
608         }
609
610         if( rc == LDAP_SUCCESS ) {
611                 Debug( LDAP_DEBUG_FILTER,
612                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
613                         (long) ids[0],
614                         (long) BDB_IDL_FIRST(ids),
615                         (long) BDB_IDL_LAST(ids) );
616
617         } else {
618                 Debug( LDAP_DEBUG_FILTER,
619                         "<= bdb_list_candidates: undefined rc=%d\n",
620                         rc, 0, 0 );
621         }
622
623         return rc;
624 }
625
626 static int
627 presence_candidates(
628         Operation *op,
629         DB_TXN *rtxn,
630         AttributeDescription *desc,
631         ID *ids )
632 {
633         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
634         DB *db;
635         int rc;
636         slap_mask_t mask;
637         struct berval prefix = {0, NULL};
638
639         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
640                         desc->ad_cname.bv_val, 0, 0 );
641
642         BDB_IDL_ALL( bdb, ids );
643
644         if( desc == slap_schema.si_ad_objectClass ) {
645                 return 0;
646         }
647
648         rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
649                 &db, &mask, &prefix );
650
651         if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
652                 /* not indexed */
653                 Debug( LDAP_DEBUG_TRACE,
654                         "<= bdb_presence_candidates: (%s) not indexed\n",
655                         desc->ad_cname.bv_val, 0, 0 );
656                 return 0;
657         }
658
659         if( rc != LDAP_SUCCESS ) {
660                 Debug( LDAP_DEBUG_TRACE,
661                         "<= bdb_presence_candidates: (%s) index_param "
662                         "returned=%d\n",
663                         desc->ad_cname.bv_val, rc, 0 );
664                 return 0;
665         }
666
667         if( prefix.bv_val == NULL ) {
668                 Debug( LDAP_DEBUG_TRACE,
669                         "<= bdb_presence_candidates: (%s) no prefix\n",
670                         desc->ad_cname.bv_val, 0, 0 );
671                 return -1;
672         }
673
674         rc = bdb_key_read( op->o_bd, db, rtxn, &prefix, ids, NULL, 0 );
675
676         if( rc == DB_NOTFOUND ) {
677                 BDB_IDL_ZERO( ids );
678                 rc = 0;
679         } else if( rc != LDAP_SUCCESS ) {
680                 Debug( LDAP_DEBUG_TRACE,
681                         "<= bdb_presense_candidates: (%s) "
682                         "key read failed (%d)\n",
683                         desc->ad_cname.bv_val, rc, 0 );
684                 goto done;
685         }
686
687         Debug(LDAP_DEBUG_TRACE,
688                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
689                 (long) ids[0],
690                 (long) BDB_IDL_FIRST(ids),
691                 (long) BDB_IDL_LAST(ids) );
692
693 done:
694         return rc;
695 }
696
697 static int
698 equality_candidates(
699         Operation *op,
700         DB_TXN *rtxn,
701         AttributeAssertion *ava,
702         ID *ids,
703         ID *tmp )
704 {
705         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
706         DB      *db;
707         int i;
708         int rc;
709         slap_mask_t mask;
710         struct berval prefix = {0, NULL};
711         struct berval *keys = NULL;
712         MatchingRule *mr;
713
714         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
715                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
716
717         BDB_IDL_ALL( bdb, ids );
718
719         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
720                 &db, &mask, &prefix );
721
722         if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
723                 Debug( LDAP_DEBUG_ANY,
724                         "<= bdb_equality_candidates: (%s) not indexed\n", 
725                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
726                 return 0;
727         }
728
729         if( rc != LDAP_SUCCESS ) {
730                 Debug( LDAP_DEBUG_ANY,
731                         "<= bdb_equality_candidates: (%s) "
732                         "index_param failed (%d)\n",
733                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
734                 return 0;
735         }
736
737         mr = ava->aa_desc->ad_type->sat_equality;
738         if( !mr ) {
739                 return 0;
740         }
741
742         if( !mr->smr_filter ) {
743                 return 0;
744         }
745
746         rc = (mr->smr_filter)(
747                 LDAP_FILTER_EQUALITY,
748                 mask,
749                 ava->aa_desc->ad_type->sat_syntax,
750                 mr,
751                 &prefix,
752                 &ava->aa_value,
753                 &keys, op->o_tmpmemctx );
754
755         if( rc != LDAP_SUCCESS ) {
756                 Debug( LDAP_DEBUG_TRACE,
757                         "<= bdb_equality_candidates: (%s, %s) "
758                         "MR filter failed (%d)\n",
759                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
760                 return 0;
761         }
762
763         if( keys == NULL ) {
764                 Debug( LDAP_DEBUG_TRACE,
765                         "<= bdb_equality_candidates: (%s) no keys\n",
766                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
767                 return 0;
768         }
769
770         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
771                 rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
772
773                 if( rc == DB_NOTFOUND ) {
774                         BDB_IDL_ZERO( ids );
775                         rc = 0;
776                         break;
777                 } else if( rc != LDAP_SUCCESS ) {
778                         Debug( LDAP_DEBUG_TRACE,
779                                 "<= bdb_equality_candidates: (%s) "
780                                 "key read failed (%d)\n",
781                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
782                         break;
783                 }
784
785                 if( BDB_IDL_IS_ZERO( tmp ) ) {
786                         Debug( LDAP_DEBUG_TRACE,
787                                 "<= bdb_equality_candidates: (%s) NULL\n", 
788                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
789                         BDB_IDL_ZERO( ids );
790                         break;
791                 }
792
793                 if ( i == 0 ) {
794                         BDB_IDL_CPY( ids, tmp );
795                 } else {
796                         bdb_idl_intersection( ids, tmp );
797                 }
798
799                 if( BDB_IDL_IS_ZERO( ids ) )
800                         break;
801         }
802
803         ber_bvarray_free_x( keys, op->o_tmpmemctx );
804
805         Debug( LDAP_DEBUG_TRACE,
806                 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
807                 (long) ids[0],
808                 (long) BDB_IDL_FIRST(ids),
809                 (long) BDB_IDL_LAST(ids) );
810         return( rc );
811 }
812
813
814 static int
815 approx_candidates(
816         Operation *op,
817         DB_TXN *rtxn,
818         AttributeAssertion *ava,
819         ID *ids,
820         ID *tmp )
821 {
822         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
823         DB      *db;
824         int i;
825         int rc;
826         slap_mask_t mask;
827         struct berval prefix = {0, NULL};
828         struct berval *keys = NULL;
829         MatchingRule *mr;
830
831         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
832                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
833
834         BDB_IDL_ALL( bdb, ids );
835
836         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
837                 &db, &mask, &prefix );
838
839         if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
840                 Debug( LDAP_DEBUG_ANY,
841                         "<= bdb_approx_candidates: (%s) not indexed\n",
842                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
843                 return 0;
844         }
845
846         if( rc != LDAP_SUCCESS ) {
847                 Debug( LDAP_DEBUG_ANY,
848                         "<= bdb_approx_candidates: (%s) "
849                         "index_param failed (%d)\n",
850                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
851                 return 0;
852         }
853
854         mr = ava->aa_desc->ad_type->sat_approx;
855         if( !mr ) {
856                 /* no approx matching rule, try equality matching rule */
857                 mr = ava->aa_desc->ad_type->sat_equality;
858         }
859
860         if( !mr ) {
861                 return 0;
862         }
863
864         if( !mr->smr_filter ) {
865                 return 0;
866         }
867
868         rc = (mr->smr_filter)(
869                 LDAP_FILTER_APPROX,
870                 mask,
871                 ava->aa_desc->ad_type->sat_syntax,
872                 mr,
873                 &prefix,
874                 &ava->aa_value,
875                 &keys, op->o_tmpmemctx );
876
877         if( rc != LDAP_SUCCESS ) {
878                 Debug( LDAP_DEBUG_TRACE,
879                         "<= bdb_approx_candidates: (%s, %s) "
880                         "MR filter failed (%d)\n",
881                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
882                 return 0;
883         }
884
885         if( keys == NULL ) {
886                 Debug( LDAP_DEBUG_TRACE,
887                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
888                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
889                 return 0;
890         }
891
892         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
893                 rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
894
895                 if( rc == DB_NOTFOUND ) {
896                         BDB_IDL_ZERO( ids );
897                         rc = 0;
898                         break;
899                 } else if( rc != LDAP_SUCCESS ) {
900                         Debug( LDAP_DEBUG_TRACE,
901                                 "<= bdb_approx_candidates: (%s) "
902                                 "key read failed (%d)\n",
903                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
904                         break;
905                 }
906
907                 if( BDB_IDL_IS_ZERO( tmp ) ) {
908                         Debug( LDAP_DEBUG_TRACE,
909                                 "<= bdb_approx_candidates: (%s) NULL\n",
910                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
911                         BDB_IDL_ZERO( ids );
912                         break;
913                 }
914
915                 if ( i == 0 ) {
916                         BDB_IDL_CPY( ids, tmp );
917                 } else {
918                         bdb_idl_intersection( ids, tmp );
919                 }
920
921                 if( BDB_IDL_IS_ZERO( ids ) )
922                         break;
923         }
924
925         ber_bvarray_free_x( keys, op->o_tmpmemctx );
926
927         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
928                 (long) ids[0],
929                 (long) BDB_IDL_FIRST(ids),
930                 (long) BDB_IDL_LAST(ids) );
931         return( rc );
932 }
933
934 static int
935 substring_candidates(
936         Operation *op,
937         DB_TXN *rtxn,
938         SubstringsAssertion     *sub,
939         ID *ids,
940         ID *tmp )
941 {
942         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
943         DB      *db;
944         int i;
945         int rc;
946         slap_mask_t mask;
947         struct berval prefix = {0, NULL};
948         struct berval *keys = NULL;
949         MatchingRule *mr;
950
951         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
952                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
953
954         BDB_IDL_ALL( bdb, ids );
955
956         rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
957                 &db, &mask, &prefix );
958
959         if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
960                 Debug( LDAP_DEBUG_ANY,
961                         "<= bdb_substring_candidates: (%s) not indexed\n",
962                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
963                 return 0;
964         }
965
966         if( rc != LDAP_SUCCESS ) {
967                 Debug( LDAP_DEBUG_ANY,
968                         "<= bdb_substring_candidates: (%s) "
969                         "index_param failed (%d)\n",
970                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
971                 return 0;
972         }
973
974         mr = sub->sa_desc->ad_type->sat_substr;
975
976         if( !mr ) {
977                 return 0;
978         }
979
980         if( !mr->smr_filter ) {
981                 return 0;
982         }
983
984         rc = (mr->smr_filter)(
985                 LDAP_FILTER_SUBSTRINGS,
986                 mask,
987                 sub->sa_desc->ad_type->sat_syntax,
988                 mr,
989                 &prefix,
990                 sub,
991                 &keys, op->o_tmpmemctx );
992
993         if( rc != LDAP_SUCCESS ) {
994                 Debug( LDAP_DEBUG_TRACE,
995                         "<= bdb_substring_candidates: (%s) "
996                         "MR filter failed (%d)\n",
997                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
998                 return 0;
999         }
1000
1001         if( keys == NULL ) {
1002                 Debug( LDAP_DEBUG_TRACE,
1003                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
1004                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
1005                 return 0;
1006         }
1007
1008         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
1009                 rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
1010
1011                 if( rc == DB_NOTFOUND ) {
1012                         BDB_IDL_ZERO( ids );
1013                         rc = 0;
1014                         break;
1015                 } else if( rc != LDAP_SUCCESS ) {
1016                         Debug( LDAP_DEBUG_TRACE,
1017                                 "<= bdb_substring_candidates: (%s) "
1018                                 "key read failed (%d)\n",
1019                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
1020                         break;
1021                 }
1022
1023                 if( BDB_IDL_IS_ZERO( tmp ) ) {
1024                         Debug( LDAP_DEBUG_TRACE,
1025                                 "<= bdb_substring_candidates: (%s) NULL\n",
1026                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
1027                         BDB_IDL_ZERO( ids );
1028                         break;
1029                 }
1030
1031                 if ( i == 0 ) {
1032                         BDB_IDL_CPY( ids, tmp );
1033                 } else {
1034                         bdb_idl_intersection( ids, tmp );
1035                 }
1036
1037                 if( BDB_IDL_IS_ZERO( ids ) )
1038                         break;
1039         }
1040
1041         ber_bvarray_free_x( keys, op->o_tmpmemctx );
1042
1043         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
1044                 (long) ids[0],
1045                 (long) BDB_IDL_FIRST(ids),
1046                 (long) BDB_IDL_LAST(ids) );
1047         return( rc );
1048 }
1049
1050 static int
1051 inequality_candidates(
1052         Operation *op,
1053         DB_TXN *rtxn,
1054         AttributeAssertion *ava,
1055         ID *ids,
1056         ID *tmp,
1057         int gtorlt )
1058 {
1059         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
1060         DB      *db;
1061         int rc;
1062         slap_mask_t mask;
1063         struct berval prefix = {0, NULL};
1064         struct berval *keys = NULL;
1065         MatchingRule *mr;
1066         DBC * cursor = NULL;
1067
1068         Debug( LDAP_DEBUG_TRACE, "=> bdb_inequality_candidates (%s)\n",
1069                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1070
1071         BDB_IDL_ALL( bdb, ids );
1072
1073         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
1074                 &db, &mask, &prefix );
1075
1076         if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
1077                 Debug( LDAP_DEBUG_ANY,
1078                         "<= bdb_inequality_candidates: (%s) not indexed\n", 
1079                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1080                 return 0;
1081         }
1082
1083         if( rc != LDAP_SUCCESS ) {
1084                 Debug( LDAP_DEBUG_ANY,
1085                         "<= bdb_inequality_candidates: (%s) "
1086                         "index_param failed (%d)\n",
1087                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
1088                 return 0;
1089         }
1090
1091         mr = ava->aa_desc->ad_type->sat_equality;
1092         if( !mr ) {
1093                 return 0;
1094         }
1095
1096         if( !mr->smr_filter ) {
1097                 return 0;
1098         }
1099
1100         rc = (mr->smr_filter)(
1101                 LDAP_FILTER_EQUALITY,
1102                 mask,
1103                 ava->aa_desc->ad_type->sat_syntax,
1104                 mr,
1105                 &prefix,
1106                 &ava->aa_value,
1107                 &keys, op->o_tmpmemctx );
1108
1109         if( rc != LDAP_SUCCESS ) {
1110                 Debug( LDAP_DEBUG_TRACE,
1111                         "<= bdb_inequality_candidates: (%s, %s) "
1112                         "MR filter failed (%d)\n",
1113                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
1114                 return 0;
1115         }
1116
1117         if( keys == NULL ) {
1118                 Debug( LDAP_DEBUG_TRACE,
1119                         "<= bdb_inequality_candidates: (%s) no keys\n",
1120                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
1121                 return 0;
1122         }
1123
1124         BDB_IDL_ZERO( ids );
1125         while(1) {
1126                 rc = bdb_key_read( op->o_bd, db, rtxn, &keys[0], tmp, &cursor, gtorlt );
1127
1128                 if( rc == DB_NOTFOUND ) {
1129                         rc = 0;
1130                         break;
1131                 } else if( rc != LDAP_SUCCESS ) {
1132                         Debug( LDAP_DEBUG_TRACE,
1133                                "<= bdb_inequality_candidates: (%s) "
1134                                "key read failed (%d)\n",
1135                                ava->aa_desc->ad_cname.bv_val, rc, 0 );
1136                         break;
1137                 }
1138
1139                 if( BDB_IDL_IS_ZERO( tmp ) ) {
1140                         Debug( LDAP_DEBUG_TRACE,
1141                                "<= bdb_inequality_candidates: (%s) NULL\n", 
1142                                ava->aa_desc->ad_cname.bv_val, 0, 0 );
1143                         break;
1144                 }
1145
1146                 bdb_idl_union( ids, tmp );
1147
1148                 if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 &&
1149                         BDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) {
1150                         cursor->c_close( cursor );
1151                         break;
1152                 }
1153         }
1154         ber_bvarray_free_x( keys, op->o_tmpmemctx );
1155
1156         Debug( LDAP_DEBUG_TRACE,
1157                 "<= bdb_inequality_candidates: id=%ld, first=%ld, last=%ld\n",
1158                 (long) ids[0],
1159                 (long) BDB_IDL_FIRST(ids),
1160                 (long) BDB_IDL_LAST(ids) );
1161         return( rc );
1162 }