]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/filterindex.c
add paged results support to back-ldap
[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 #ifdef NEW_LOGGING
64         LDAP_LOG ( INDEX, ENTRY, "=> bdb_filter_candidates\n", 0, 0, 0 );
65 #else
66         Debug( LDAP_DEBUG_FILTER, "=> bdb_filter_candidates\n", 0, 0, 0 );
67 #endif
68 #if 0
69         char *subtree="SUBTREE";
70 #endif
71
72         switch ( f->f_choice ) {
73         case SLAPD_FILTER_COMPUTED:
74                 switch( f->f_result ) {
75                 case SLAPD_COMPARE_UNDEFINED:
76                 /* This technically is not the same as FALSE, but it
77                  * certainly will produce no matches.
78                  */
79                 /* FALL THRU */
80                 case LDAP_COMPARE_FALSE:
81                         BDB_IDL_ZERO( ids );
82                         break;
83                 case LDAP_COMPARE_TRUE: {
84                         struct bdb_info *bdb = (struct bdb_info *)op->o_bd->be_private;
85                         BDB_IDL_ALL( bdb, ids );
86                         } break;
87                 case LDAP_SUCCESS:
88                         /* this is a pre-computed scope, leave it alone */
89                         break;
90                 }
91                 break;
92 #if 0   /* Not used any more, search calls bdb_dn2idl directly */
93         case SLAPD_FILTER_DN_ONE:
94 #ifdef NEW_LOGGING
95                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN ONE\n",
96                         0, 0, 0 );
97 #else
98                 Debug( LDAP_DEBUG_FILTER, "\tDN ONE\n", 0, 0, 0 );
99 #endif
100                 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_ONE_PREFIX, ids,
101                         stack, op->o_tmpmemctx );
102                 if( rc == DB_NOTFOUND ) {
103                         BDB_IDL_ZERO( ids );
104                         rc = 0;
105                 }
106                 break;
107
108         case SLAPD_FILTER_DN_CHILDREN:
109                 subtree="CHILDREN";
110                 /* Fall Thru */
111         case SLAPD_FILTER_DN_SUBTREE:
112 #ifdef NEW_LOGGING
113                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tDN %s\n",
114                         subtree, 0, 0 );
115 #else
116                 Debug( LDAP_DEBUG_FILTER, "\tDN %s\n",
117                         subtree, 0, 0 );
118 #endif
119                 rc = bdb_dn2idl( op->o_bd, f->f_dn, DN_SUBTREE_PREFIX, ids,
120                         stack, op->o_tmpmemctx );
121                 break;
122 #endif
123         case LDAP_FILTER_PRESENT:
124 #ifdef NEW_LOGGING
125                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tPRESENT\n",
126                         0, 0, 0 );
127 #else
128                 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
129 #endif
130                 rc = presence_candidates( op, f->f_desc, ids );
131                 break;
132
133         case LDAP_FILTER_EQUALITY:
134 #ifdef NEW_LOGGING
135                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tEQUALITY\n",
136                         0, 0, 0 );
137 #else
138                 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
139 #endif
140                 rc = equality_candidates( op, f->f_ava, ids, tmp );
141                 break;
142
143         case LDAP_FILTER_APPROX:
144 #ifdef NEW_LOGGING
145                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAPPROX\n",
146                         0, 0, 0 );
147 #else
148                 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
149 #endif
150                 rc = approx_candidates( op, f->f_ava, ids, tmp );
151                 break;
152
153         case LDAP_FILTER_SUBSTRINGS:
154 #ifdef NEW_LOGGING
155                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tSUBSTRINGS\n",
156                         0, 0, 0 );
157 #else
158                 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
159 #endif
160                 rc = substring_candidates( op, f->f_sub, ids, tmp );
161                 break;
162
163         case LDAP_FILTER_GE:
164                 /* no GE index, use pres */
165 #ifdef NEW_LOGGING
166                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tGE\n",
167                         0, 0, 0 );
168 #else
169                 Debug( LDAP_DEBUG_FILTER, "\tGE\n", 0, 0, 0 );
170 #endif
171                 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
172                 break;
173
174         case LDAP_FILTER_LE:
175                 /* no LE index, use pres */
176 #ifdef NEW_LOGGING
177                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tLE\n",
178                         0, 0, 0 );
179 #else
180                 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
181 #endif
182                 rc = presence_candidates( op, f->f_ava->aa_desc, ids );
183                 break;
184
185         case LDAP_FILTER_NOT:
186                 /* no indexing to support NOT filters */
187 #ifdef NEW_LOGGING
188                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tNOT\n",
189                         0, 0, 0 );
190 #else
191                 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
192 #endif
193                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
194                 BDB_IDL_ALL( bdb, ids );
195                 }
196                 break;
197
198         case LDAP_FILTER_AND:
199 #ifdef NEW_LOGGING
200                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tAND\n",
201                         0, 0, 0 );
202 #else
203                 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
204 #endif
205                 rc = list_candidates( op, 
206                         f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
207                 break;
208
209         case LDAP_FILTER_OR:
210 #ifdef NEW_LOGGING
211                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tOR\n",
212                         0, 0, 0 );
213 #else
214                 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
215 #endif
216                 rc = list_candidates( op, 
217                         f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
218                 break;
219
220         default:
221 #ifdef NEW_LOGGING
222                 LDAP_LOG ( INDEX, ARGS, "=> bdb_filter_candidates: \tUNKNOWN\n",
223                         0, 0, 0 );
224 #else
225                 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
226                         (unsigned long) f->f_choice, 0, 0 );
227 #endif
228                 /* Must not return NULL, otherwise extended filters break */
229                 { struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
230                 BDB_IDL_ALL( bdb, ids );
231                 }
232         }
233
234 #ifdef NEW_LOGGING
235         LDAP_LOG ( INDEX, RESULTS, 
236                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n", 
237                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long) BDB_IDL_LAST( ids ));
238 #else
239         Debug( LDAP_DEBUG_FILTER,
240                 "<= bdb_filter_candidates: id=%ld first=%ld last=%ld\n",
241                 (long) ids[0],
242                 (long) BDB_IDL_FIRST( ids ),
243                 (long) BDB_IDL_LAST( ids ) );
244 #endif
245
246         return rc;
247 }
248
249 static int
250 list_candidates(
251         Operation *op,
252         Filter  *flist,
253         int             ftype,
254         ID *ids,
255         ID *tmp,
256         ID *save )
257 {
258         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
259         int rc = 0;
260         Filter  *f;
261
262 #ifdef NEW_LOGGING
263         LDAP_LOG ( INDEX, ARGS, "=> bdb_list_candidates: 0x%x\n", ftype, 0 , 0 );
264 #else
265         Debug( LDAP_DEBUG_FILTER, "=> bdb_list_candidates 0x%x\n", ftype, 0, 0 );
266 #endif
267         for ( f = flist; f != NULL; f = f->f_next ) {
268                 /* ignore precomputed scopes */
269                 if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
270                      f->f_result == LDAP_SUCCESS ) {
271                         continue;
272                 }
273                 BDB_IDL_ZERO( save );
274                 rc = bdb_filter_candidates( op, f, save, tmp,
275                         save+BDB_IDL_UM_SIZE );
276
277                 if ( rc != 0 ) {
278                         if ( ftype == LDAP_FILTER_AND ) {
279                                 rc = 0;
280                                 continue;
281                         }
282                         break;
283                 }
284
285                 
286                 if ( ftype == LDAP_FILTER_AND ) {
287                         if ( f == flist ) {
288                                 BDB_IDL_CPY( ids, save );
289                         } else {
290                                 bdb_idl_intersection( ids, save );
291                         }
292                         if( BDB_IDL_IS_ZERO( ids ) )
293                                 break;
294                 } else {
295                         if ( f == flist ) {
296                                 BDB_IDL_CPY( ids, save );
297                         } else {
298                                 bdb_idl_union( ids, save );
299                         }
300                 }
301         }
302
303         if( rc == LDAP_SUCCESS ) {
304 #ifdef NEW_LOGGING
305                 LDAP_LOG ( INDEX, RESULTS, 
306                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
307                         (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
308                         (long) BDB_IDL_LAST( ids ) );
309 #else
310                 Debug( LDAP_DEBUG_FILTER,
311                         "<= bdb_list_candidates: id=%ld first=%ld last=%ld\n",
312                         (long) ids[0],
313                         (long) BDB_IDL_FIRST(ids),
314                         (long) BDB_IDL_LAST(ids) );
315 #endif
316
317         } else {
318 #ifdef NEW_LOGGING
319                 LDAP_LOG ( INDEX, ARGS, "<= bdb_list_candidates: rc=%d\n", rc, 0, 0 );
320 #else
321                 Debug( LDAP_DEBUG_FILTER,
322                         "<= bdb_list_candidates: undefined rc=%d\n",
323                         rc, 0, 0 );
324 #endif
325         }
326
327         return rc;
328 }
329
330 static int
331 presence_candidates(
332         Operation *op,
333         AttributeDescription *desc,
334         ID *ids )
335 {
336         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
337         DB *db;
338         int rc;
339         slap_mask_t mask;
340         struct berval prefix = {0, NULL};
341
342 #ifdef NEW_LOGGING
343         LDAP_LOG ( INDEX, ENTRY, "=> bdb_presence_candidates (%s)\n", 
344                         desc->ad_cname.bv_val, 0, 0 );
345 #else
346         Debug( LDAP_DEBUG_TRACE, "=> bdb_presence_candidates (%s)\n",
347                         desc->ad_cname.bv_val, 0, 0 );
348 #endif
349
350         BDB_IDL_ALL( bdb, ids );
351
352         if( desc == slap_schema.si_ad_objectClass ) {
353                 return 0;
354         }
355
356         rc = bdb_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
357                 &db, &mask, &prefix );
358
359         if( rc != LDAP_SUCCESS ) {
360 #ifdef NEW_LOGGING
361                 LDAP_LOG ( INDEX, RESULTS, 
362                         "<= bdb_presence_candidates: (%s) index_param "
363                         "returned=%d\n",
364                         desc->ad_cname.bv_val, rc, 0 );
365 #else
366                 Debug( LDAP_DEBUG_TRACE,
367                         "<= bdb_presence_candidates: (%s) index_param "
368                         "returned=%d\n",
369                         desc->ad_cname.bv_val, rc, 0 );
370 #endif
371                 return 0;
372         }
373
374         if( db == NULL ) {
375                 /* not indexed */
376 #ifdef NEW_LOGGING
377                 LDAP_LOG(INDEX, RESULTS, 
378                         "<= bdb_presence_candidates: (%s) not indexed\n",
379                         desc->ad_cname.bv_val, 0, 0 );
380 #else
381                 Debug( LDAP_DEBUG_TRACE,
382                         "<= bdb_presence_candidates: (%s) not indexed\n",
383                         desc->ad_cname.bv_val, 0, 0 );
384 #endif
385                 return 0;
386         }
387
388         if( prefix.bv_val == NULL ) {
389 #ifdef NEW_LOGGING
390                 LDAP_LOG(INDEX, RESULTS, 
391                         "<= bdb_presence_candidates: (%s) no prefix\n",
392                         desc->ad_cname.bv_val, 0, 0 );
393 #else
394                 Debug( LDAP_DEBUG_TRACE,
395                         "<= bdb_presence_candidates: (%s) no prefix\n",
396                         desc->ad_cname.bv_val, 0, 0 );
397 #endif
398                 return -1;
399         }
400
401         rc = bdb_key_read( op->o_bd, db, NULL, &prefix, ids );
402
403         if( rc == DB_NOTFOUND ) {
404                 BDB_IDL_ZERO( ids );
405                 rc = 0;
406         } else if( rc != LDAP_SUCCESS ) {
407 #ifdef NEW_LOGGING
408                 LDAP_LOG ( INDEX, RESULTS, 
409                         "<= bdb_presence_candidates: (%s) "
410                         "key read failed (%d)\n",
411                         desc->ad_cname.bv_val, rc, 0 );
412 #else
413                 Debug( LDAP_DEBUG_TRACE,
414                         "<= bdb_presense_candidates: (%s) "
415                         "key read failed (%d)\n",
416                         desc->ad_cname.bv_val, rc, 0 );
417 #endif
418                 goto done;
419         }
420
421 #ifdef NEW_LOGGING
422         LDAP_LOG ( INDEX, RESULTS, 
423                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
424                 (long)ids[0], (long)BDB_IDL_FIRST( ids ), (long)BDB_IDL_LAST( ids ) );
425 #else
426         Debug(LDAP_DEBUG_TRACE,
427                 "<= bdb_presence_candidates: id=%ld first=%ld last=%ld\n",
428                 (long) ids[0],
429                 (long) BDB_IDL_FIRST(ids),
430                 (long) BDB_IDL_LAST(ids) );
431 #endif
432
433 done:
434         return rc;
435 }
436
437 static int
438 equality_candidates(
439         Operation *op,
440         AttributeAssertion *ava,
441         ID *ids,
442         ID *tmp )
443 {
444         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
445         DB      *db;
446         int i;
447         int rc;
448         slap_mask_t mask;
449         struct berval prefix = {0, NULL};
450         struct berval *keys = NULL;
451         MatchingRule *mr;
452
453 #ifdef NEW_LOGGING
454         LDAP_LOG ( INDEX, ENTRY, "=> bdb_equality_candidates (%s)\n",
455                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
456 #else
457         Debug( LDAP_DEBUG_TRACE, "=> bdb_equality_candidates (%s)\n",
458                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
459 #endif
460
461         BDB_IDL_ALL( bdb, ids );
462
463         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
464                 &db, &mask, &prefix );
465
466         if( rc != LDAP_SUCCESS ) {
467 #ifdef NEW_LOGGING
468                 LDAP_LOG ( INDEX, RESULTS, 
469                         "<= bdb_equality_candidates: (%s) "
470                         "index_param failed (%d)\n", 
471                         ava->aa_desc->ad_cname.bv_val, rc, 0);
472 #else
473                 Debug( LDAP_DEBUG_ANY,
474                         "<= bdb_equality_candidates: (%s) "
475                         "index_param failed (%d)\n",
476                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
477 #endif
478                 return 0;
479         }
480
481         if ( db == NULL ) {
482 #ifdef NEW_LOGGING
483                 LDAP_LOG(INDEX, RESULTS, 
484                         "<= bdb_equality_candidates: (%s) not indexed\n", 
485                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
486 #else
487                 Debug( LDAP_DEBUG_ANY,
488                         "<= bdb_equality_candidates: (%s) not indexed\n", 
489                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
490 #endif
491                 return 0;
492         }
493
494         mr = ava->aa_desc->ad_type->sat_equality;
495         if( !mr ) {
496                 return 0;
497         }
498
499         if( !mr->smr_filter ) {
500                 return 0;
501         }
502
503         rc = (mr->smr_filter)(
504                 LDAP_FILTER_EQUALITY,
505                 mask,
506                 ava->aa_desc->ad_type->sat_syntax,
507                 mr,
508                 &prefix,
509                 &ava->aa_value,
510                 &keys, op->o_tmpmemctx );
511
512         if( rc != LDAP_SUCCESS ) {
513 #ifdef NEW_LOGGING
514                 LDAP_LOG ( INDEX, RESULTS, 
515                         "<= bdb_equality_candidates: (%s, %s) "
516                         "MR filter failed (%d)\n",
517                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
518 #else
519                 Debug( LDAP_DEBUG_TRACE,
520                         "<= bdb_equality_candidates: (%s, %s) "
521                         "MR filter failed (%d)\n",
522                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
523 #endif
524                 return 0;
525         }
526
527         if( keys == NULL ) {
528 #ifdef NEW_LOGGING
529                 LDAP_LOG ( INDEX, RESULTS, 
530                         "<= bdb_equality_candidates: (%s) no keys\n", 
531                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
532 #else
533                 Debug( LDAP_DEBUG_TRACE,
534                         "<= bdb_equality_candidates: (%s) no keys\n",
535                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
536 #endif
537                 return 0;
538         }
539
540         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
541                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
542
543                 if( rc == DB_NOTFOUND ) {
544                         BDB_IDL_ZERO( ids );
545                         rc = 0;
546                         break;
547                 } else if( rc != LDAP_SUCCESS ) {
548 #ifdef NEW_LOGGING
549                         LDAP_LOG ( INDEX, RESULTS, 
550                                 "<= bdb_equality_candidates: (%s) "
551                                 "key read failed (%d)\n",
552                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
553 #else
554                         Debug( LDAP_DEBUG_TRACE,
555                                 "<= bdb_equality_candidates: (%s) "
556                                 "key read failed (%d)\n",
557                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
558 #endif
559                         break;
560                 }
561
562                 if( BDB_IDL_IS_ZERO( tmp ) ) {
563 #ifdef NEW_LOGGING
564                         LDAP_LOG ( INDEX, RESULTS,
565                                 "<= bdb_equality_candidates: (%s) NULL\n",
566                                 ava->aa_desc->ad_cname.bv_val, 0, 0);
567 #else
568                         Debug( LDAP_DEBUG_TRACE,
569                                 "<= bdb_equality_candidates: (%s) NULL\n", 
570                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
571 #endif
572                         BDB_IDL_ZERO( ids );
573                         break;
574                 }
575
576                 if ( i == 0 ) {
577                         BDB_IDL_CPY( ids, tmp );
578                 } else {
579                         bdb_idl_intersection( ids, tmp );
580                 }
581
582                 if( BDB_IDL_IS_ZERO( ids ) )
583                         break;
584         }
585
586         ber_bvarray_free_x( keys, op->o_tmpmemctx );
587
588 #ifdef NEW_LOGGING
589         LDAP_LOG ( INDEX, RESULTS, 
590                 "<= bdb_equality_candidates: id=%ld first=%ld last=%ld\n", 
591                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
592                 (long) BDB_IDL_LAST( ids ) );
593 #else
594         Debug( LDAP_DEBUG_TRACE,
595                 "<= bdb_equality_candidates: id=%ld, first=%ld, last=%ld\n",
596                 (long) ids[0],
597                 (long) BDB_IDL_FIRST(ids),
598                 (long) BDB_IDL_LAST(ids) );
599 #endif
600         return( rc );
601 }
602
603
604 static int
605 approx_candidates(
606         Operation *op,
607         AttributeAssertion *ava,
608         ID *ids,
609         ID *tmp )
610 {
611         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
612         DB      *db;
613         int i;
614         int rc;
615         slap_mask_t mask;
616         struct berval prefix = {0, NULL};
617         struct berval *keys = NULL;
618         MatchingRule *mr;
619
620 #ifdef NEW_LOGGING
621         LDAP_LOG ( INDEX, ENTRY, "=> bdb_approx_candidates (%s)\n",
622                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
623 #else
624         Debug( LDAP_DEBUG_TRACE, "=> bdb_approx_candidates (%s)\n",
625                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
626 #endif
627
628         BDB_IDL_ALL( bdb, ids );
629
630         rc = bdb_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
631                 &db, &mask, &prefix );
632
633         if( rc != LDAP_SUCCESS ) {
634 #ifdef NEW_LOGGING
635                 LDAP_LOG ( INDEX, RESULTS, 
636                         "<= bdb_approx_candidates: (%s) "
637                         "index_param failed (%d)\n",
638                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
639 #else
640                 Debug( LDAP_DEBUG_ANY,
641                         "<= bdb_approx_candidates: (%s) "
642                         "index_param failed (%d)\n",
643                         ava->aa_desc->ad_cname.bv_val, rc, 0 );
644 #endif
645                 return 0;
646         }
647
648         if ( db == NULL ) {
649 #ifdef NEW_LOGGING
650                 LDAP_LOG(INDEX, RESULTS, 
651                         "<= bdb_approx_candidates: (%s) not indexed\n",
652                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
653 #else
654                 Debug( LDAP_DEBUG_ANY,
655                         "<= bdb_approx_candidates: (%s) not indexed\n",
656                         ava->aa_desc->ad_cname.bv_val, 0, 0 );
657 #endif
658                 return 0;
659         }
660
661         mr = ava->aa_desc->ad_type->sat_approx;
662         if( !mr ) {
663                 /* no approx matching rule, try equality matching rule */
664                 mr = ava->aa_desc->ad_type->sat_equality;
665         }
666
667         if( !mr ) {
668                 return 0;
669         }
670
671         if( !mr->smr_filter ) {
672                 return 0;
673         }
674
675         rc = (mr->smr_filter)(
676                 LDAP_FILTER_APPROX,
677                 mask,
678                 ava->aa_desc->ad_type->sat_syntax,
679                 mr,
680                 &prefix,
681                 &ava->aa_value,
682                 &keys, op->o_tmpmemctx );
683
684         if( rc != LDAP_SUCCESS ) {
685 #ifdef NEW_LOGGING
686                 LDAP_LOG ( INDEX, RESULTS, 
687                         "<= bdb_approx_candidates: (%s, %s) "
688                         "MR filter failed (%d)\n",
689                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
690 #else
691                 Debug( LDAP_DEBUG_TRACE,
692                         "<= bdb_approx_candidates: (%s, %s) "
693                         "MR filter failed (%d)\n",
694                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
695 #endif
696                 return 0;
697         }
698
699         if( keys == NULL ) {
700 #ifdef NEW_LOGGING
701                 LDAP_LOG ( INDEX, RESULTS, 
702                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
703                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
704 #else
705                 Debug( LDAP_DEBUG_TRACE,
706                         "<= bdb_approx_candidates: (%s) no keys (%s)\n",
707                         prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
708 #endif
709                 return 0;
710         }
711
712         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
713                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
714
715                 if( rc == DB_NOTFOUND ) {
716                         BDB_IDL_ZERO( ids );
717                         rc = 0;
718                         break;
719                 } else if( rc != LDAP_SUCCESS ) {
720 #ifdef NEW_LOGGING
721                         LDAP_LOG ( INDEX, RESULTS, 
722                                 "<= bdb_approx_candidates: (%s) "
723                                 "key read failed (%d)\n",
724                                 ava->aa_desc->ad_cname.bv_val, rc, 0);
725 #else
726                         Debug( LDAP_DEBUG_TRACE,
727                                 "<= bdb_approx_candidates: (%s) "
728                                 "key read failed (%d)\n",
729                                 ava->aa_desc->ad_cname.bv_val, rc, 0 );
730 #endif
731                         break;
732                 }
733
734                 if( BDB_IDL_IS_ZERO( tmp ) ) {
735 #ifdef NEW_LOGGING
736                         LDAP_LOG ( INDEX, RESULTS, 
737                                 "<= bdb_approx_candidates: (%s) NULL\n",
738                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
739 #else
740                         Debug( LDAP_DEBUG_TRACE,
741                                 "<= bdb_approx_candidates: (%s) NULL\n",
742                                 ava->aa_desc->ad_cname.bv_val, 0, 0 );
743 #endif
744                         BDB_IDL_ZERO( ids );
745                         break;
746                 }
747
748                 if ( i == 0 ) {
749                         BDB_IDL_CPY( ids, tmp );
750                 } else {
751                         bdb_idl_intersection( ids, tmp );
752                 }
753
754                 if( BDB_IDL_IS_ZERO( ids ) )
755                         break;
756         }
757
758         ber_bvarray_free_x( keys, op->o_tmpmemctx );
759
760 #ifdef NEW_LOGGING
761         LDAP_LOG ( INDEX, RESULTS, 
762                 "<= bdb_approx_candidates: id=%ld first=%ld last=%ld\n", 
763                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
764                 (long) BDB_IDL_LAST( ids ) );
765 #else
766         Debug( LDAP_DEBUG_TRACE, "<= bdb_approx_candidates %ld, first=%ld, last=%ld\n",
767                 (long) ids[0],
768                 (long) BDB_IDL_FIRST(ids),
769                 (long) BDB_IDL_LAST(ids) );
770 #endif
771         return( rc );
772 }
773
774 static int
775 substring_candidates(
776         Operation *op,
777         SubstringsAssertion     *sub,
778         ID *ids,
779         ID *tmp )
780 {
781         struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
782         DB      *db;
783         int i;
784         int rc;
785         slap_mask_t mask;
786         struct berval prefix = {0, NULL};
787         struct berval *keys = NULL;
788         MatchingRule *mr;
789
790 #ifdef NEW_LOGGING
791         LDAP_LOG ( INDEX, ENTRY, "=> bdb_substring_candidates (%s)\n",
792                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
793 #else
794         Debug( LDAP_DEBUG_TRACE, "=> bdb_substring_candidates (%s)\n",
795                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
796 #endif
797
798         BDB_IDL_ALL( bdb, ids );
799
800         rc = bdb_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
801                 &db, &mask, &prefix );
802
803         if( rc != LDAP_SUCCESS ) {
804 #ifdef NEW_LOGGING
805                 LDAP_LOG ( INDEX, RESULTS, 
806                         "<= bdb_substring_candidates: (%s) "
807                         "index_param failed (%d)\n",
808                         sub->sa_desc->ad_cname.bv_val, rc, 0);
809 #else
810                 Debug( LDAP_DEBUG_ANY,
811                         "<= bdb_substring_candidates: (%s) "
812                         "index_param failed (%d)\n",
813                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
814 #endif
815                 return 0;
816         }
817
818         if ( db == NULL ) {
819 #ifdef NEW_LOGGING
820                 LDAP_LOG ( INDEX, RESULTS, 
821                         "<= bdb_substring_candidates: (%s) not indexed\n",
822                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
823 #else
824                 Debug( LDAP_DEBUG_ANY,
825                         "<= bdb_substring_candidates: (%s) not indexed\n",
826                         sub->sa_desc->ad_cname.bv_val, 0, 0 );
827 #endif
828                 return 0;
829         }
830
831         mr = sub->sa_desc->ad_type->sat_substr;
832
833         if( !mr ) {
834                 return 0;
835         }
836
837         if( !mr->smr_filter ) {
838                 return 0;
839         }
840
841         rc = (mr->smr_filter)(
842                 LDAP_FILTER_SUBSTRINGS,
843                 mask,
844                 sub->sa_desc->ad_type->sat_syntax,
845                 mr,
846                 &prefix,
847                 sub,
848                 &keys, op->o_tmpmemctx );
849
850         if( rc != LDAP_SUCCESS ) {
851 #ifdef NEW_LOGGING
852                 LDAP_LOG ( INDEX, RESULTS, 
853                         "<= bdb_substring_candidates: (%s) "
854                         "MR filter failed (%d)\n", 
855                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
856 #else
857                 Debug( LDAP_DEBUG_TRACE,
858                         "<= bdb_substring_candidates: (%s) "
859                         "MR filter failed (%d)\n",
860                         sub->sa_desc->ad_cname.bv_val, rc, 0 );
861 #endif
862                 return 0;
863         }
864
865         if( keys == NULL ) {
866 #ifdef NEW_LOGGING
867                 LDAP_LOG ( INDEX, RESULTS, 
868                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
869                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
870 #else
871                 Debug( LDAP_DEBUG_TRACE,
872                         "<= bdb_substring_candidates: (0x%04lx) no keys (%s)\n",
873                         mask, sub->sa_desc->ad_cname.bv_val, 0 );
874 #endif
875                 return 0;
876         }
877
878         for ( i= 0; keys[i].bv_val != NULL; i++ ) {
879                 rc = bdb_key_read( op->o_bd, db, NULL, &keys[i], tmp );
880
881                 if( rc == DB_NOTFOUND ) {
882                         BDB_IDL_ZERO( ids );
883                         rc = 0;
884                         break;
885                 } else if( rc != LDAP_SUCCESS ) {
886 #ifdef NEW_LOGGING
887                         LDAP_LOG ( INDEX, RESULTS, 
888                                 "<= bdb_substring_candidates: (%s) "
889                                 "key read failed (%d)\n",
890                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
891 #else
892                         Debug( LDAP_DEBUG_TRACE,
893                                 "<= bdb_substring_candidates: (%s) "
894                                 "key read failed (%d)\n",
895                                 sub->sa_desc->ad_cname.bv_val, rc, 0 );
896 #endif
897                         break;
898                 }
899
900                 if( BDB_IDL_IS_ZERO( tmp ) ) {
901 #ifdef NEW_LOGGING
902                         LDAP_LOG ( INDEX, RESULTS, 
903                                 "<= bdb_substring_candidates: (%s) NULL\n",
904                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
905 #else
906                         Debug( LDAP_DEBUG_TRACE,
907                                 "<= bdb_substring_candidates: (%s) NULL\n",
908                                 sub->sa_desc->ad_cname.bv_val, 0, 0 );
909 #endif
910                         BDB_IDL_ZERO( ids );
911                         break;
912                 }
913
914                 if ( i == 0 ) {
915                         BDB_IDL_CPY( ids, tmp );
916                 } else {
917                         bdb_idl_intersection( ids, tmp );
918                 }
919
920                 if( BDB_IDL_IS_ZERO( ids ) )
921                         break;
922         }
923
924         ber_bvarray_free_x( keys, op->o_tmpmemctx );
925
926 #ifdef NEW_LOGGING
927         LDAP_LOG ( INDEX, RESULTS, 
928                 "<= bdb_substring_candidates: id=%ld first=%ld last=%ld\n",
929                 (long) ids[0], (long) BDB_IDL_FIRST( ids ), 
930                 (long) BDB_IDL_LAST( ids ) );
931 #else
932         Debug( LDAP_DEBUG_TRACE, "<= bdb_substring_candidates: %ld, first=%ld, last=%ld\n",
933                 (long) ids[0],
934                 (long) BDB_IDL_FIRST(ids),
935                 (long) BDB_IDL_LAST(ids) );
936 #endif
937         return( rc );
938 }
939