diff options
| -rw-r--r-- | ldap/servers/slapd/back-ldbm/dblayer.c | 34 | ||||
| -rw-r--r-- | ldap/servers/slapd/back-ldbm/index.c | 48 |
2 files changed, 68 insertions, 14 deletions
diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index 141662c2..68ea3338 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -232,22 +232,42 @@ static int dblayer_db_remove_ex(dblayer_private_env *env, char const path[], cha always normalize both arguments. We need to add an additional syntax compare function that does not normalize or takes an argument like value_cmp to specify to normalize or not. -*/ -typedef int (*syntax_cmp_fn_type)(struct berval *, struct berval *); + More fun - this function is used to compare both raw database + keys (e.g. with the prefix '=' or '+' or '*' etc.) and without + (in the case of two equality keys, we want to strip off the + leading '=' to compare the actual values). We only use the + value_compare function if both keys are equality keys with + some data after the equality prefix. In every other case, + we will just use a standard berval cmp function. + + see also DBTcmp +*/ static int dblayer_bt_compare(DB *db, const DBT *dbt1, const DBT *dbt2) { struct berval bv1, bv2; value_compare_fn_type syntax_cmp_fn = (value_compare_fn_type)db->app_private; - bv1.bv_val = (char *)dbt1->data+1; /* remove leading '=' */ - bv1.bv_len = (ber_len_t)dbt1->size-1; + if ((dbt1->data && (dbt1->size>1) && (*((char*)dbt1->data) == EQ_PREFIX)) && + (dbt2->data && (dbt2->size>1) && (*((char*)dbt2->data) == EQ_PREFIX))) { + bv1.bv_val = (char *)dbt1->data+1; /* remove leading '=' */ + bv1.bv_len = (ber_len_t)dbt1->size-1; + + bv2.bv_val = (char *)dbt2->data+1; /* remove leading '=' */ + bv2.bv_len = (ber_len_t)dbt2->size-1; + + return syntax_cmp_fn(&bv1, &bv2); + } + + /* else compare two "raw" index keys */ + bv1.bv_val = (char *)dbt1->data; + bv1.bv_len = (ber_len_t)dbt1->size; - bv2.bv_val = (char *)dbt2->data+1; /* remove leading '=' */ - bv2.bv_len = (ber_len_t)dbt2->size-1; + bv2.bv_val = (char *)dbt2->data; + bv2.bv_len = (ber_len_t)dbt2->size; - return syntax_cmp_fn(&bv1, &bv2); + return slapi_berval_cmp(&bv1, &bv2); } /* this flag use if user remotely turned batching off */ diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c index 9da2389c..344f33f1 100644 --- a/ldap/servers/slapd/back-ldbm/index.c +++ b/ldap/servers/slapd/back-ldbm/index.c @@ -895,16 +895,50 @@ index_read_ext( return( idl ); } +/* This function compares two index keys. It is assumed + that the values are already normalized, since they should have + been when the index was created (by int_values2keys). + + richm - actually, the current syntax compare functions + always normalize both arguments. We need to add an additional + syntax compare function that does not normalize or takes + an argument like value_cmp to specify to normalize or not. + + More fun - this function is used to compare both raw database + keys (e.g. with the prefix '=' or '+' or '*' etc.) and without + (in the case of two equality keys, we want to strip off the + leading '=' to compare the actual values). We only use the + value_compare function if both keys are equality keys with + some data after the equality prefix. In every other case, + we will just use a standard berval cmp function. + + see also dblayer_bt_compare +*/ static int -DBTcmp (DBT* L, DBT* R) +DBTcmp (DBT* L, DBT* R, value_compare_fn_type cmp_fn) { struct berval Lv; struct berval Rv; - Lv.bv_val = L->dptr; Lv.bv_len = L->dsize; - Rv.bv_val = R->dptr; Rv.bv_len = R->dsize; - return slapi_berval_cmp (&Lv, &Rv); + + if ((L->data && (L->size>1) && (*((char*)L->data) == EQ_PREFIX)) && + (R->data && (R->size>1) && (*((char*)R->data) == EQ_PREFIX))) { + Lv.bv_val = (char*)L->data+1; Lv.bv_len = (ber_len_t)L->size-1; + Rv.bv_val = (char*)R->data+1; Rv.bv_len = (ber_len_t)R->size-1; + /* use specific compare fn, if any */ + cmp_fn = (cmp_fn ? cmp_fn : slapi_berval_cmp); + } else { + Lv.bv_val = (char*)L->data; Lv.bv_len = (ber_len_t)L->size; + Rv.bv_val = (char*)R->data; Rv.bv_len = (ber_len_t)R->size; + /* just compare raw bervals */ + cmp_fn = slapi_berval_cmp; + } + return cmp_fn(&Lv, &Rv); } +/* This only works with normalized keys, which + should be ok because at this point both L and R + should have already been normalized +*/ #define DBT_EQ(L,R) ((L)->dsize == (R)->dsize &&\ ! memcmp ((L)->dptr, (R)->dptr, (L)->dsize)) @@ -1145,7 +1179,7 @@ index_range_read( "index_range_read(%s,%s) seek to end of index file err %i\n", type, prefix, *err ); } - } else if (DBTcmp (&upperkey, &cur_key) > 0) { + } else if (DBTcmp (&upperkey, &cur_key, ai->ai_key_cmp_fn) > 0) { tmpbuf = slapi_ch_realloc (tmpbuf, cur_key.dsize); memcpy (tmpbuf, cur_key.dptr, cur_key.dsize); DBT_FREE_PAYLOAD(upperkey); @@ -1233,8 +1267,8 @@ index_range_read( } while (*err == 0 && (operator == SLAPI_OP_LESS) ? - DBTcmp(&cur_key, &upperkey) < 0 : - DBTcmp(&cur_key, &upperkey) <= 0) { + DBTcmp(&cur_key, &upperkey, ai->ai_key_cmp_fn) < 0 : + DBTcmp(&cur_key, &upperkey, ai->ai_key_cmp_fn) <= 0) { /* exit the loop when we either run off the end of the table, * fail to read a key, or read a key that's out of range. */ |
