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