]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
ff04cd3e2a61f5e828b0c6edc520082534c9d4f2
[openldap] / servers / slapd / back-bdb / filterindex.c
1 /* filterindex.c - generate the list of candidate entries from a filter */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2000-2004 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20 #include <ac/string.h>
21
22 #include "back-bdb.h"
23 #include "idl.h"
24
25 static int presence_candidates(
26         Operation *op,
27         AttributeDescription *desc,
28         ID *ids );
29
30 static int equality_candidates(
31         Operation *op,
32         AttributeAssertion *ava,
33         ID *ids,
34         ID *tmp );
35 static int approx_candidates(
36         Operation *op,
37         AttributeAssertion *ava,
38         ID *ids,
39         ID *tmp );
40 static int substring_candidates(
41         Operation *op,
42         SubstringsAssertion *sub,
43         ID *ids,
44         ID *tmp );
45
46 static int list_candidates(
47         Operation *op,
48         Filter *flist,
49         int ftype,
50         ID *ids,
51         ID *tmp,
52         ID *stack );
53
54 int
55 bdb_filter_candidates(
56         Operation *op,
57         Filter  *f,
58         ID *ids,
59         ID *tmp,
60         ID *stack )
61 {
62         int rc = 0;
63         Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
64 #if 0
65         char *subtree="SUBTREE";
66 #endif
67
68         switch ( f->f_choice ) {
69         case SLAPD_FILTER_COMPUTED:
70                 switch( f->f_result ) {
71                 case SLAPD_COMPARE_UNDEFINED:
72                 /* This technically is not the same as FALSE, but it
73                  * certainly will produce no matches.
74                  */
75                 /* FALL THRU */
76                 case LDAP_COMPARE_FALSE:
77                         BDB_IDL_ZERO( ids );
78                         break;
79                 case LDAP_COMPARE_TRUE: {
80                         struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
81                         BDB_IDL_ALL( bdb, ids );
82                         } break;
83                 case LDAP_SUCCESS:
84                         /* this is a pre-computed scope, leave it alone */
85                         break;
86                 }
87                 break;
88 #if 0   /* Not used any more, search calls bdb_dn2idl directly */
89         case SLAPD_FILTER_DN_ONE:
90                 Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
91                 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_ONE_PREFIX, ids,
92                         stack, op->o_tmpmemctx );
93                 if( rc == DB_NOTFOUND ) {
94                         BDB_IDL_ZERO( ids );
95                         rc = 0;
96                 }
97                 break;
98
99         case SLAPD_FILTER_DN_CHILDREN:
100                 subtree="CHILDREN";
101                 /* Fall Thru */
102         case SLAPD_FILTER_DN_SUBTREE:
103                 Debug( LDAP_DEBUG_FILTER, "\tDN %s\n",
104                         subtree, 0, 0 );
105                 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_SUBTREE_PREFIX, ids,
106                         stack, op->o_tmpmemctx );
107                 break;
108 #endif
109         case LDAP_FILTER_PRESENT:
110                 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
111                 rc = presence_candidates( op, f->f_desc, ids );
112                 break;
113
114         case LDAP_FILTER_EQUALITY:
115                 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
116                 rc = equality_candidates( op, f->f_ava, ids, tmp );
117                 break;
118
119         case LDAP_FILTER_APPROX:
120                 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
121                 rc = approx_candidates( op, f->f_ava, ids, tmp );
122                 break;
123
124         case LDAP_FILTER_SUBSTRINGS:
125                 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
126                 rc = substring_candidates( op, f->f_sub, ids, tmp );
127                 break;
128
129         case LDAP_FILTER_GE:
130                 /* no GE index, use pres */
131                 Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
132                 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
133                 break;
134
135         case LDAP_FILTER_LE:
136                 /* no LE index, use pres */
137                 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
138                 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
139                 break;
140
141         case LDAP_FILTER_NOT:
142                 /* no indexing to support NOT filters */
143                 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
144                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
145                 BDB_IDL_ALL( bdb, ids );
146                 }
147                 break;
148
149         case LDAP_FILTER_AND:
150                 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
151                 rc = list_candidates( op, 
152                         f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
153                 break;
154
155         case LDAP_FILTER_OR:
156                 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
157                 rc = list_candidates( op, 
158                         f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
159                 break;
160
161         default:
162                 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
163                         (unsigned long) f->f_choice, 0, 0 );
164                 /* Must not return NULL, otherwise extended filters break */
165                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
166                 BDB_IDL_ALL( bdb, ids );
167                 }
168         }
169
170         Debug( LDAP_DEBUG_FILTER,
171                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
172                 (long) ids[0],
173                 (long) BDB_IDL_FIRST( ids ),
174                 (long) BDB_IDL_LAST( ids ) );
175
176         return rc;
177 }
178
179 static int
180 list_candidates(
181         Operation *op,
182         Filter  *flist,
183         int             ftype,
184         ID *ids,
185         ID *tmp,
186         ID *save )
187 {
188         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
189         int rc = 0;
190         Filter  *f;
191
192         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
193         for ( f = flist; f != NULL; f = f->f_next ) {
194                 /* ignore precomputed scopes */
195                 if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
196                      f->f_result == LDAP_SUCCESS ) {
197                         continue;
198                 }
199                 BDB_IDL_ZERO( save );
200                 rc = bdb_filter_candidates( op, f, save, tmp,
201                         save+BDB_IDL_UM_SIZE );
202
203                 if ( rc != 0 ) {
204                         if ( ftype == LDAP_FILTER_AND ) {
205                                 rc = 0;
206                                 continue;
207                         }
208                         break;
209                 }
210
211                 
212                 if ( ftype == LDAP_FILTER_AND ) {
213                         if ( f == flist ) {
214                                 BDB_IDL_CPY( ids, save );
215                         } else {
216                                 bdb_idl_intersection( ids, save );
217                         }
218                         if( BDB_IDL_IS_ZERO( ids ) )
219                                 break;
220                 } else {
221                         if ( f == flist ) {
222                                 BDB_IDL_CPY( ids, save );
223                         } else {
224                                 bdb_idl_union( ids, save );
225                         }
226                 }
227         }
228
229         if( rc == LDAP_SUCCESS ) {
230                 Debug( LDAP_DEBUG_FILTER,
231                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
232                         (long) ids[0],
233                         (long) BDB_IDL_FIRST(ids),
234                         (long) BDB_IDL_LAST(ids) );
235
236         } else {
237                 Debug( LDAP_DEBUG_FILTER,
238                         "<= bdb_list_candidates: undefined rc=%d\n",
239                         rc, 0, 0 );
240         }
241
242         return rc;
243 }
244
245 static int
246 presence_candidates(
247         Operation *op,
248         AttributeDescription *desc,
249         ID *ids )
250 {
251         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
252         DB *db;
253         int rc;
254         slap_mask_t mask;
255         struct berval prefix = {0, NULL};
256
257         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
258                         desc->ad_cname.bv_val, 0, 0 );
259
260         BDB_IDL_ALL( bdb, ids );
261
262         if( desc == slap_schema.si_ad_objectClass ) {
263                 return 0;
264         }
265
266         rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
267                 &db, &mask, &prefix );
268
269         if( rc != LDAP_SUCCESS ) {
270                 Debug( LDAP_DEBUG_TRACE,
271                         "<= bdb_presence_candidates: (%s) index_param "
272                         "returned=%d\n",
273                         desc->ad_cname.bv_val, rc, 0 );
274                 return 0;
275         }
276
277         if( db == NULL ) {
278                 /* not indexed */
279                 Debug( LDAP_DEBUG_TRACE,
280                         "<= bdb_presence_candidates: (%s) not indexed\n",
281                         desc->ad_cname.bv_val, 0, 0 );
282                 return 0;
283         }
284
285         if( prefix.bv_val == NULL ) {
286                 Debug( LDAP_DEBUG_TRACE,
287                         "<= bdb_presence_candidates: (%s) no prefix\n",
288                         desc->ad_cname.bv_val, 0, 0 );
289                 return -1;
290         }
291
292         rc = bdb_key_read( op->o_bd, db, NULL, &prefix, ids );
293
294         if( rc == DB_NOTFOUND ) {
295                 BDB_IDL_ZERO( ids );
296                 rc = 0;
297         } else if( rc != LDAP_SUCCESS ) {
298                 Debug( LDAP_DEBUG_TRACE,
299                         "<= bdb_presense_candidates: (%s) "
300                         "key read failed (%d)\n",
301                         desc->ad_cname.bv_val, rc, 0 );
302                 goto done;
303         }
304
305         Debug(LDAP_DEBUG_TRACE,
306                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
307                 (long) ids[0],
308                 (long) BDB_IDL_FIRST(ids),
309                 (long) BDB_IDL_LAST(ids) );
310
311 done:
312         return rc;
313 }
314
315 static int
316 equality_candidates(
317         Operation *op,
318         AttributeAssertion *ava,
319         ID *ids,
320         ID *tmp )
321 {
322         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
323         DB      *db;
324         int i;
325         int rc;
326         slap_mask_t mask;
327         struct berval prefix = {0, NULL};
328         struct berval *keys = NULL;
329         MatchingRule *mr;
330
331         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
332                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
333
334         BDB_IDL_ALL( bdb, ids );
335
336         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
337                 &db, &mask, &prefix );
338
339         if( rc != LDAP_SUCCESS ) {
340                 Debug( LDAP_DEBUG_ANY,
341                         "<= bdb_equality_candidates: (%s) "
342                         "index_param failed (%d)\n",
343                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
344                 return 0;
345         }
346
347         if ( db == NULL ) {
348                 Debug( LDAP_DEBUG_ANY,
349                         "<= bdb_equality_candidates: (%s) not indexed\n", 
350                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
351                 return 0;
352         }
353
354         mr = ava->aa_desc->ad_type->sat_equality;
355         if( !mr ) {
356                 return 0;
357         }
358
359         if( !mr->smr_filter ) {
360                 return 0;
361         }
362
363         rc = (mr->smr_filter)(
364                 LDAP_FILTER_EQUALITY,
365                 mask,
366                 ava->aa_desc->ad_type->sat_syntax,
367                 mr,
368                 &prefix,
369                 &ava->aa_value,
370                 &keys, op->o_tmpmemctx );
371
372         if( rc != LDAP_SUCCESS ) {
373                 Debug( LDAP_DEBUG_TRACE,
374                         "<= bdb_equality_candidates: (%s, %s) "
375                         "MR filter failed (%d)\n",
376                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
377                 return 0;
378         }
379
380         if( keys == NULL ) {
381                 Debug( LDAP_DEBUG_TRACE,
382                         "<= bdb_equality_candidates: (%s) no keys\n",
383                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
384                 return 0;
385         }
386
387         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
388                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
389
390                 if( rc == DB_NOTFOUND ) {
391                         BDB_IDL_ZERO( ids );
392                         rc = 0;
393                         break;
394                 } else if( rc != LDAP_SUCCESS ) {
395                         Debug( LDAP_DEBUG_TRACE,
396                                 "<= bdb_equality_candidates: (%s) "
397                                 "key read failed (%d)\n",
398                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
399                         break;
400                 }
401
402                 if( BDB_IDL_IS_ZERO( tmp ) ) {
403                         Debug( LDAP_DEBUG_TRACE,
404                                 "<= bdb_equality_candidates: (%s) NULL\n", 
405                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
406                         BDB_IDL_ZERO( ids );
407                         break;
408                 }
409
410                 if ( i == 0 ) {
411                         BDB_IDL_CPY( ids, tmp );
412                 } else {
413                         bdb_idl_intersection( ids, tmp );
414                 }
415
416                 if( BDB_IDL_IS_ZERO( ids ) )
417                         break;
418         }
419
420         ber_bvarray_free_x( keys, op->o_tmpmemctx );
421
422         Debug( LDAP_DEBUG_TRACE,
423                 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
424                 (long) ids[0],
425                 (long) BDB_IDL_FIRST(ids),
426                 (long) BDB_IDL_LAST(ids) );
427         return( rc );
428 }
429
430
431 static int
432 approx_candidates(
433         Operation *op,
434         AttributeAssertion *ava,
435         ID *ids,
436         ID *tmp )
437 {
438         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
439         DB      *db;
440         int i;
441         int rc;
442         slap_mask_t mask;
443         struct berval prefix = {0, NULL};
444         struct berval *keys = NULL;
445         MatchingRule *mr;
446
447         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
448                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
449
450         BDB_IDL_ALL( bdb, ids );
451
452         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
453                 &db, &mask, &prefix );
454
455         if( rc != LDAP_SUCCESS ) {
456                 Debug( LDAP_DEBUG_ANY,
457                         "<= bdb_approx_candidates: (%s) "
458                         "index_param failed (%d)\n",
459                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
460                 return 0;
461         }
462
463         if ( db == NULL ) {
464                 Debug( LDAP_DEBUG_ANY,
465                         "<= bdb_approx_candidates: (%s) not indexed\n",
466                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
467                 return 0;
468         }
469
470         mr = ava->aa_desc->ad_type->sat_approx;
471         if( !mr ) {
472                 /* no approx matching rule, try equality matching rule */
473                 mr = ava->aa_desc->ad_type->sat_equality;
474         }
475
476         if( !mr ) {
477                 return 0;
478         }
479
480         if( !mr->smr_filter ) {
481                 return 0;
482         }
483
484         rc = (mr->smr_filter)(
485                 LDAP_FILTER_APPROX,
486                 mask,
487                 ava->aa_desc->ad_type->sat_syntax,
488                 mr,
489                 &prefix,
490                 &ava->aa_value,
491                 &keys, op->o_tmpmemctx );
492
493         if( rc != LDAP_SUCCESS ) {
494                 Debug( LDAP_DEBUG_TRACE,
495                         "<= bdb_approx_candidates: (%s, %s) "
496                         "MR filter failed (%d)\n",
497                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
498                 return 0;
499         }
500
501         if( keys == NULL ) {
502                 Debug( LDAP_DEBUG_TRACE,
503                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
504                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
505                 return 0;
506         }
507
508         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
509                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
510
511                 if( rc == DB_NOTFOUND ) {
512                         BDB_IDL_ZERO( ids );
513                         rc = 0;
514                         break;
515                 } else if( rc != LDAP_SUCCESS ) {
516                         Debug( LDAP_DEBUG_TRACE,
517                                 "<= bdb_approx_candidates: (%s) "
518                                 "key read failed (%d)\n",
519                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
520                         break;
521                 }
522
523                 if( BDB_IDL_IS_ZERO( tmp ) ) {
524                         Debug( LDAP_DEBUG_TRACE,
525                                 "<= bdb_approx_candidates: (%s) NULL\n",
526                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
527                         BDB_IDL_ZERO( ids );
528                         break;
529                 }
530
531                 if ( i == 0 ) {
532                         BDB_IDL_CPY( ids, tmp );
533                 } else {
534                         bdb_idl_intersection( ids, tmp );
535                 }
536
537                 if( BDB_IDL_IS_ZERO( ids ) )
538                         break;
539         }
540
541         ber_bvarray_free_x( keys, op->o_tmpmemctx );
542
543         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
544                 (long) ids[0],
545                 (long) BDB_IDL_FIRST(ids),
546                 (long) BDB_IDL_LAST(ids) );
547         return( rc );
548 }
549
550 static int
551 substring_candidates(
552         Operation *op,
553         SubstringsAssertion     *sub,
554         ID *ids,
555         ID *tmp )
556 {
557         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
558         DB      *db;
559         int i;
560         int rc;
561         slap_mask_t mask;
562         struct berval prefix = {0, NULL};
563         struct berval *keys = NULL;
564         MatchingRule *mr;
565
566         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
567                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
568
569         BDB_IDL_ALL( bdb, ids );
570
571         rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
572                 &db, &mask, &prefix );
573
574         if( rc != LDAP_SUCCESS ) {
575                 Debug( LDAP_DEBUG_ANY,
576                         "<= bdb_substring_candidates: (%s) "
577                         "index_param failed (%d)\n",
578                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
579                 return 0;
580         }
581
582         if ( db == NULL ) {
583                 Debug( LDAP_DEBUG_ANY,
584                         "<= bdb_substring_candidates: (%s) not indexed\n",
585                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
586                 return 0;
587         }
588
589         mr = sub->sa_desc->ad_type->sat_substr;
590
591         if( !mr ) {
592                 return 0;
593         }
594
595         if( !mr->smr_filter ) {
596                 return 0;
597         }
598
599         rc = (mr->smr_filter)(
600                 LDAP_FILTER_SUBSTRINGS,
601                 mask,
602                 sub->sa_desc->ad_type->sat_syntax,
603                 mr,
604                 &prefix,
605                 sub,
606                 &keys, op->o_tmpmemctx );
607
608         if( rc != LDAP_SUCCESS ) {
609                 Debug( LDAP_DEBUG_TRACE,
610                         "<= bdb_substring_candidates: (%s) "
611                         "MR filter failed (%d)\n",
612                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
613                 return 0;
614         }
615
616         if( keys == NULL ) {
617                 Debug( LDAP_DEBUG_TRACE,
618                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
619                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
620                 return 0;
621         }
622
623         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
624                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
625
626                 if( rc == DB_NOTFOUND ) {
627                         BDB_IDL_ZERO( ids );
628                         rc = 0;
629                         break;
630                 } else if( rc != LDAP_SUCCESS ) {
631                         Debug( LDAP_DEBUG_TRACE,
632                                 "<= bdb_substring_candidates: (%s) "
633                                 "key read failed (%d)\n",
634                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
635                         break;
636                 }
637
638                 if( BDB_IDL_IS_ZERO( tmp ) ) {
639                         Debug( LDAP_DEBUG_TRACE,
640                                 "<= bdb_substring_candidates: (%s) NULL\n",
641                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
642                         BDB_IDL_ZERO( ids );
643                         break;
644                 }
645
646                 if ( i == 0 ) {
647                         BDB_IDL_CPY( ids, tmp );
648                 } else {
649                         bdb_idl_intersection( ids, tmp );
650                 }
651
652                 if( BDB_IDL_IS_ZERO( ids ) )
653                         break;
654         }
655
656         ber_bvarray_free_x( keys, op->o_tmpmemctx );
657
658         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
659                 (long) ids[0],
660                 (long) BDB_IDL_FIRST(ids),
661                 (long) BDB_IDL_LAST(ids) );
662         return( rc );
663 }
664