summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Kinder <nkinder@redhat.com>2005-08-26 15:44:36 +0000
committerNathan Kinder <nkinder@redhat.com>2005-08-26 15:44:36 +0000
commitfd47e2643aa00acd07b4cad660f9b8ebe7ec1600 (patch)
tree630d3c67510242c6caeceab3d1bb75c8a085cc22
parent3ad44b386d44e7d384573a942aaf5b3059863aaa (diff)
downloadds-fd47e2643aa00acd07b4cad660f9b8ebe7ec1600.tar.gz
ds-fd47e2643aa00acd07b4cad660f9b8ebe7ec1600.tar.xz
ds-fd47e2643aa00acd07b4cad660f9b8ebe7ec1600.zip
164843, 166012, 165827 - Indexing code now deals with attribute subtypes correctly.
-rw-r--r--ldap/servers/slapd/back-ldbm/back-ldbm.h1
-rw-r--r--ldap/servers/slapd/back-ldbm/index.c211
-rw-r--r--ldap/servers/slapd/libslapd.def1
-rw-r--r--ldap/servers/slapd/slapi-private.h1
4 files changed, 177 insertions, 37 deletions
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 0a0e3553..f4699863 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -637,6 +637,7 @@ typedef struct _back_search_result_set
#define BE_INDEX_PRESENCE 4 /* (w/DEL) remove the presence index */
#define BE_INDEX_TOMBSTONE 8 /* Index entry as a tombstone */
#define BE_INDEX_DONT_ENCRYPT 16 /* Disable any encryption if this flag is set */
+#define BE_INDEX_EQUALITY 32 /* (w/DEL) remove the equality index */
/* Name of attribute type used for binder-based look through limit */
#define LDBM_LOOKTHROUGHLIMIT_AT "nsLookThroughLimit"
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index e9fac76d..750c1041 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -453,35 +453,120 @@ index_add_mods(
)
{
int rc = 0;
- int i;
- Slapi_Attr *attr;
+ int i, j;
ID id = olde->ep_id;
- Slapi_Value **svals = NULL;
+ int flags = 0;
+ char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
+ char *basetype = NULL;
+ char *tmp = NULL;
+ Slapi_Attr *curr_attr = NULL;
+ Slapi_ValueSet *all_vals = NULL;
+ Slapi_ValueSet *mod_vals = NULL;
+ Slapi_Value **evals = NULL; /* values that still exist after a
+ * delete.
+ */
+ Slapi_Value **mods_valueArray = NULL; /* values that are specified in this
+ * operation.
+ */
+ Slapi_Value **deleted_valueArray = NULL; /* values whose index entries
+ * should be deleted.
+ */
for ( i = 0; mods[i] != NULL; i++ ) {
+ /* Get base attribute type */
+ basetype = buf;
+ tmp = slapi_attr_basetype(mods[i]->mod_type, buf, sizeof(buf));
+ if(tmp != NULL) {
+ basetype = tmp; /* basetype was malloc'd */
+ }
+
+ /* Get a list of all remaining values for the base type
+ * and any present subtypes.
+ */
+ all_vals = slapi_valueset_new();
+
+ for (curr_attr = newe->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
+ if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
+ valueset_add_valuearray(all_vals, attr_get_present_values(curr_attr));
+ }
+ }
+
+ evals = valueset_get_valuearray(all_vals);
+
+ /* Get a list of all values specified in the operation.
+ */
+ if ( mods[i]->mod_bvalues != NULL ) {
+ valuearray_init_bervalarray(mods[i]->mod_bvalues,
+ &mods_valueArray);
+ }
+
switch ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ) {
case LDAP_MOD_REPLACE:
+ flags = BE_INDEX_DEL;
+ /* Get a list of all values being deleted.
+ */
+ mod_vals = slapi_valueset_new();
+
+ for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
+ if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
+ valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
+ }
+ }
+
+ deleted_valueArray = valueset_get_valuearray(mod_vals);
+
+ /* If subtypes exist, don't remove the presence
+ * index.
+ */
+ if ( evals != NULL && deleted_valueArray != NULL) {
+ /* evals will contain the new value that is being
+ * added as part of the replace operation if one
+ * was specified. We must remove this value from
+ * evals to know if any subtypes are present.
+ */
+ slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr );
+ if ( mods_valueArray != NULL ) {
+ for ( j = 0; mods_valueArray[j] != NULL; j++ ) {
+ valuearray_remove_value(curr_attr, evals, mods_valueArray[j]);
+ }
+ }
+
+ /* Search evals for the values being deleted. If
+ * they don't exist, delete the equality index.
+ */
+ for ( j = 0; deleted_valueArray[j] != NULL; j++ ) {
+ if (valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1) {
+ if (!(flags & BE_INDEX_EQUALITY)) {
+ flags |= BE_INDEX_EQUALITY;
+ }
+ } else {
+ /* Remove duplicate value from deleted value array */
+ valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
+ j--;
+ }
+ }
+ } else {
+ flags |= BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
+ }
+
/* We need to first remove the old values from the
- * index. */
- if ( slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &attr ) == 0 &&
- (svals = attr_get_present_values(attr)) != NULL ) {
+ * index, if any. */
+ if (deleted_valueArray) {
index_addordel_values_sv( be, mods[i]->mod_type,
- svals, NULL, id,
- BE_INDEX_DEL|BE_INDEX_PRESENCE,
- txn );
+ deleted_valueArray, evals, id,
+ flags, txn );
}
+
+ /* Free valuearray */
+ slapi_valueset_free(mod_vals);
case LDAP_MOD_ADD:
- if ( mods[i]->mod_bvalues == NULL ) {
+ if ( mods_valueArray == NULL ) {
rc = 0;
} else {
- Slapi_Value **mods_valueArray = NULL;
- valuearray_init_bervalarray(mods[i]->mod_bvalues,
- &mods_valueArray);
rc = index_addordel_values_sv( be,
mods[i]->mod_type,
mods_valueArray, NULL,
id, BE_INDEX_ADD, txn );
- valuearray_free(&mods_valueArray);
}
break;
@@ -489,44 +574,92 @@ index_add_mods(
if ( (mods[i]->mod_bvalues == NULL) ||
(mods[i]->mod_bvalues[0] == NULL) ) {
rc = 0;
- /* if no value are specified all the values will
- * be suppressed -> remove the presence index
+ flags = BE_INDEX_DEL;
+
+ /* Get a list of all values that are being
+ * deleted.
+ */
+ mod_vals = slapi_valueset_new();
+
+ for (curr_attr = olde->ep_entry->e_attrs; curr_attr != NULL; curr_attr = curr_attr->a_next) {
+ if (slapi_attr_type_cmp( mods[i]->mod_type, curr_attr->a_type, SLAPI_TYPE_CMP_EXACT ) == 0) {
+ valueset_add_valuearray(mod_vals, attr_get_present_values(curr_attr));
+ }
+ }
+
+ deleted_valueArray = valueset_get_valuearray(mod_vals);
+
+ /* If subtypes exist, don't remove the
+ * presence index.
*/
- if ( slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &attr ) == 0 &&
- (svals = attr_get_present_values(attr)) != NULL ) {
- index_addordel_values_sv( be, mods[i]->mod_type,
- svals, NULL, id, BE_INDEX_DEL|BE_INDEX_PRESENCE, txn);
+ if (evals != NULL) {
+ for (curr_attr = newe->ep_entry->e_attrs; (curr_attr != NULL);
+ curr_attr = curr_attr->a_next) {
+ if (slapi_attr_type_cmp( basetype, curr_attr->a_type, SLAPI_TYPE_CMP_BASE ) == 0) {
+ /* Check if the any values being deleted
+ * also exist in a subtype.
+ */
+ for ( j=0; deleted_valueArray[j] != NULL; j++) {
+ if ( valuearray_find(curr_attr, evals, deleted_valueArray[j]) == -1 ) {
+ /* If the equality flag isn't already set, set it */
+ if (!(flags & BE_INDEX_EQUALITY)) {
+ flags |= BE_INDEX_EQUALITY;
+ }
+ } else {
+ /* Remove duplicate value from the mod list */
+ valuearray_remove_value(curr_attr, deleted_valueArray, deleted_valueArray[j]);
+ j--;
+ }
+ }
+ }
+ }
+ } else {
+ flags = BE_INDEX_DEL|BE_INDEX_PRESENCE|BE_INDEX_EQUALITY;
}
+
+ /* Update the index */
+ index_addordel_values_sv( be, mods[i]->mod_type,
+ deleted_valueArray, evals, id, flags, txn);
+
+ slapi_valueset_free(mod_vals);
} else {
+
/* determine if the presence key should be
* removed (are we removing the last value
* for this attribute?)
*/
- int flags = BE_INDEX_DEL;
- Slapi_Value ** svals = NULL;
- Slapi_Value **mods_valueArray = NULL;
-
- valuearray_init_bervalarray(mods[i]->mod_bvalues,
- &mods_valueArray);
-
- if (slapi_entry_attr_find(newe->ep_entry,
- mods[i]->mod_type, &attr) == 0) {
- svals = attr_get_present_values(attr);
+ if (evals == NULL || evals[0] == NULL) {
+ flags = BE_INDEX_DEL|BE_INDEX_PRESENCE;
+ } else {
+ flags = BE_INDEX_DEL;
}
- if (svals == NULL || svals[0] == NULL) {
- flags |= BE_INDEX_PRESENCE;
- }
+ /* If the same value doesn't exist in a subtype, set
+ * BE_INDEX_EQUALITY flag so the equality index is
+ * removed.
+ */
+ slapi_entry_attr_find( olde->ep_entry, mods[i]->mod_type, &curr_attr);
+ for (j = 0; mods_valueArray[j] != NULL; j++ ) {
+ if ( valuearray_find(curr_attr, evals, mods_valueArray[j]) == -1 ) {
+ if (!(flags & BE_INDEX_EQUALITY)) {
+ flags |= BE_INDEX_EQUALITY;
+ }
+ }
+ }
- rc = index_addordel_values_sv( be, mods[i]->mod_type,
+ rc = index_addordel_values_sv( be, basetype,
mods_valueArray,
- svals, id, flags, txn );
- valuearray_free(&mods_valueArray);
+ evals, id, flags, txn );
}
rc = 0;
break;
}
+ /* free memory */
+ slapi_ch_free((void **)&tmp);
+ valuearray_free(&mods_valueArray);
+ slapi_valueset_free(all_vals);
+
if ( rc != 0 ) {
ldbm_nasty(errmsg, 1040, rc);
return( rc );
@@ -1595,7 +1728,11 @@ index_addordel_values_ext_sv(
/*
* equality index entry
*/
- if ( ai->ai_indexmask & INDEX_EQUALITY ) {
+ if (( ai->ai_indexmask & INDEX_EQUALITY ) &&
+ (flags & (BE_INDEX_ADD|BE_INDEX_EQUALITY))) {
+ /* on delete, only remove the equality index if the
+ * BE_INDEX_EQUALITY flag is set.
+ */
slapi_call_syntax_values2keys_sv( ai->ai_plugin, vals, &ivals,
LDAP_FILTER_EQUALITY );
diff --git a/ldap/servers/slapd/libslapd.def b/ldap/servers/slapd/libslapd.def
index 074a8873..cb4b4e77 100644
--- a/ldap/servers/slapd/libslapd.def
+++ b/ldap/servers/slapd/libslapd.def
@@ -1056,6 +1056,7 @@ EXPORTS
slapi_entry_delete_values_sv @1058
slapi_entry_attr_replace_sv @1059
+ valuearray_find @1060
valuearray_free @1061
slapd_Client_auth @1062
slapi_rand_r @1063
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 27b5609b..9c9ce5c3 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -778,6 +778,7 @@ void valuearray_add_value(Slapi_Value ***vals, const Slapi_Value *addval);
void valuearray_add_value_fast(Slapi_Value ***vals, Slapi_Value *addval, int nvals, int *maxvals, int exact, int passin);
void valuearray_add_valuearray( Slapi_Value ***vals, Slapi_Value **addvals, PRUint32 flags );
void valuearray_add_valuearray_fast( Slapi_Value ***vals, Slapi_Value **addvals, int nvals, int naddvals, int *maxvals, int exact, int passin );
+int valuearray_find(const Slapi_Attr *a, Slapi_Value **va, const Slapi_Value *v);
/******************************************************************************