1 /* index.c - routines for dealing with attribute indexes */
4 * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/string.h>
13 #include <ac/socket.h>
16 #include "back-ldbm.h"
19 static int change_value(Backend *be,
26 (*idl_func)(Backend *, DBCache *, Datum, ID));
27 static int index2prefix(int indextype);
37 struct berval *bvals[2];
39 Debug( LDAP_DEBUG_TRACE, "=> index_add( %ld, \"%s\" )\n", e->e_id,
43 * dn index entry - make it look like an attribute so it works
44 * with index_change_values() call
47 bv.bv_val = ch_strdup( e->e_ndn );
48 bv.bv_len = strlen( bv.bv_val );
52 /* add the dn to the indexes */
54 char *dn = ch_strdup("dn");
55 #ifdef SLAPD_SCHEMA_NOT_COMPAT
56 /* not yet implemented */
58 index_change_values( be, dn, bvals, e->e_id, SLAP_INDEX_ADD_OP );
65 /* add each attribute to the indexes */
66 for ( ap = e->e_attrs; ap != NULL; ap = ap->a_next ) {
67 #ifdef SLAPD_SCHEMA_NOT_COMPAT
68 /* index_change_values( be, SLAP_INDEX_ADD_OP, e->e_id, ap ); */
70 index_change_values( be, ap->a_type, ap->a_vals, e->e_id,
75 Debug( LDAP_DEBUG_TRACE, "<= index_add( %ld, \"%s\" ) 0\n", e->e_id,
89 for ( ; ml != NULL; ml = ml->ml_next ) {
90 Modification *mod = &ml->ml_mod;
92 #ifdef SLAPD_SCHEMA_NOT_COMPAT
93 /* not yet implemented */
96 switch ( mod->mod_op ) {
97 case LDAP_MOD_REPLACE:
98 /* XXX: Delete old index data==>problem when this
99 * gets called we lost values already!
102 rc = index_change_values( be,
108 case LDAP_MOD_DELETE:
109 rc = index_change_values( be,
113 SLAP_INDEX_DELETE_OP );
115 case SLAP_MOD_SOFTADD: /* SOFTADD means index was there */
145 char *realval, *tmpval;
150 ldbm_datum_init( key );
152 prefix = index2prefix( indextype );
153 Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n",
156 attr_mask( be->be_private, type, &indexmask );
157 if ( ! (indextype & indexmask) ) {
158 idl = idl_allids( be );
159 Debug( LDAP_DEBUG_TRACE,
160 "<= index_read %ld candidates (allids - not indexed)\n",
161 idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
165 #ifdef SLAPD_SCHEMA_NOT_COMPAT
166 at_cn = at_canonical_name( at_find( type ) );
168 attr_normalize( type );
169 at_cn = at_canonical_name( type );
172 if ( at_cn == NULL ) {
173 Debug( LDAP_DEBUG_ANY,
174 "<= index_read no canonical name for type \"%s\"\n",
175 type != NULL ? type : "(NULL)", 0, 0 );
179 if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
181 Debug( LDAP_DEBUG_ANY,
182 "<= index_read NULL (could not open %s%s)\n",
183 at_cn, LDBM_SUFFIX, 0 );
189 if ( prefix != UNKNOWN_PREFIX ) {
190 unsigned int len = strlen( val );
192 if ( (len + 2) < sizeof(buf) ) {
195 /* value + prefix + null */
196 tmpval = (char *) ch_malloc( len + 2 );
201 strcpy( &realval[1], val );
205 key.dsize = strlen( realval ) + 1;
207 idl = idl_fetch( be, db, key );
208 if ( tmpval != NULL ) {
212 ldbm_cache_close( be, db );
214 Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
215 idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
219 /* Add or remove stuff from index files */
229 int (*idl_func)(Backend *, DBCache *, Datum, ID)
238 char prefix = index2prefix( indextype );
240 ldbm_datum_init( key );
242 Debug( LDAP_DEBUG_TRACE,
243 "=> change_value( \"%c%s\", op=%s )\n",
244 prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
246 if ( prefix != UNKNOWN_PREFIX ) {
247 unsigned int len = strlen( val );
249 if ( (len + 2) < sizeof(buf) ) {
252 /* value + prefix + null */
253 tmpval = (char *) ch_malloc( len + 2 );
257 strcpy( &realval[1], val );
261 key.dsize = strlen( realval ) + 1;
263 rc = idl_func( be, db, key, id );
265 if ( tmpval != NULL ) {
269 ldap_pvt_thread_yield();
271 Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
275 }/* static int change_value() */
282 struct berval **vals,
287 char *val, *p, *code, *w;
289 int indexmask, syntax;
290 char buf[SUBLEN + 1];
295 int (*idl_funct)(Backend *,
298 char *at_cn; /* Attribute canonical name */
302 Debug( LDAP_DEBUG_TRACE,
303 "=> index_change_values( %s, NULL, %ld, op=%s )\n",
304 type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
308 Debug( LDAP_DEBUG_TRACE,
309 "=> index_change_values( \"%s\", %ld, op=%s )\n",
310 type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
313 if (op == SLAP_INDEX_ADD_OP) {
317 idl_funct = idl_insert_key;
324 idl_funct = idl_delete_key;
329 #ifndef SLAPD_SCHEMA_NOT_COMPAT
330 attr_normalize(type);
332 attr_mask( be->be_private, type, &indexmask );
334 if ( indexmask == 0 ) {
338 #ifdef SLAPD_SCHEMA_NOT_COMPAT
339 at_cn = at_canonical_name( at_find( type ) );
341 syntax = attr_syntax( type );
342 at_cn = at_canonical_name( type );
345 if ( at_cn == NULL ) {
346 Debug( LDAP_DEBUG_ANY,
347 "<= index_change_values no canonical name for type \"%s\"\n",
348 type != NULL ? type : "(NULL)", 0, 0 );
352 if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
354 Debug( LDAP_DEBUG_ANY,
355 "<= index_change_values (couldn't open(%s%s),md=%s)\n",
357 ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
362 #ifdef SLAPD_SCHEMA_NOT_COMPAT
363 /* not yet implemented */
365 for ( i = 0; vals[i] != NULL; i++ ) {
367 * presence index entry
369 if ( indexmask & SLAP_INDEX_PRESENCE ) {
371 change_value( be, db, at_cn, SLAP_INDEX_PRESENCE,
372 "*", id, idl_funct );
376 Debug( LDAP_DEBUG_TRACE,
377 "index_change_values syntax 0x%x syntax bin 0x%x\n",
378 syntax, SYNTAX_BIN, 0 );
380 if ( syntax & SYNTAX_BIN ) {
382 ldbm_cache_close( be, db );
388 len = vals[i]->bv_len;
391 if ( len + 2 > sizeof(vbuf) ) {
392 bigbuf = (char *) ch_malloc( len + 1 );
397 (void) memcpy( val, vals[i]->bv_val, len );
400 value_normalize( val, syntax );
402 /* value_normalize could change the length of val */
406 * equality index entry
408 if ( indexmask & SLAP_INDEX_EQUALITY ) {
410 change_value( be, db, at_cn, SLAP_INDEX_EQUALITY,
416 * approximate index entry
418 if ( indexmask & SLAP_INDEX_APPROX ) {
419 for ( w = first_word( val ); w != NULL;
420 w = next_word( w ) ) {
421 if ( (code = phonetic( w )) != NULL ) {
435 * substrings index entry
437 if ( indexmask & SLAP_INDEX_SUB ) {
438 /* leading and trailing */
439 if ( len > SUBLEN - 2 ) {
441 for ( j = 0; j < SUBLEN - 1; j++ ) {
446 change_value( be, db, at_cn, SLAP_INDEX_SUB,
447 buf, id, idl_funct );
449 p = val + len - SUBLEN + 1;
450 for ( j = 0; j < SUBLEN - 1; j++ ) {
453 buf[SUBLEN - 1] = '$';
456 change_value( be, db, at_cn, SLAP_INDEX_SUB,
457 buf, id, idl_funct );
461 for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
462 for ( j = 0; j < SUBLEN; j++ ) {
467 change_value( be, db, at_cn, SLAP_INDEX_SUB,
468 buf, id, idl_funct );
472 if ( bigbuf != NULL ) {
478 ldbm_cache_close( be, db );
484 index2prefix( int indextype )
488 switch ( indextype ) {
489 case SLAP_INDEX_EQUALITY:
492 case SLAP_INDEX_APPROX:
493 prefix = APPROX_PREFIX;
499 prefix = UNKNOWN_PREFIX;