]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/filterindex.c
implement support for selective iteration in slaptools (ITS#6442)
[openldap] / servers / slapd / back-bdb / filterindex.c
index 64514cc86237ce678ce10294cf9f2b129d565074..29fd0096c40d1440c0292a488ce05a973f5e0acf 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2004 The OpenLDAP Foundation.
+ * Copyright 2000-2009 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 #include "back-bdb.h"
 #include "idl.h"
+#ifdef LDAP_COMP_MATCH
+#include <component.h>
+#endif
 
 static int presence_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeDescription *desc,
        ID *ids );
 
 static int equality_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp );
 static int inequality_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp,
        int gtorlt );
 static int approx_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp );
 static int substring_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        SubstringsAssertion *sub,
        ID *ids,
        ID *tmp );
 
 static int list_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        Filter *flist,
        int ftype,
        ID *ids,
        ID *tmp,
        ID *stack );
 
-#ifdef LDAP_COMP_MATCH
 static int
 ext_candidates(
         Operation *op,
+               DB_TXN *rtxn,
         MatchingRuleAssertion *mra,
         ID *ids,
         ID *tmp,
         ID *stack);
 
+#ifdef LDAP_COMP_MATCH
 static int
 comp_candidates (
        Operation *op,
+       DB_TXN *rtxn,
        MatchingRuleAssertion *mra,
        ComponentFilter *f,
        ID *ids,
        ID *tmp,
        ID *stack);
+
+static int
+ava_comp_candidates (
+               Operation *op,
+               DB_TXN *rtxn,
+               AttributeAssertion *ava,
+               AttributeAliasing *aa,
+               ID *ids,
+               ID *tmp,
+               ID *stack);
 #endif
 
 int
 bdb_filter_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        Filter  *f,
        ID *ids,
        ID *tmp,
        ID *stack )
 {
        int rc = 0;
+#ifdef LDAP_COMP_MATCH
+       AttributeAliasing *aa;
+#endif
        Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
 
+       if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
+               BDB_IDL_ZERO( ids );
+               goto out;
+       }
+
        switch ( f->f_choice ) {
        case SLAPD_FILTER_COMPUTED:
                switch( f->f_result ) {
@@ -109,42 +139,50 @@ bdb_filter_candidates(
                break;
        case LDAP_FILTER_PRESENT:
                Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
-               rc = presence_candidates( op, f->f_desc, ids );
+               rc = presence_candidates( op, rtxn, f->f_desc, ids );
                break;
 
        case LDAP_FILTER_EQUALITY:
                Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
-               rc = equality_candidates( op, f->f_ava, ids, tmp );
+#ifdef LDAP_COMP_MATCH
+               if ( is_aliased_attribute && ( aa = is_aliased_attribute ( f->f_ava->aa_desc ) ) ) {
+                       rc = ava_comp_candidates ( op, rtxn, f->f_ava, aa, ids, tmp, stack );
+               }
+               else
+#endif
+               {
+                       rc = equality_candidates( op, rtxn, f->f_ava, ids, tmp );
+               }
                break;
 
        case LDAP_FILTER_APPROX:
                Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
-               rc = approx_candidates( op, f->f_ava, ids, tmp );
+               rc = approx_candidates( op, rtxn, f->f_ava, ids, tmp );
                break;
 
        case LDAP_FILTER_SUBSTRINGS:
                Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
-               rc = substring_candidates( op, f->f_sub, ids, tmp );
+               rc = substring_candidates( op, rtxn, f->f_sub, ids, tmp );
                break;
 
        case LDAP_FILTER_GE:
                /* if no GE index, use pres */
                Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
                if( f->f_ava->aa_desc->ad_type->sat_ordering &&
-                       ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage && SLAP_MR_ORDERED_INDEX ) )
-                       rc = inequality_candidates( op, f->f_ava, ids, tmp, LDAP_FILTER_GE );
+                       ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
+                       rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_GE );
                else
-                       rc = presence_candidates( op, f->f_ava->aa_desc, ids );
+                       rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
                break;
 
        case LDAP_FILTER_LE:
                /* if no LE index, use pres */
                Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
                if( f->f_ava->aa_desc->ad_type->sat_ordering &&
-                       ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage && SLAP_MR_ORDERED_INDEX ) )
-                       rc = inequality_candidates( op, f->f_ava, ids, tmp, LDAP_FILTER_LE );
+                       ( f->f_ava->aa_desc->ad_type->sat_ordering->smr_usage & SLAP_MR_ORDERED_INDEX ) )
+                       rc = inequality_candidates( op, rtxn, f->f_ava, ids, tmp, LDAP_FILTER_LE );
                else
