X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Ffilterindex.c;h=d5a3108d8f59fea2622560960f26aea141c732b4;hb=23116be5aef2880cfbdb998778070c6813f2f130;hp=d6fa3c32a6971dba2196020d774ef53ab5aa4948;hpb=dc0eacd40b625258355eea866d62188e5aa7ce3b;p=openldap diff --git a/servers/slapd/back-bdb/filterindex.c b/servers/slapd/back-bdb/filterindex.c index d6fa3c32a6..d5a3108d8f 100644 --- a/servers/slapd/back-bdb/filterindex.c +++ b/servers/slapd/back-bdb/filterindex.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2005 The OpenLDAP Foundation. + * Copyright 2000-2007 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -21,72 +21,102 @@ #include "back-bdb.h" #include "idl.h" +#ifdef LDAP_COMP_MATCH +#include +#endif static int presence_candidates( Operation *op, + BDB_LOCKER locker, AttributeDescription *desc, ID *ids ); static int equality_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp ); static int inequality_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp, int gtorlt ); static int approx_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp ); static int substring_candidates( Operation *op, + BDB_LOCKER locker, SubstringsAssertion *sub, ID *ids, ID *tmp ); static int list_candidates( Operation *op, + BDB_LOCKER locker, Filter *flist, int ftype, ID *ids, ID *tmp, ID *stack ); -#ifdef LDAP_COMP_MATCH static int ext_candidates( Operation *op, + BDB_LOCKER locker, MatchingRuleAssertion *mra, ID *ids, ID *tmp, ID *stack); +#ifdef LDAP_COMP_MATCH static int comp_candidates ( Operation *op, + BDB_LOCKER locker, MatchingRuleAssertion *mra, ComponentFilter *f, ID *ids, ID *tmp, ID *stack); + +static int +ava_comp_candidates ( + Operation *op, + BDB_LOCKER locker, + AttributeAssertion *ava, + AttributeAliasing *aa, + ID *ids, + ID *tmp, + ID *stack); #endif int bdb_filter_candidates( Operation *op, + BDB_LOCKER locker, 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, locker, 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, locker, f->f_ava, aa, ids, tmp, stack ); + } + else +#endif + { + rc = equality_candidates( op, locker, 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, locker, 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, locker, 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, locker, f->f_ava, ids, tmp, LDAP_FILTER_GE ); else - rc = presence_candidates( op, f->f_ava->aa_desc, ids ); + rc = presence_candidates( op, locker, 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, locker, f->f_ava, ids, tmp, LDAP_FILTER_LE ); else - rc = presence_candidates( op, f->f_ava->aa_desc, ids ); + rc = presence_candidates( op, locker, 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, locker, 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, locker, 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, locker, 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, + BDB_LOCKER locker, 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, locker, 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, + BDB_LOCKER locker, 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, locker, &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, + BDB_LOCKER locker, + 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, locker, &mra, ava->aa_cf, ids, tmp, stack ); +} + static int comp_candidates ( Operation *op, + BDB_LOCKER locker, 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, locker, 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, locker, 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, locker, mra, f->cf_ca, ids, tmp, stack ); break; default: { @@ -407,39 +475,98 @@ comp_candidates ( return( rc ); } +#endif static int ext_candidates( Operation *op, + BDB_LOCKER locker, 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, locker, 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, locker, &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, locker, &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, locker, &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, locker, &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, + BDB_LOCKER locker, 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,7 +578,7 @@ list_candidates( continue; } BDB_IDL_ZERO( save ); - rc = bdb_filter_candidates( op, f, save, tmp, + rc = bdb_filter_candidates( op, locker, f, save, tmp, save+BDB_IDL_UM_SIZE ); if ( rc != 0 ) { @@ -499,6 +626,7 @@ list_candidates( static int presence_candidates( Operation *op, + BDB_LOCKER locker, AttributeDescription *desc, ID *ids ) { @@ -520,19 +648,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 +671,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, locker, &prefix, ids, NULL, 0 ); if( rc == DB_NOTFOUND ) { BDB_IDL_ZERO( ids ); @@ -569,6 +697,7 @@ done: static int equality_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp ) @@ -590,18 +719,18 @@ equality_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_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 +768,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, locker, &keys[i], tmp, NULL, 0 ); if( rc == DB_NOTFOUND ) { BDB_IDL_ZERO( ids ); @@ -685,6 +814,7 @@ equality_candidates( static int approx_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp ) @@ -706,18 +836,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 +890,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, locker, &keys[i], tmp, NULL, 0 ); if( rc == DB_NOTFOUND ) { BDB_IDL_ZERO( ids ); @@ -804,6 +934,7 @@ approx_candidates( static int substring_candidates( Operation *op, + BDB_LOCKER locker, SubstringsAssertion *sub, ID *ids, ID *tmp ) @@ -825,18 +956,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 +1006,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, locker, &keys[i], tmp, NULL, 0 ); if( rc == DB_NOTFOUND ) { BDB_IDL_ZERO( ids ); @@ -919,6 +1050,7 @@ substring_candidates( static int inequality_candidates( Operation *op, + BDB_LOCKER locker, AttributeAssertion *ava, ID *ids, ID *tmp, @@ -926,7 +1058,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 +1073,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 +1123,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, locker, &keys[0], tmp, &cursor, gtorlt ); if( rc == DB_NOTFOUND ) { rc = 0; @@ -1014,9 +1145,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 );