]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/index.c
More fixes for autosubtype index generation
[openldap] / servers / slapd / back-bdb / index.c
1 /* index.c - routines for dealing with attribute indexes */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/string.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16 #include "back-bdb.h"
17 #include "lutil_hash.h"
18
19 static char presence_keyval[LUTIL_HASH_BYTES] = {0,0,0,1};
20 static struct berval presence_key = {LUTIL_HASH_BYTES, presence_keyval};
21
22 static slap_mask_t index_mask(
23         Backend *be,
24         AttributeDescription *desc,
25         char **dbname,
26         struct berval *atname )
27 {
28         AttributeType *at;
29         slap_mask_t mask = 0;
30
31         bdb_attr_mask( be->be_private, desc, &mask );
32
33         if( mask ) {
34                 *atname = desc->ad_cname;
35                 *dbname = desc->ad_cname.bv_val;
36                 return mask;
37         }
38
39         /* If there is a language tag, did we ever index the base
40          * type? If so, check for mask, otherwise it's not there.
41          */
42         if( slap_ad_is_lang( desc ) && desc != desc->ad_type->sat_ad ) {
43                 /* has language tag */
44                 bdb_attr_mask( be->be_private, desc->ad_type->sat_ad, &mask );
45
46                 if ( mask && ( mask ^ SLAP_INDEX_NOLANG ) ) {
47                         *atname = desc->ad_type->sat_cname;
48                         *dbname = desc->ad_type->sat_cname.bv_val;
49                         return mask;
50                 }
51         }
52
53         /* see if supertype defined mask for its subtypes */
54         for( at = desc->ad_type; at != NULL ; at = at->sat_sup ) {
55                 /* If no AD, we've never indexed this type */
56                 if ( !at->sat_ad ) continue;
57
58                 bdb_attr_mask( be->be_private, at->sat_ad, &mask );
59
60                 if ( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
61                         *atname = desc->ad_type->sat_cname;
62                         *dbname = at->sat_cname.bv_val;
63                         return mask;
64                 }
65
66                 if ( mask && ( mask ^ SLAP_INDEX_NOSUBTYPES ) ) {
67                         *atname = at->sat_cname;
68                         *dbname = at->sat_cname.bv_val;
69                         return mask;
70                 }
71         }
72
73         return 0;
74 }
75
76 int bdb_index_is_indexed(
77         Backend *be,
78         AttributeDescription *desc )
79 {
80         int rc;
81         slap_mask_t mask;
82         char *dbname;
83         struct berval prefix;
84
85         mask = index_mask( be, desc, &dbname, &prefix );
86
87         if( mask == 0 ) {
88                 return LDAP_INAPPROPRIATE_MATCHING;
89         }
90
91         return LDAP_SUCCESS;
92 }
93
94 int bdb_index_param(
95         Backend *be,
96         AttributeDescription *desc,
97         int ftype,
98         DB **dbp,
99         slap_mask_t *maskp,
100         struct berval *prefixp )
101 {
102         int rc;
103         slap_mask_t mask;
104         DB *db;
105         char *dbname;
106
107         mask = index_mask( be, desc, &dbname, prefixp );
108
109         if( mask == 0 ) {
110                 return LDAP_INAPPROPRIATE_MATCHING;
111         }
112
113         rc = bdb_db_cache( be, dbname, &db );
114
115         if( rc != LDAP_SUCCESS ) {
116                 return rc;
117         }
118
119         switch( ftype ) {
120         case LDAP_FILTER_PRESENT:
121                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
122                         goto done;
123                 }
124                 break;
125
126         case LDAP_FILTER_APPROX:
127                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
128                         goto done;
129                 }
130                 /* fall thru */
131
132         case LDAP_FILTER_EQUALITY:
133                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
134                         goto done;
135                 }
136                 break;
137
138         case LDAP_FILTER_SUBSTRINGS:
139                 if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
140                         goto done;
141                 }
142                 break;
143
144         default:
145                 return LDAP_OTHER;
146         }
147
148         return LDAP_INAPPROPRIATE_MATCHING;
149
150 done:
151         *dbp = db;
152         *maskp = mask;
153         return LDAP_SUCCESS;
154 }
155
156 static int indexer(
157         Backend *be,
158         DB_TXN *txn,
159         char *dbname,
160         struct berval *atname,
161         BerVarray vals,
162         ID id,
163         int op,
164         slap_mask_t mask )
165 {
166         int rc, i;
167         const char *text;
168         DB *db;
169         AttributeDescription *ad = NULL;
170         struct berval *keys;
171
172         assert( mask );
173
174         rc = bdb_db_cache( be, dbname, &db );
175         
176         if ( rc != LDAP_SUCCESS ) {
177 #ifdef NEW_LOGGING
178                 LDAP_LOG(( "index", LDAP_LEVEL_ERR,
179                         "bdb_index_read: Could not open DB %s\n", dbname));
180 #else
181                 Debug( LDAP_DEBUG_ANY,
182                         "<= bdb_index_read NULL (could not open %s)\n",
183                         dbname, 0, 0 );
184 #endif
185                 return LDAP_OTHER;
186         }
187
188         rc = slap_bv2ad( atname, &ad, &text );
189         if( rc != LDAP_SUCCESS ) return rc;
190
191         if( IS_SLAP_INDEX( mask, SLAP_INDEX_PRESENT ) ) {
192                 rc = bdb_key_change( be, db, txn, &presence_key, id, op );
193                 if( rc ) {
194                         goto done;
195                 }
196         }
197
198         if( IS_SLAP_INDEX( mask, SLAP_INDEX_EQUALITY ) ) {
199                 rc = ad->ad_type->sat_equality->smr_indexer(
200                         LDAP_FILTER_EQUALITY,
201                         mask,
202                         ad->ad_type->sat_syntax,
203                         ad->ad_type->sat_equality,
204                         atname, vals, &keys );
205
206                 if( rc == LDAP_SUCCESS && keys != NULL ) {
207                         for( i=0; keys[i].bv_val != NULL; i++ ) {
208                                 rc = bdb_key_change( be, db, txn, &keys[i], id, op );
209                                 if( rc ) {
210                                         ber_bvarray_free( keys );
211                                         goto done;
212                                 }
213                         }
214                         ber_bvarray_free( keys );
215                 }
216                 rc = LDAP_SUCCESS;
217         }
218
219         if( IS_SLAP_INDEX( mask, SLAP_INDEX_APPROX ) ) {
220                 rc = ad->ad_type->sat_approx->smr_indexer(
221                         LDAP_FILTER_APPROX,
222                         mask,
223                         ad->ad_type->sat_syntax,
224                         ad->ad_type->sat_approx,
225                         atname, vals, &keys );
226
227                 if( rc == LDAP_SUCCESS && keys != NULL ) {
228                         for( i=0; keys[i].bv_val != NULL; i++ ) {
229                                 rc = bdb_key_change( be, db, txn, &keys[i], id, op );
230                                 if( rc ) {
231                                         ber_bvarray_free( keys );
232                                         goto done;
233                                 }
234                         }
235                         ber_bvarray_free( keys );
236                 }
237
238                 rc = LDAP_SUCCESS;
239         }
240
241         if( IS_SLAP_INDEX( mask, SLAP_INDEX_SUBSTR ) ) {
242                 rc = ad->ad_type->sat_substr->smr_indexer(
243                         LDAP_FILTER_SUBSTRINGS,
244                         mask,
245                         ad->ad_type->sat_syntax,
246                         ad->ad_type->sat_substr,
247                         atname, vals, &keys );
248
249                 if( rc == LDAP_SUCCESS && keys != NULL ) {
250                         for( i=0; keys[i].bv_val != NULL; i++ ) {
251                                 bdb_key_change( be, db, txn, &keys[i], id, op );
252                                 if( rc ) {
253                                         ber_bvarray_free( keys );
254                                         goto done;
255                                 }
256                         }
257                         ber_bvarray_free( keys );
258                 }
259
260                 rc = LDAP_SUCCESS;
261         }
262
263 done:
264         return rc;
265 }
266
267 static int index_at_values(
268         Backend *be,
269         DB_TXN *txn,
270         AttributeType *type,
271         struct berval *lang,
272         BerVarray vals,
273         ID id,
274         int op,
275         char ** dbnamep,
276         slap_mask_t *maskp )
277 {
278         int rc;
279         slap_mask_t mask = 0;
280         slap_mask_t tmpmask = 0;
281         int lindex = 0;
282
283         if( type->sat_sup ) {
284                 /* recurse */
285                 rc = index_at_values( be, txn,
286                         type->sat_sup, lang,
287                         vals, id, op,
288                         dbnamep, &tmpmask );
289
290                 if( rc ) return rc;
291         }
292
293         /* If this type has no AD, we've never used it before */
294         if( type->sat_ad ) {
295                 bdb_attr_mask( be->be_private, type->sat_ad, &mask );
296         }
297
298         if( mask ) {
299                 *dbnamep = type->sat_cname.bv_val;
300         } else if ( tmpmask & SLAP_INDEX_AUTO_SUBTYPES ) {
301                 mask = tmpmask;
302         }
303
304         if( mask ) {
305                 rc = indexer( be, txn, *dbnamep,
306                         &type->sat_cname,
307                         vals, id, op,
308                         mask );
309
310                 if( rc ) return rc;
311                 if( mask & SLAP_INDEX_AUTO_SUBTYPES ) {
312                         *maskp = mask;
313                 }
314         }
315
316         if( lang->bv_len ) {
317                 char *dbname = NULL;
318                 struct berval lname;
319                 AttributeDescription *desc;
320
321                 tmpmask = 0;
322                 lname.bv_val = NULL;
323
324                 desc = ad_find_lang( type, lang );
325                 if( desc ) {
326                         bdb_attr_mask( be->be_private, desc, &tmpmask );
327                 }
328
329                 if( tmpmask ) {
330                         dbname = desc->ad_cname.bv_val;
331                         lname = desc->ad_cname;
332                         mask = tmpmask;
333                 }
334
335                 if( dbname != NULL ) {
336                         rc = indexer( be, txn, dbname, &lname,
337                                 vals, id, op,
338                                 mask );
339
340                         if( !tmpmask ) {
341                                 ch_free( lname.bv_val );
342                         }
343                         if( rc ) {
344                                 return rc;
345                         }
346                 }
347         }
348
349         return LDAP_SUCCESS;
350 }
351
352 int bdb_index_values(
353         Backend *be,
354         DB_TXN *txn,
355         AttributeDescription *desc,
356         BerVarray vals,
357         ID id,
358         int op )
359 {
360         int rc;
361         char *dbname = NULL;
362         slap_mask_t mask;
363
364         rc = index_at_values( be, txn,
365                 desc->ad_type, &desc->ad_lang,
366                 vals, id, op,
367                 &dbname, &mask );
368
369         return rc;
370 }
371
372 int
373 bdb_index_entry(
374         Backend *be,
375         DB_TXN *txn,
376         int op,
377         Entry   *e,
378         Attribute *ap )
379 {
380         int rc;
381
382 #ifdef NEW_LOGGING
383         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
384                 "index_entry: %s (%s) %ld\n",
385                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
386                 e->e_dn, (long) e->e_id ));
387 #else
388         Debug( LDAP_DEBUG_TRACE, "=> index_entry_%s( %ld, \"%s\" )\n",
389                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
390                 (long) e->e_id, e->e_dn );
391 #endif
392
393         /* add each attribute to the indexes */
394         for ( ; ap != NULL; ap = ap->a_next ) {
395                 rc = bdb_index_values( be, txn,
396                         ap->a_desc, ap->a_vals, e->e_id, op );
397
398                 if( rc != LDAP_SUCCESS ) {
399 #ifdef NEW_LOGGING
400                         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
401                                 "index_entry: success\n" ));
402 #else
403                         Debug( LDAP_DEBUG_TRACE,
404                                 "<= index_entry_%s( %ld, \"%s\" ) success\n",
405                                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
406                                 (long) e->e_id, e->e_dn );
407 #endif
408                         return rc;
409                 }
410         }
411
412 #ifdef NEW_LOGGING
413         LDAP_LOG(( "index", LDAP_LEVEL_ENTRY,
414                 "index_entry: success\n" ));
415 #else
416         Debug( LDAP_DEBUG_TRACE, "<= index_entry_%s( %ld, \"%s\" ) success\n",
417                 op == SLAP_INDEX_ADD_OP ? "add" : "del",
418                 (long) e->e_id, e->e_dn );
419 #endif
420
421         return LDAP_SUCCESS;
422 }