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