/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 2008 The OpenLDAP Foundation.
+ * Copyright 2008-2012 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
}
static int ndb_filter_set( Operation *op, struct ndb_info *ni, Filter *f, int indexed,
- NdbIndexScanOperation *scan, NdbScanFilter **sf, int *bounds )
+ NdbIndexScanOperation *scan, NdbScanFilter *sf, int *bounds )
{
AttributeDescription *ad = NULL;
ber_tag_t choice = f->f_choice;
scan->end_of_bound( (*bounds)++ );
}
case LDAP_FILTER_AND:
+ if ( sf ) {
+ sf->begin( choice == LDAP_FILTER_OR ? NdbScanFilter::OR : NdbScanFilter::AND );
+ }
for ( f = f->f_list; f; f=f->f_next ) {
if ( ndb_filter_set( op, ni, f, indexed, scan, sf, bounds ))
return -1;
}
+ if ( sf ) {
+ sf->end();
+ }
break;
case LDAP_FILTER_PRESENT:
ad = f->f_desc;
}
ai = ndb_ai_find( ni, ad->ad_type );
if ( ai ) {
+ int rc;
if ( ai->na_flag & NDB_INFO_INDEX ) {
char *buf, *ptr;
NdbIndexScanOperation::BoundType bt;
- int rc;
switch(choice) {
case LDAP_FILTER_PRESENT:
default:
break;
}
- } else {
+ } else if ( sf ) {
+ char *buf, *ptr;
+ NdbScanFilter::BinaryCondition bc;
+
+ switch(choice) {
+ case LDAP_FILTER_PRESENT:
+ rc = sf->isnotnull( ai->na_column );
+ break;
+ case LDAP_FILTER_EQUALITY:
+ case LDAP_FILTER_APPROX:
+ bc = NdbScanFilter::COND_EQ;
+ goto setf;
+ case LDAP_FILTER_GE:
+ bc = NdbScanFilter::COND_GE;
+ goto setf;
+ case LDAP_FILTER_LE:
+ bc = NdbScanFilter::COND_LE;
+ setf:
+ rc = sf->cmp( bc, ai->na_column, f->f_av_value.bv_val, f->f_av_value.bv_len );
+ break;
+ case LDAP_FILTER_SUBSTRINGS:
+ rc = 0;
+ if ( f->f_sub_initial.bv_val )
+ rc += f->f_sub_initial.bv_len + 1;
+ if ( f->f_sub_any ) {
+ int i;
+ if ( !rc ) rc++;
+ for (i=0; f->f_sub_any[i].bv_val; i++)
+ rc += f->f_sub_any[i].bv_len + 1;
+ }
+ if ( f->f_sub_final.bv_val ) {
+ if ( !rc ) rc++;
+ rc += f->f_sub_final.bv_len;
+ }
+ buf = (char *)op->o_tmpalloc( rc+1, op->o_tmpmemctx );
+ ptr = buf;
+ if ( f->f_sub_initial.bv_val ) {
+ memcpy( ptr, f->f_sub_initial.bv_val, f->f_sub_initial.bv_len );
+ ptr += f->f_sub_initial.bv_len;
+ *ptr++ = '%';
+ }
+ if ( f->f_sub_any ) {
+ int i;
+ if ( ptr == buf )
+ *ptr++ = '%';
+ for (i=0; f->f_sub_any[i].bv_val; i++) {
+ memcpy( ptr, f->f_sub_any[i].bv_val, f->f_sub_any[i].bv_len );
+ ptr += f->f_sub_any[i].bv_len;
+ *ptr++ = '%';
+ }
+ }
+ if ( f->f_sub_final.bv_val ) {
+ if ( ptr == buf )
+ *ptr++ = '%';
+ memcpy( ptr, f->f_sub_final.bv_val, f->f_sub_final.bv_len );
+ ptr += f->f_sub_final.bv_len;
+ }
+ *ptr = '\0';
+ rc = sf->cmp( NdbScanFilter::COND_LIKE, ai->na_column, buf, ptr - buf );
+ op->o_tmpfree( buf, op->o_tmpmemctx );
+ break;
+ }
}
}
}
NdbIndexScanOperation *scan;
NdbIndexOperation *ixop;
NdbScanFilter *sf = NULL;
- struct berval *ocs, matched;
+ struct berval *ocs;
NdbRecAttr *scanID, *scanOC, *scanDN[NDB_MAX_RDNS];
char dnBuf[2048], *ptr;
NdbRdns rdns;
int i, rc, bounds;
Entry e = {0};
Uint64 eid;
+ time_t stoptime;
+ int manageDSAit;
+
+ stoptime = op->o_time + op->ors_tlimit;
+ manageDSAit = get_manageDSAit( op );
myTable = myDict->getTable( oci->no_table.bv_val );
if ( indexed ) {
scan = txn->getNdbIndexScanOperation( INDEX_NAME, DN2ID_TABLE );
if ( !scan )
return LDAP_OTHER;
+ scan->readTuples( NdbOperation::LM_CommittedRead );
} else {
myIndex = myDict->getIndex( "eid$unique", DN2ID_TABLE );
if ( !myIndex ) {
scan = (NdbIndexScanOperation *)txn->getNdbScanOperation( myTable );
if ( !scan )
return LDAP_OTHER;
+ scan->readTuples( NdbOperation::LM_CommittedRead );
+#if 1
sf = new NdbScanFilter(scan);
if ( !sf )
return LDAP_OTHER;
goto leave;
}
}
+#endif
}
- scan->readTuples( NdbOperation::LM_CommittedRead );
bounds = 0;
- rc = ndb_filter_set( op, ni, op->ors_filter, indexed, scan, &sf, &bounds );
+ rc = ndb_filter_set( op, ni, op->ors_filter, indexed, scan, sf, &bounds );
if ( rc )
goto leave;
+ if ( sf ) sf->end();
scanID = scan->getValue( EID_COLUMN, idbuf );
if ( indexed ) {
e.e_name.bv_val = dnBuf;
NA.e = &e;
NA.ndb = ndb;
- while ( scan->nextResult() == 0 ) {
+ while ( scan->nextResult( true, true ) == 0 ) {
NdbTransaction *tx2;
- if ( op->o_abandon )
+ if ( op->o_abandon ) {
+ rs->sr_err = SLAPD_ABANDON;
+ break;
+ }
+ if ( slapd_shutdown ) {
+ rs->sr_err = LDAP_UNAVAILABLE;
break;
+ }
+ if ( op->ors_tlimit != SLAP_NO_LIMIT &&
+ slap_get_time() > stoptime ) {
+ rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
+ break;
+ }
+
eid = scanID->u_64_value();
e.e_id = eid;
if ( !indexed ) {
}
}
- ocs = ndb_ref2oclist( ocbuf );
+ ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
break;
dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
{
-#ifdef notdef /* NDBapi is broken here */
+#if 1 /* NDBapi was broken here but seems to work now */
Ndb::Key_part_ptr keys[2];
- char xbuf[32];
+ char xbuf[512];
keys[0].ptr = &eid;
keys[0].len = sizeof(eid);
keys[1].ptr = NULL;
}
NA.txn = tx2;
NA.ocs = ocs;
- rc = ndb_entry_get_data( op->o_bd, &NA, 0 );
+ rc = ndb_entry_get_data( op, &NA, 0 );
tx2->close();
}
- ber_bvarray_free( ocs );
- rc = test_filter( op, &e, op->ors_filter );
- if ( rc == LDAP_COMPARE_TRUE ) {
- rs->sr_entry = &e;
- rs->sr_attrs = op->ors_attrs;
- rs->sr_flags = 0;
- rc = send_search_entry( op, rs );
- rs->sr_entry = NULL;
- } else {
- rc = 0;
+ ber_bvarray_free_x( ocs, op->o_tmpmemctx );
+ if ( !manageDSAit && is_entry_referral( &e )) {
+ BerVarray erefs = get_entry_referrals( op, &e );
+ rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
+ op->ors_scope == LDAP_SCOPE_ONELEVEL ?
+ LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
+ rc = send_search_reference( op, rs );
+ ber_bvarray_free( rs->sr_ref );
+ ber_bvarray_free( erefs );
+ rs->sr_ref = NULL;
+ } else if ( manageDSAit || !is_entry_glue( &e )) {
+ rc = test_filter( op, &e, op->ors_filter );
+ if ( rc == LDAP_COMPARE_TRUE ) {
+ rs->sr_entry = &e;
+ rs->sr_attrs = op->ors_attrs;
+ rs->sr_flags = 0;
+ rc = send_search_entry( op, rs );
+ rs->sr_entry = NULL;
+ rs->sr_attrs = NULL;
+ } else {
+ rc = 0;
+ }
}
attrs_free( e.e_attrs );
e.e_attrs = NULL;
int ndb_back_search( Operation *op, SlapReply *rs )
{
struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private;
- NdbTransaction *txn, *tx2;
+ NdbTransaction *txn;
NdbIndexScanOperation *scan;
NdbScanFilter *sf = NULL;
Entry e = {0};
NdbRdns rdns;
NdbOcInfo *oci;
NdbArgs NA;
+ slap_mask_t mask;
+ time_t stoptime;
+ int manageDSAit;
rc = ndb_thread_handle( op, &NA.ndb );
rdns.nr_num = 0;
+ manageDSAit = get_manageDSAit( op );
+
txn = NA.ndb->startTransaction();
if ( !txn ) {
Debug( LDAP_DEBUG_TRACE,
NA.txn = txn;
e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
NA.e = &e;
NA.rdns = &rdns;
- NA.ocs = op->ors_scope == LDAP_SCOPE_BASE ? NULL : &matched;
+ NA.ocs = NULL;
- rs->sr_err = ndb_entry_get_info( op->o_bd, &NA, 0, &matched );
+ rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched );
if ( rs->sr_err ) {
- if ( rs->sr_err == LDAP_NO_SUCH_OBJECT )
+ if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
rs->sr_matched = matched.bv_val;
+ if ( NA.ocs )
+ ndb_check_referral( op, rs, &NA );
+ }
goto leave;
}
+ if ( !access_allowed_mask( op, &e, slap_schema.si_ad_entry,
+ NULL, ACL_SEARCH, NULL, &mask )) {
+ if ( !ACL_GRANT( mask, ACL_DISCLOSE ))
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ else
+ rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
+ ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
+ goto leave;
+ }
+
+ rs->sr_err = ndb_entry_get_data( op, &NA, 0 );
+ ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
+ if ( rs->sr_err )
+ goto leave;
+
+ if ( !manageDSAit && is_entry_referral( &e )) {
+ rs->sr_ref = get_entry_referrals( op, &e );
+ rs->sr_err = LDAP_REFERRAL;
+ if ( rs->sr_ref )
+ rs->sr_flags |= REP_REF_MUSTBEFREED;
+ rs->sr_matched = e.e_name.bv_val;
+ attrs_free( e.e_attrs );
+ e.e_attrs = NULL;
+ goto leave;
+ }
+
+ if ( !manageDSAit && is_entry_glue( &e )) {
+ rs->sr_err = LDAP_NO_SUCH_OBJECT;
+ goto leave;
+ }
+
+ if ( get_assert( op ) && test_filter( op, &e, (Filter *)get_assertion( op )) !=
+ LDAP_COMPARE_TRUE ) {
+ rs->sr_err = LDAP_ASSERTION_FAILED;
+ attrs_free( e.e_attrs );
+ e.e_attrs = NULL;
+ goto leave;
+ }
+
+ /* admin ignores tlimits */
+ stoptime = op->o_time + op->ors_tlimit;
+
if ( op->ors_scope == LDAP_SCOPE_BASE ) {
- e.e_name = op->o_req_dn;
- e.e_nname = op->o_req_ndn;
- rc = ndb_entry_get_data( op->o_bd, &NA, 0 );
- ber_bvarray_free( NA.ocs );
rc = test_filter( op, &e, op->ors_filter );
if ( rc == LDAP_COMPARE_TRUE ) {
rs->sr_entry = &e;
e.e_attrs = NULL;
rs->sr_err = LDAP_SUCCESS;
goto leave;
- } else if ( rdns.nr_num == NDB_MAX_RDNS ) {
- if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ||
- op->ors_scope == LDAP_SCOPE_CHILDREN )
- rs->sr_err = LDAP_SUCCESS;
- goto leave;
+ } else {
+ attrs_free( e.e_attrs );
+ e.e_attrs = NULL;
+ if ( rdns.nr_num == NDB_MAX_RDNS ) {
+ if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ||
+ op->ors_scope == LDAP_SCOPE_CHILDREN )
+ rs->sr_err = LDAP_SUCCESS;
+ goto leave;
+ }
}
/* See if we can handle the filter. Filtering on objectClass is only done
}
scan = txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
+ if ( !scan ) {
+ rs->sr_err = LDAP_OTHER;
+ goto leave;
+ }
scan->readTuples( NdbOperation::LM_CommittedRead );
rc = ndb_dn2bound( scan, &rdns );
+ /* TODO: if ( ocfilter ) set up scanfilter for objectclass matches
+ * column COND_LIKE "% <class> %"
+ */
+
switch( op->ors_scope ) {
case LDAP_SCOPE_ONELEVEL:
sf = new NdbScanFilter(scan);
}
e.e_name.bv_val = dnBuf;
- while ( scan->nextResult() == 0 ) {
- if ( op->o_abandon )
+ while ( scan->nextResult( true, true ) == 0 ) {
+ if ( op->o_abandon ) {
+ rs->sr_err = SLAPD_ABANDON;
+ break;
+ }
+ if ( slapd_shutdown ) {
+ rs->sr_err = LDAP_UNAVAILABLE;
+ break;
+ }
+ if ( op->ors_tlimit != SLAP_NO_LIMIT &&
+ slap_get_time() > stoptime ) {
+ rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
break;
+ }
e.e_id = scanID->u_64_value();
- NA.ocs = ndb_ref2oclist( ocbuf );
+ NA.ocs = ndb_ref2oclist( ocbuf, op->o_tmpmemctx );
for ( i=0; i<NDB_MAX_RDNS; i++ ) {
if ( scanDN[i]->isNULL() || !rdns.nr_buf[i][0] )
break;
e.e_name.bv_len = ptr - dnBuf;
dnNormalize( 0, NULL, NULL, &e.e_name, &e.e_nname, op->o_tmpmemctx );
NA.txn = NA.ndb->startTransaction();
- rc = ndb_entry_get_data( op->o_bd, &NA, 0 );
+ rc = ndb_entry_get_data( op, &NA, 0 );
NA.txn->close();
- ber_bvarray_free( NA.ocs );
- rc = test_filter( op, &e, op->ors_filter );
- if ( rc == LDAP_COMPARE_TRUE ) {
- rs->sr_entry = &e;
- rs->sr_attrs = op->ors_attrs;
- rs->sr_flags = 0;
- rc = send_search_entry( op, rs );
- rs->sr_entry = NULL;
- } else {
- rc = 0;
+ ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx );
+ if ( !manageDSAit && is_entry_referral( &e )) {
+ BerVarray erefs = get_entry_referrals( op, &e );
+ rs->sr_ref = referral_rewrite( erefs, &e.e_name, NULL,
+ op->ors_scope == LDAP_SCOPE_ONELEVEL ?
+ LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
+ rc = send_search_reference( op, rs );
+ ber_bvarray_free( rs->sr_ref );
+ ber_bvarray_free( erefs );
+ rs->sr_ref = NULL;
+ } else if ( manageDSAit || !is_entry_glue( &e )) {
+ rc = test_filter( op, &e, op->ors_filter );
+ if ( rc == LDAP_COMPARE_TRUE ) {
+ rs->sr_entry = &e;
+ rs->sr_attrs = op->ors_attrs;
+ rs->sr_flags = 0;
+ rc = send_search_entry( op, rs );
+ rs->sr_entry = NULL;
+ } else {
+ rc = 0;
+ }
}
attrs_free( e.e_attrs );
e.e_attrs = NULL;
leave:
if ( sf )
delete sf;
- txn->close();
+ if ( txn )
+ txn->close();
send_ldap_result( op, rs );
return rs->sr_err;
}
+extern NdbInterpretedCode *ndb_lastrow_code; /* init.cpp */
+
extern "C" int
ndb_has_children(
NdbArgs *NA,
*hasChildren = LDAP_COMPARE_FALSE;
return 0;
}
-
+
scan = NA->txn->getNdbIndexScanOperation( "PRIMARY", DN2ID_TABLE );
if ( !scan )
return LDAP_OTHER;
if ( rc < NDB_MAX_RDNS ) {
scan->setBound( rc, NdbIndexScanOperation::BoundLT, "\0" );
}
+#if 0
scan->interpret_exit_last_row();
+#else
+ scan->setInterpretedCode(ndb_lastrow_code);
+#endif
scan->getValue( EID_COLUMN, idbuf );
if ( NA->txn->execute( NdbTransaction::NoCommit, NdbOperation::AO_IgnoreError, 1 )) {
return LDAP_OTHER;
}
- if (rc < NDB_MAX_RDNS && scan->nextResult() == 0 )
+ if (rc < NDB_MAX_RDNS && scan->nextResult( true, true ) == 0 )
*hasChildren = LDAP_COMPARE_TRUE;
else
*hasChildren = LDAP_COMPARE_FALSE;
+ scan->close();
return 0;
}
assert( rs->sr_entry != NULL );
- for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next )
- /* just count */ ;
+ for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) {
+ if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) {
+ break;
+ }
+ }
- if ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
- ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) )
+ if ( *ap == NULL &&
+ attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL &&
+ ( SLAP_OPATTRS( rs->sr_attr_flags ) ||
+ ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) )
{
int hasSubordinates, rc;