-                       rc = presence_candidates( op, f->f_ava->aa_desc, ids );
+                       rc = presence_candidates( op, rtxn, f->f_ava->aa_desc, ids );
                break;
 
        case LDAP_FILTER_NOT:
@@ -157,21 +195,19 @@ bdb_filter_candidates(
 
        case LDAP_FILTER_AND:
                Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
-               rc = list_candidates( op, 
+               rc = list_candidates( op, rtxn, 
                        f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
                break;
 
        case LDAP_FILTER_OR:
                Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
-               rc = list_candidates( op, 
+               rc = list_candidates( op, rtxn,
                        f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
                break;
-#ifdef LDAP_COMP_MATCH
        case LDAP_FILTER_EXT:
                 Debug( LDAP_DEBUG_FILTER, "\tEXT\n", 0, 0, 0 );
-                rc = ext_candidates( op, f->f_mra, ids, tmp, stack );
+                rc = ext_candidates( op, rtxn, f->f_mra, ids, tmp, stack );
                 break;
-#endif
        default:
                Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
                        (unsigned long) f->f_choice, 0, 0 );
@@ -181,6 +217,7 @@ bdb_filter_candidates(
                }
        }
 
+out:
        Debug( LDAP_DEBUG_FILTER,
                "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
                (long) ids[0],
@@ -194,6 +231,7 @@ bdb_filter_candidates(
 static int
 comp_list_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        MatchingRuleAssertion* mra,
        ComponentFilter *flist,
        int     ftype,
@@ -201,7 +239,6 @@ comp_list_candidates(
        ID *tmp,
        ID *save )
 {
-       struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        int rc = 0;
        ComponentFilter *f;
 
@@ -213,7 +250,7 @@ comp_list_candidates(
                        continue;
                }
                BDB_IDL_ZERO( save );
-               rc = comp_candidates( op, mra, f, save, tmp, save+BDB_IDL_UM_SIZE );
+               rc = comp_candidates( op, rtxn, mra, f, save, tmp, save+BDB_IDL_UM_SIZE );
 
                if ( rc != 0 ) {
                        if ( ftype == LDAP_COMP_FILTER_AND ) {
@@ -259,6 +296,7 @@ comp_list_candidates(
 static int
 comp_equality_candidates (
         Operation *op,
+       DB_TXN *rtxn,
         MatchingRuleAssertion *mra,
        ComponentAssertion *ca,
         ID *ids,
@@ -275,12 +313,20 @@ comp_equality_candidates (
         MatchingRule *mr = mra->ma_rule;
         Syntax *sat_syntax;
        ComponentReference* cr_list, *cr;
+       AttrInfo *ai;
 
         BDB_IDL_ALL( bdb, ids );
 
-       bdb_attr_comp_ref ( op->o_bd->be_private, mra->ma_desc, &cr_list );
-       if( !cr_list || !ca->ca_comp_ref )
+       if ( !ca->ca_comp_ref )
                return 0;
+
+       ai = bdb_attr_mask( op->o_bd->be_private, mra->ma_desc );
+       if( ai ) {
+               cr_list = ai->ai_cr;
+       }
+       else {
+               return 0;
+       }
        /* find a component reference to be indexed */
        sat_syntax = ca->ca_ma_rule->smr_syntax;
        for ( cr = cr_list ; cr ; cr = cr->cr_next ) {
@@ -298,9 +344,6 @@ comp_equality_candidates (
         if( rc != LDAP_SUCCESS ) {
                 return 0;
         }
-        if ( db == NULL ) {
-                return 0;
-        }
 
         if( !mr ) {
                 return 0;
@@ -327,7 +370,7 @@ comp_equality_candidates (
                 return 0;
         }
         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-                rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp, NULL, 0 );
+                rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
 
                 if( rc == DB_NOTFOUND ) {
                         BDB_IDL_ZERO( ids );
@@ -361,9 +404,34 @@ comp_equality_candidates (
         return( rc );
 }
 
+static int
+ava_comp_candidates (
+       Operation *op,
+       DB_TXN *rtxn,
+       AttributeAssertion *ava,
+       AttributeAliasing *aa,
+       ID *ids,
+       ID *tmp,
+       ID *stack )
+{
+       MatchingRuleAssertion mra;
+       
+       mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
+       if ( !mra.ma_rule ) {
+               struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
+               BDB_IDL_ALL( bdb, ids );
+               return 0;
+       }
+       mra.ma_desc = aa->aa_aliased_ad;
+       mra.ma_rule = ava->aa_desc->ad_type->sat_equality;
+       
+       return comp_candidates ( op, rtxn, &mra, ava->aa_cf, ids, tmp, stack );
+}
+
 static int
 comp_candidates (
        Operation *op,
+       DB_TXN *rtxn,
        MatchingRuleAssertion *mra,
        ComponentFilter *f,
        ID *ids,
@@ -380,10 +448,10 @@ comp_candidates (
                rc = f->cf_result;
                break;
        case LDAP_COMP_FILTER_AND:
-               rc = comp_list_candidates( op, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
+               rc = comp_list_candidates( op, rtxn, mra, f->cf_and, LDAP_COMP_FILTER_AND, ids, tmp, stack );
                break;
        case LDAP_COMP_FILTER_OR:
-               rc = comp_list_candidates( op, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
+               rc = comp_list_candidates( op, rtxn, mra, f->cf_or, LDAP_COMP_FILTER_OR, ids, tmp, stack );
                break;
        case LDAP_COMP_FILTER_NOT:
                /* No component indexing supported for NOT filter */
@@ -395,7 +463,7 @@ comp_candidates (
                rc = LDAP_PROTOCOL_ERROR;
                break;
        case LDAP_COMP_FILTER_ITEM:
-               rc = comp_equality_candidates( op, mra, f->cf_ca, ids, tmp, stack );
+               rc = comp_equality_candidates( op, rtxn, mra, f->cf_ca, ids, tmp, stack );
                break;
        default:
                {
@@ -407,39 +475,98 @@ comp_candidates (
 
        return( rc );
 }
+#endif
 
 static int
 ext_candidates(
         Operation *op,
+               DB_TXN *rtxn,
         MatchingRuleAssertion *mra,
         ID *ids,
         ID *tmp,
         ID *stack)
 {
+       struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
+
+#ifdef LDAP_COMP_MATCH
        /*
         * Currently Only Component Indexing for componentFilterMatch is supported
         * Indexing for an extensible filter is not supported yet
         */
-       if ( !mra->ma_cf ) {
-               struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
-               BDB_IDL_ALL( bdb, ids );
-               return 0;
+       if ( mra->ma_cf ) {
+               return comp_candidates ( op, rtxn, mra, mra->ma_cf, ids, tmp, stack);
+       }
+#endif
+       if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
+               int rc;
+               EntryInfo *ei;
+
+               BDB_IDL_ZERO( ids );
+               if ( mra->ma_rule == slap_schema.si_mr_distinguishedNameMatch ) {
+                       ei = NULL;
+                       rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
+                       if ( rc == LDAP_SUCCESS )
+                               bdb_idl_insert( ids, ei->bei_id );
+                       if ( ei )
+                               bdb_cache_entryinfo_unlock( ei );
+                       return 0;
+               } else if ( mra->ma_rule && mra->ma_rule->smr_match ==
+                       dnRelativeMatch && dnIsSuffix( &mra->ma_value,
+                               op->o_bd->be_nsuffix )) {
+                       int scope;
+                       if ( mra->ma_rule == slap_schema.si_mr_dnSuperiorMatch ) {
+                               struct berval pdn;
+                               ei = NULL;
+                               dnParent( &mra->ma_value, &pdn );
+                               bdb_cache_find_ndn( op, rtxn, &pdn, &ei );
+                               if ( ei ) {
+                                       bdb_cache_entryinfo_unlock( ei );
+                                       while ( ei && ei->bei_id ) {
+                                               bdb_idl_insert( ids, ei->bei_id );
+                                               ei = ei->bei_parent;
+                                       }
+                               }
+                               return 0;
+                       }
+                       if ( mra->ma_rule == slap_schema.si_mr_dnSubtreeMatch )
+                               scope = LDAP_SCOPE_SUBTREE;
+                       else if ( mra->ma_rule == slap_schema.si_mr_dnOneLevelMatch )
+                               scope = LDAP_SCOPE_ONELEVEL;
+                       else if ( mra->ma_rule == slap_schema.si_mr_dnSubordinateMatch )
+                               scope = LDAP_SCOPE_SUBORDINATE;
+                       else
+                               scope = LDAP_SCOPE_BASE;
+                       if ( scope > LDAP_SCOPE_BASE ) {
+                               ei = NULL;
+                               rc = bdb_cache_find_ndn( op, rtxn, &mra->ma_value, &ei );
+                               if ( ei )
+                                       bdb_cache_entryinfo_unlock( ei );
+                               if ( rc == LDAP_SUCCESS ) {
+                                       int sc = op->ors_scope;
+                                       op->ors_scope = scope;
+                                       rc = bdb_dn2idl( op, rtxn, &mra->ma_value, ei, ids,
+                                               stack );
+                                       op->ors_scope = sc;
+                               }
+                               return 0;
+                       }
+               }
        }
 
-       return comp_candidates ( op, mra, mra->ma_cf, ids, tmp, stack);
+       BDB_IDL_ALL( bdb, ids );
+       return 0;
 }
-#endif
 
 static int
 list_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        Filter  *flist,
        int             ftype,
        ID *ids,
        ID *tmp,
        ID *save )
 {
-       struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        int rc = 0;
        Filter  *f;
 
@@ -451,10 +578,13 @@ list_candidates(
                        continue;
                }
                BDB_IDL_ZERO( save );
-               rc = bdb_filter_candidates( op, f, save, tmp,
+               rc = bdb_filter_candidates( op, rtxn, f, save, tmp,
                        save+BDB_IDL_UM_SIZE );
 
                if ( rc != 0 ) {
+                       if ( rc == DB_LOCK_DEADLOCK )
+                               return rc;
+
                        if ( ftype == LDAP_FILTER_AND ) {
                                rc = 0;
                                continue;
@@ -499,6 +629,7 @@ list_candidates(
 static int
 presence_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeDescription *desc,
        ID *ids )
 {
@@ -520,19 +651,19 @@ presence_candidates(
        rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
+               /* not indexed */
                Debug( LDAP_DEBUG_TRACE,
-                       "<= bdb_presence_candidates: (%s) index_param "
-                       "returned=%d\n",
-                       desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_presence_candidates: (%s) not indexed\n",
+                       desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if( db == NULL ) {
-               /* not indexed */
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_TRACE,
-                       "<= bdb_presence_candidates: (%s) not indexed\n",
-                       desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_presence_candidates: (%s) index_param "
+                       "returned=%d\n",
+                       desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -543,7 +674,7 @@ presence_candidates(
                return -1;
        }
 
-       rc = bdb_key_read( op->o_bd, db, NULL, &prefix, ids, NULL, 0 );
+       rc = bdb_key_read( op->o_bd, db, rtxn, &prefix, ids, NULL, 0 );
 
        if( rc == DB_NOTFOUND ) {
                BDB_IDL_ZERO( ids );
@@ -569,6 +700,7 @@ done:
 static int
 equality_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp )
@@ -585,23 +717,37 @@ equality_candidates(
        Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
                        ava->aa_desc->ad_cname.bv_val, 0, 0 );
 
+       if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
+               EntryInfo *ei = NULL;
+               rc = bdb_cache_find_ndn( op, rtxn, &ava->aa_value, &ei );
+               if ( rc == LDAP_SUCCESS ) {
+                       /* exactly one ID can match */
+                       ids[0] = 1;
+                       ids[1] = ei->bei_id;
+               }
+               if ( ei ) {
+                       bdb_cache_entryinfo_unlock( ei );
+               }
+               return rc;
+       }
+
        BDB_IDL_ALL( bdb, ids );
 
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_equality_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_equality_candidates: (%s) not indexed\n", 
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_equality_candidates: (%s) not indexed\n", 
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_equality_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -639,7 +785,7 @@ equality_candidates(
        }
 
        for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-               rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp, NULL, 0 );
+               rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
 
                if( rc == DB_NOTFOUND ) {
                        BDB_IDL_ZERO( ids );
@@ -685,6 +831,7 @@ equality_candidates(
 static int
 approx_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp )
@@ -706,18 +853,18 @@ approx_candidates(
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_approx_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_approx_candidates: (%s) not indexed\n",
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_approx_candidates: (%s) not indexed\n",
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_approx_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -760,7 +907,7 @@ approx_candidates(
        }
 
        for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-               rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp, NULL, 0 );
+               rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
 
                if( rc == DB_NOTFOUND ) {
                        BDB_IDL_ZERO( ids );
@@ -804,6 +951,7 @@ approx_candidates(
 static int
 substring_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        SubstringsAssertion     *sub,
        ID *ids,
        ID *tmp )
@@ -825,18 +973,18 @@ substring_candidates(
        rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_substring_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       sub->sa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_substring_candidates: (%s) not indexed\n",
+                       sub->sa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_substring_candidates: (%s) not indexed\n",
-                       sub->sa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_substring_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       sub->sa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -875,7 +1023,7 @@ substring_candidates(
        }
 
        for ( i= 0; keys[i].bv_val != NULL; i++ ) {
-               rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp, NULL, 0 );
+               rc = bdb_key_read( op->o_bd, db, rtxn, &keys[i], tmp, NULL, 0 );
 
                if( rc == DB_NOTFOUND ) {
                        BDB_IDL_ZERO( ids );
@@ -919,6 +1067,7 @@ substring_candidates(
 static int
 inequality_candidates(
        Operation *op,
+       DB_TXN *rtxn,
        AttributeAssertion *ava,
        ID *ids,
        ID *tmp,
@@ -926,7 +1075,6 @@ inequality_candidates(
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        DB      *db;
-       int i;
        int rc;
        slap_mask_t mask;
        struct berval prefix = {0, NULL};
@@ -942,18 +1090,18 @@ inequality_candidates(
        rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
                &db, &mask, &prefix );
 
-       if( rc != LDAP_SUCCESS ) {
+       if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_inequality_candidates: (%s) "
-                       "index_param failed (%d)\n",
-                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
+                       "<= bdb_inequality_candidates: (%s) not indexed\n", 
+                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
                return 0;
        }
 
-       if ( db == NULL ) {
+       if( rc != LDAP_SUCCESS ) {
                Debug( LDAP_DEBUG_ANY,
-                       "<= bdb_inequality_candidates: (%s) not indexed\n", 
-                       ava->aa_desc->ad_cname.bv_val, 0, 0 );
+                       "<= bdb_inequality_candidates: (%s) "
+                       "index_param failed (%d)\n",
+                       ava->aa_desc->ad_cname.bv_val, rc, 0 );
                return 0;
        }
 
@@ -992,7 +1140,7 @@ inequality_candidates(
 
        BDB_IDL_ZERO( ids );
        while(1) {
-               rc = bdb_key_read( op->o_bd, db, NULL, &keys[0], tmp, &cursor, gtorlt );
+               rc = bdb_key_read( op->o_bd, db, rtxn, &keys[0], tmp, &cursor, gtorlt );
 
                if( rc == DB_NOTFOUND ) {
                        rc = 0;
@@ -1014,9 +1162,11 @@ inequality_candidates(
 
                bdb_idl_union( ids, tmp );
 
-               if( BDB_IDL_IS_ZERO( ids ) )
+               if( op->ors_limit && op->ors_limit->lms_s_unchecked != -1 &&
+                       BDB_IDL_N( ids ) >= (unsigned) op->ors_limit->lms_s_unchecked ) {
+                       cursor->c_close( cursor );
                        break;
-               i++;
+               }
        }
        ber_bvarray_free_x( keys, op->o_tmpmemctx );