1 /* index.c - routines for dealing with attribute indexes */
4 * Copyright 1998-2000 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"
18 #ifdef SLAPD_SCHEMA_NOT_COMPAT
21 AttributeDescription *desc,
28 /* we do support indexing of binary attributes */
29 if( slap_ad_is_binary( desc ) ) return 0;
31 attr_mask( be->be_private, desc->ad_cname->bv_val, &mask );
34 *atname = desc->ad_cname->bv_val;
35 *dbname = desc->ad_cname->bv_val;
39 if( slap_ad_is_lang( desc ) ) {
40 /* has language tag */
41 attr_mask( be->be_private, desc->ad_type->sat_cname, &mask );
43 if( mask & SLAP_INDEX_AUTO_LANG ) {
44 *atname = desc->ad_cname->bv_val;
45 *dbname = desc->ad_type->sat_cname;
48 if( mask & SLAP_INDEX_LANG ) {
49 *atname = desc->ad_type->sat_cname;
50 *dbname = desc->ad_type->sat_cname;
55 /* see if supertype defined mask for its subtypes */
56 for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
57 attr_mask( be->be_private, at->sat_cname, &mask );
59 if( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
60 *atname = desc->ad_type->sat_cname;
61 *dbname = at->sat_cname;
64 if( mask & SLAP_INDEX_SUBTYPES ) {
65 *atname = at->sat_cname;
66 *dbname = at->sat_cname;
78 AttributeDescription *desc,
82 struct berval **prefixp )
88 mask = index_mask( be, desc, &dbname, &atname );
91 return LDAP_INAPPROPRIATE_MATCHING;
95 case LDAP_FILTER_PRESENT:
96 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
101 case LDAP_FILTER_APPROX:
102 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
107 case LDAP_FILTER_EQUALITY:
108 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
113 case LDAP_FILTER_SUBSTRINGS:
114 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
123 return LDAP_INAPPROPRIATE_MATCHING;
127 *prefixp = ber_bvstrdup( atname );
136 struct berval **vals,
144 AttributeDescription *ad = NULL;
145 struct berval **keys;
146 struct berval prefix;
150 rc = slap_str2ad( atname, &ad, &text );
152 if( rc != LDAP_SUCCESS ) return rc;
154 prefix.bv_val = atname;
155 prefix.bv_len = strlen( atname );
157 db = ldbm_cache_open( be, dbname, LDBM_SUFFIX, LDBM_WRCREAT );
160 Debug( LDAP_DEBUG_ANY,
161 "<= index_read NULL (could not open %s%s)\n",
162 dbname, LDBM_SUFFIX, 0 );
167 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
168 key_change( be, db, &prefix, id, op );
171 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
172 rc = ad->ad_type->sat_equality->smr_indexer(
174 ad->ad_type->sat_syntax,
175 ad->ad_type->sat_equality,
176 &prefix, vals, &keys );
178 if( rc == LDAP_SUCCESS ) {
179 for( i= 0; keys[i] != NULL; i++ ) {
180 key_change( be, db, keys[i], id, op );
185 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
186 rc = ad->ad_type->sat_approx->smr_indexer(
188 ad->ad_type->sat_syntax,
189 ad->ad_type->sat_approx,
190 &prefix, vals, &keys );
192 if( rc == LDAP_SUCCESS ) {
193 for( i= 0; keys[i] != NULL; i++ ) {
194 key_change( be, db, keys[i], id, op );
199 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
200 rc = ad->ad_type->sat_substr->smr_indexer(
202 ad->ad_type->sat_syntax,
203 ad->ad_type->sat_substr,
204 &prefix, vals, &keys );
206 if( rc == LDAP_SUCCESS ) {
207 for( i= 0; keys[i] != NULL; i++ ) {
208 key_change( be, db, keys[i], id, op );
213 ldbm_cache_close( be, db );
218 static int index_at_values(
222 struct berval **vals,
229 slap_index tmpmask = 0;
232 if( type->sat_sup ) {
234 (void) index_at_values( be,
240 attr_mask( be->be_private, type->sat_cname, &mask );
243 *dbnamep = type->sat_cname;
244 } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
249 indexer( be, *dbnamep,
257 size_t tlen = strlen( type->sat_cname );
258 size_t llen = strlen( lang );
259 char *lname = ch_malloc( tlen + llen + sizeof(";") );
261 sprintf( lname, "%s;%s", type->sat_cname, lang );
263 attr_mask( be->be_private, lname, &tmpmask );
267 } else if ( mask & SLAP_INDEX_AUTO_LANG ) {
272 if( dbname != NULL ) {
273 indexer( be, dbname, lname,
286 AttributeDescription *desc,
287 struct berval **vals,
294 if( slap_ad_is_binary( desc ) ) {
295 /* binary attributes have no index capabilities */
299 (void) index_at_values( be,
300 desc->ad_type, desc->ad_lang,
308 int index_change_values(
310 #ifdef SLAPD_SCHEMA_NOT_COMPAT
311 AttributeDescription *desc,
315 struct berval **vals,
320 #ifndef SLAPD_SCHEMA_NOT_COMPAT
321 static int change_value(Backend *be,
328 (*idl_func)(Backend *, DBCache *, Datum, ID));
340 #ifndef SLAPD_SCHEMA_NOT_COMPAT
342 struct berval *bvals[2];
345 Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
346 op == SLAP_INDEX_ADD_OP ? "add" : "del",
349 #ifndef SLAPD_SCHEMA_NOT_COMPAT
351 * dn index entry - make it look like an attribute so it works
352 * with index_change_values() call
355 bv.bv_val = ch_strdup( e->e_ndn );
356 bv.bv_len = strlen( bv.bv_val );
360 /* add the dn to the indexes */
362 char *dn = ch_strdup("dn");
363 index_change_values( be, dn, bvals, e->e_id, op );
370 /* add each attribute to the indexes */
371 for ( ap; ap != NULL; ap = ap->a_next ) {
372 #ifdef SLAPD_SCHEMA_NOT_COMPAT
373 index_values( be, ap->a_desc, ap->a_vals, e->e_id, op );
375 index_change_values( be, ap->a_type, ap->a_vals, e->e_id, op );
379 Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
380 op == SLAP_INDEX_ADD_OP ? "add" : "del",
386 #ifndef SLAPD_SCHEMA_NOT_COMPAT
401 char *realval, *tmpval;
406 ldbm_datum_init( key );
408 prefix = slap_index2prefix( indextype );
409 Debug( LDAP_DEBUG_TRACE, "=> index_read(\"%c%s\"->\"%s\")\n",
412 attr_mask( be->be_private, type, &indexmask );
413 if ( ! (indextype & indexmask) ) {
414 idl = idl_allids( be );
415 Debug( LDAP_DEBUG_TRACE,
416 "<= index_read %ld candidates (allids - not indexed)\n",
417 idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
421 #ifdef SLAPD_SCHEMA_NOT_COMPAT
422 at_cn = at_canonical_name( at_find( type ) );
424 attr_normalize( type );
425 at_cn = at_canonical_name( type );
428 if ( at_cn == NULL ) {
429 Debug( LDAP_DEBUG_ANY,
430 "<= index_read no canonical name for type \"%s\"\n",
431 type != NULL ? type : "(NULL)", 0, 0 );
435 if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, LDBM_WRCREAT ))
437 Debug( LDAP_DEBUG_ANY,
438 "<= index_read NULL (could not open %s%s)\n",
439 at_cn, LDBM_SUFFIX, 0 );
445 if ( prefix != UNKNOWN_PREFIX ) {
446 unsigned int len = strlen( val );
448 if ( (len + 2) < sizeof(buf) ) {
451 /* value + prefix + null */
452 tmpval = (char *) ch_malloc( len + 2 );
457 strcpy( &realval[1], val );
461 key.dsize = strlen( realval ) + 1;
463 idl = idl_fetch( be, db, key );
464 if ( tmpval != NULL ) {
468 ldbm_cache_close( be, db );
470 Debug( LDAP_DEBUG_TRACE, "<= index_read %ld candidates\n",
471 idl ? ID_BLOCK_NIDS(idl) : 0, 0, 0 );
475 /* Add or remove stuff from index files */
485 int (*idl_func)(Backend *, DBCache *, Datum, ID)
494 char prefix = slap_index2prefix( indextype );
496 ldbm_datum_init( key );
498 Debug( LDAP_DEBUG_TRACE,
499 "=> change_value( \"%c%s\", op=%s )\n",
500 prefix, val, (idl_func == idl_insert_key ? "ADD":"DELETE") );
502 if ( prefix != UNKNOWN_PREFIX ) {
503 unsigned int len = strlen( val );
505 if ( (len + 2) < sizeof(buf) ) {
508 /* value + prefix + null */
509 tmpval = (char *) ch_malloc( len + 2 );
513 strcpy( &realval[1], val );
517 key.dsize = strlen( realval ) + 1;
519 rc = idl_func( be, db, key, id );
521 if ( tmpval != NULL ) {
525 ldap_pvt_thread_yield();
527 Debug( LDAP_DEBUG_TRACE, "<= change_value %d\n", rc, 0, 0 );
533 #ifdef SLAPD_SCHEMA_NOT_COMPAT
539 #ifdef SLAPD_SCHEMA_NOT_COMPAT
540 AttributeDescription *desc,
544 struct berval **vals,
549 char *val, *p, *code, *w;
551 int indexmask, syntax;
552 char buf[SUBLEN + 1];
557 int (*idl_funct)(Backend *,
560 char *at_cn; /* Attribute canonical name */
563 #ifdef SLAPD_SCHEMA_NOT_COMPAT
564 char *type = desc->ad_cname->bv_val;
570 Debug( LDAP_DEBUG_TRACE,
571 "=> index_change_values( %s, NULL, %ld, op=%s )\n",
572 type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
576 Debug( LDAP_DEBUG_TRACE,
577 "=> index_change_values( \"%s\", %ld, op=%s )\n",
578 type, id, ((op == SLAP_INDEX_ADD_OP) ? "ADD" : "DELETE" ) );
581 if (op == SLAP_INDEX_ADD_OP) {
583 idl_funct = idl_insert_key;
588 idl_funct = idl_delete_key;
592 #ifndef SLAPD_SCHEMA_NOT_COMPAT
593 attr_normalize(type);
595 attr_mask( be->be_private, desc, &indexmask );
597 if ( indexmask == 0 ) {
601 #ifdef SLAPD_SCHEMA_NOT_COMPAT
602 at_cn = at_canonical_name( at_find( type ) );
604 syntax = attr_syntax( type );
605 at_cn = at_canonical_name( type );
608 if ( at_cn == NULL ) {
609 Debug( LDAP_DEBUG_ANY,
610 "<= index_change_values no canonical name for type \"%s\"\n",
611 type != NULL ? type : "(NULL)", 0, 0 );
615 if ( (db = ldbm_cache_open( be, at_cn, LDBM_SUFFIX, mode ))
617 Debug( LDAP_DEBUG_ANY,
618 "<= index_change_values (couldn't open(%s%s),md=%s)\n",
620 ((mode==LDBM_WRCREAT)?"LDBM_WRCREAT":"LDBM_WRITER") );
625 * presence index entry
627 if ( indexmask & SLAP_INDEX_PRESENT ) {
628 change_value( be, db, at_cn, SLAP_INDEX_PRESENT,
629 "*", id, idl_funct );
632 #ifndef SLAPD_SCHEMA_NOT_COMPAT
633 if ( syntax & SYNTAX_BIN ) {
638 for ( i = 0; vals[i] != NULL; i++ ) {
639 Debug( LDAP_DEBUG_TRACE,
640 "index_change_values syntax 0x%x\n",
644 len = vals[i]->bv_len;
647 if ( len + 2 > sizeof(vbuf) ) {
648 bigbuf = (char *) ch_malloc( len + 1 );
653 (void) memcpy( val, vals[i]->bv_val, len );
656 #ifndef SLAPD_SCHEMA_NOT_COMPAT
657 value_normalize( val, syntax );
660 /* value_normalize could change the length of val */
664 * equality index entry
666 if ( indexmask & SLAP_INDEX_EQUALITY ) {
667 change_value( be, db, at_cn, SLAP_INDEX_EQUALITY,
672 * approximate index entry
674 if ( indexmask & SLAP_INDEX_APPROX ) {
675 for ( w = first_word( val ); w != NULL;
676 w = next_word( w ) ) {
677 if ( (code = phonetic( w )) != NULL ) {
691 * substrings index entry
693 if ( indexmask & SLAP_INDEX_SUBSTR ) {
694 /* leading and trailing */
695 if ( len > SUBLEN - 2 ) {
697 for ( j = 0; j < SUBLEN - 1; j++ ) {
702 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
703 buf, id, idl_funct );
705 p = val + len - SUBLEN + 1;
706 for ( j = 0; j < SUBLEN - 1; j++ ) {
709 buf[SUBLEN - 1] = '$';
712 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
713 buf, id, idl_funct );
717 for ( p = val; p < (val + len - SUBLEN + 1); p++ ) {
718 for ( j = 0; j < SUBLEN; j++ ) {
723 change_value( be, db, at_cn, SLAP_INDEX_SUBSTR,
724 buf, id, idl_funct );
728 if ( bigbuf != NULL ) {
732 #ifndef SLAPD_SCHEMA_NOT_COMPAT
735 ldbm_cache_close( be, db );