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