1 /* OpenLDAP WiredTiger backend */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2002-2018 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * This work was developed by HAMANO Tsukasa <hamano@osstech.co.jp>
18 * based on back-bdb for inclusion in OpenLDAP Software.
19 * WiredTiger is a product of MongoDB Inc.
25 #include <ac/string.h>
33 AttributeDescription *desc,
36 struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
38 struct berval prefix = {0, NULL};
40 WT_CURSOR *cursor = NULL;
42 Debug( LDAP_DEBUG_TRACE, "=> wt_presence_candidates (%s)\n",
43 desc->ad_cname.bv_val, 0, 0 );
45 WT_IDL_ALL( wi, ids );
47 if( desc == slap_schema.si_ad_objectClass ) {
51 rc = wt_index_param( op->o_bd, desc, LDAP_FILTER_PRESENT,
54 if( rc == LDAP_INAPPROPRIATE_MATCHING ) {
56 Debug( LDAP_DEBUG_TRACE,
57 "<= wt_presence_candidates: (%s) not indexed\n",
58 desc->ad_cname.bv_val, 0, 0 );
62 if( rc != LDAP_SUCCESS ) {
63 Debug( LDAP_DEBUG_TRACE,
64 "<= wt_presence_candidates: (%s) index_param "
66 desc->ad_cname.bv_val, rc, 0 );
70 if( prefix.bv_val == NULL ) {
71 Debug( LDAP_DEBUG_TRACE,
72 "<= wt_presence_candidates: (%s) no prefix\n",
73 desc->ad_cname.bv_val, 0, 0 );
77 /* open index cursor */
78 cursor = wt_ctx_index_cursor(wc, &desc->ad_type->sat_cname, 0);
80 Debug( LDAP_DEBUG_ANY,
81 "<= wt_presence_candidates: open index cursor failed: %s\n",
82 desc->ad_type->sat_cname.bv_val, 0, 0 );
86 rc = wt_key_read( op->o_bd, cursor, &prefix, ids, NULL, 0 );
89 cursor->close(cursor);
91 Debug(LDAP_DEBUG_TRACE,
92 "<= wt_presence_candidates: id=%ld first=%ld last=%ld\n",
94 (long) WT_IDL_FIRST(ids),
95 (long) WT_IDL_LAST(ids) );
104 AttributeAssertion *ava,
108 struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
110 struct berval prefix = {0, NULL};
111 struct berval *keys = NULL;
115 WT_CURSOR *cursor = NULL;
117 Debug( LDAP_DEBUG_TRACE, "=> wt_equality_candidates (%s)\n",
118 ava->aa_desc->ad_cname.bv_val, 0, 0 );
120 if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
122 rc = wt_dn2id(op, wc->session, &ava->aa_value, &id);
124 wt_idl_append_one(ids, id);
125 }else if ( rc == WT_NOTFOUND ) {
132 WT_IDL_ALL( wi, ids );
134 rc = wt_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_EQUALITY,
137 if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
138 Debug( LDAP_DEBUG_ANY,
139 "<= wt_equality_candidates: (%s) not indexed\n",
140 ava->aa_desc->ad_cname.bv_val, 0, 0 );
144 if( rc != LDAP_SUCCESS ) {
145 Debug( LDAP_DEBUG_ANY,
146 "<= wt_equality_candidates: (%s) index_param failed (%d)\n",
147 ava->aa_desc->ad_cname.bv_val, rc, 0 );
151 mr = ava->aa_desc->ad_type->sat_equality;
156 if( !mr->smr_filter ) {
160 rc = (mr->smr_filter)(
161 LDAP_FILTER_EQUALITY,
163 ava->aa_desc->ad_type->sat_syntax,
167 &keys, op->o_tmpmemctx );
169 if( rc != LDAP_SUCCESS ) {
170 Debug( LDAP_DEBUG_TRACE,
171 "<= wt_equality_candidates: (%s, %s) "
172 "MR filter failed (%d)\n",
173 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
178 Debug( LDAP_DEBUG_TRACE,
179 "<= wt_equality_candidates: (%s) no keys\n",
180 ava->aa_desc->ad_cname.bv_val, 0, 0 );
184 /* open index cursor */
185 cursor = wt_ctx_index_cursor(wc, &ava->aa_desc->ad_type->sat_cname, 0);
187 Debug( LDAP_DEBUG_ANY,
188 "<= wt_equality_candidates: open index cursor failed: %s\n",
189 ava->aa_desc->ad_type->sat_cname.bv_val, 0, 0 );
193 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
194 rc = wt_key_read( op->o_bd, cursor, &keys[i], tmp, NULL, 0 );
195 if( rc == WT_NOTFOUND ) {
199 } else if( rc != LDAP_SUCCESS ) {
200 Debug( LDAP_DEBUG_TRACE,
201 "<= wt_equality_candidates: (%s) "
202 "key read failed (%d)\n",
203 ava->aa_desc->ad_cname.bv_val, rc, 0 );
207 WT_IDL_CPY( ids, tmp );
209 wt_idl_intersection( ids, tmp );
212 if( WT_IDL_IS_ZERO( ids ) )
216 ber_bvarray_free_x( keys, op->o_tmpmemctx );
219 cursor->close(cursor);
222 Debug( LDAP_DEBUG_TRACE,
223 "<= wt_equality_candidates: id=%ld, first=%ld, last=%ld\n",
225 (long) WT_IDL_FIRST(ids),
226 (long) WT_IDL_LAST(ids) );
235 AttributeAssertion *ava,
239 struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
243 struct berval prefix = {0, NULL};
244 struct berval *keys = NULL;
246 WT_CURSOR *cursor = NULL;
248 Debug( LDAP_DEBUG_TRACE, "=> wt_approx_candidates (%s)\n",
249 ava->aa_desc->ad_cname.bv_val, 0, 0 );
251 WT_IDL_ALL( wi, ids );
253 rc = wt_index_param( op->o_bd, ava->aa_desc, LDAP_FILTER_APPROX,
256 if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
257 Debug( LDAP_DEBUG_ANY,
258 "<= wt_approx_candidates: (%s) not indexed\n",
259 ava->aa_desc->ad_cname.bv_val, 0, 0 );
263 if( rc != LDAP_SUCCESS ) {
264 Debug( LDAP_DEBUG_ANY,
265 "<= wt_approx_candidates: (%s) index_param failed (%d)\n",
266 ava->aa_desc->ad_cname.bv_val, rc, 0 );
270 mr = ava->aa_desc->ad_type->sat_approx;
272 /* no approx matching rule, try equality matching rule */
273 mr = ava->aa_desc->ad_type->sat_equality;
280 if( !mr->smr_filter ) {
284 rc = (mr->smr_filter)(
287 ava->aa_desc->ad_type->sat_syntax,
291 &keys, op->o_tmpmemctx );
293 if( rc != LDAP_SUCCESS ) {
294 Debug( LDAP_DEBUG_TRACE,
295 "<= wt_approx_candidates: (%s, %s) MR filter failed (%d)\n",
296 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, rc );
301 Debug( LDAP_DEBUG_TRACE,
302 "<= wt_approx_candidates: (%s) no keys (%s)\n",
303 prefix.bv_val, ava->aa_desc->ad_cname.bv_val, 0 );
307 /* open index cursor */
308 cursor = wt_ctx_index_cursor(wc, &ava->aa_desc->ad_type->sat_cname, 0);
310 Debug( LDAP_DEBUG_ANY,
311 "<= wt_approx_candidates: open index cursor failed: %s\n",
312 ava->aa_desc->ad_type->sat_cname.bv_val, 0, 0 );
316 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
317 rc = wt_key_read( op->o_bd, cursor, &keys[i], tmp, NULL, 0 );
318 if( rc == WT_NOTFOUND ) {
322 } else if( rc != LDAP_SUCCESS ) {
323 Debug( LDAP_DEBUG_TRACE,
324 "<= wt_approx_candidates: (%s) key read failed (%d)\n",
325 ava->aa_desc->ad_cname.bv_val, rc, 0 );
329 if( WT_IDL_IS_ZERO( tmp ) ) {
330 Debug( LDAP_DEBUG_TRACE,
331 "<= wt_approx_candidates: (%s) NULL\n",
332 ava->aa_desc->ad_cname.bv_val, 0, 0 );
338 WT_IDL_CPY( ids, tmp );
340 wt_idl_intersection( ids, tmp );
343 if( WT_IDL_IS_ZERO( ids ) )
347 ber_bvarray_free_x( keys, op->o_tmpmemctx );
350 cursor->close(cursor);
353 Debug( LDAP_DEBUG_TRACE,
354 "<= wt_approx_candidates %ld, first=%ld, last=%ld\n",
356 (long) WT_IDL_FIRST(ids),
357 (long) WT_IDL_LAST(ids) );
363 substring_candidates(
366 SubstringsAssertion *sub,
370 struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
374 struct berval prefix = {0, NULL};
375 struct berval *keys = NULL;
377 WT_CURSOR *cursor = NULL;
379 Debug( LDAP_DEBUG_TRACE, "=> wt_substring_candidates (%s)\n",
380 sub->sa_desc->ad_cname.bv_val, 0, 0 );
382 WT_IDL_ALL( wi, ids );
384 rc = wt_index_param( op->o_bd, sub->sa_desc, LDAP_FILTER_SUBSTRINGS,
387 if ( rc == LDAP_INAPPROPRIATE_MATCHING ) {
388 Debug( LDAP_DEBUG_ANY,
389 "<= wt_substring_candidates: (%s) not indexed\n",
390 sub->sa_desc->ad_cname.bv_val, 0, 0 );
394 if( rc != LDAP_SUCCESS ) {
395 Debug( LDAP_DEBUG_ANY,
396 "<= wt_substring_candidates: (%s) "
397 "index_param failed (%d)\n",
398 sub->sa_desc->ad_cname.bv_val, rc, 0 );
402 mr = sub->sa_desc->ad_type->sat_substr;
408 if( !mr->smr_filter ) {
412 rc = (mr->smr_filter)(
413 LDAP_FILTER_SUBSTRINGS,
415 sub->sa_desc->ad_type->sat_syntax,
419 &keys, op->o_tmpmemctx );
421 if( rc != LDAP_SUCCESS ) {
422 Debug( LDAP_DEBUG_TRACE,
423 "<= wt_substring_candidates: (%s) MR filter failed (%d)\n",
424 sub->sa_desc->ad_cname.bv_val, rc, 0 );
429 Debug( LDAP_DEBUG_TRACE,
430 "<= wt_substring_candidates: (0x%04lx) no keys (%s)\n",
431 mask, sub->sa_desc->ad_cname.bv_val, 0 );
435 /* open index cursor */
436 cursor = wt_ctx_index_cursor(wc, &sub->sa_desc->ad_cname, 0);
438 Debug( LDAP_DEBUG_ANY,
439 "<= wt_substring_candidates: open index cursor failed: %s\n",
440 sub->sa_desc->ad_cname.bv_val, 0, 0 );
444 for ( i= 0; keys[i].bv_val != NULL; i++ ) {
445 rc = wt_key_read( op->o_bd, cursor, &keys[i], tmp, NULL, 0 );
447 if( rc == WT_NOTFOUND ) {
451 } else if( rc != LDAP_SUCCESS ) {
452 Debug( LDAP_DEBUG_TRACE,
453 "<= wt_substring_candidates: (%s) key read failed (%d)\n",
454 sub->sa_desc->ad_cname.bv_val, rc, 0 );
458 if( WT_IDL_IS_ZERO( tmp ) ) {
459 Debug( LDAP_DEBUG_TRACE,
460 "<= wt_substring_candidates: (%s) NULL\n",
461 sub->sa_desc->ad_cname.bv_val, 0, 0 );
467 WT_IDL_CPY( ids, tmp );
469 wt_idl_intersection( ids, tmp );
472 if( WT_IDL_IS_ZERO( ids ) )
476 ber_bvarray_free_x( keys, op->o_tmpmemctx );
479 cursor->close(cursor);
482 Debug( LDAP_DEBUG_TRACE,
483 "<= wt_substring_candidates: %ld, first=%ld, last=%ld\n",
485 (long) WT_IDL_FIRST(ids),
486 (long) WT_IDL_LAST(ids));
504 Debug( LDAP_DEBUG_FILTER, "=> wt_list_candidates 0x%x\n", ftype, 0, 0 );
505 for ( f = flist; f != NULL; f = f->f_next ) {
506 /* ignore precomputed scopes */
507 if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
508 f->f_result == LDAP_SUCCESS ) {
512 rc = wt_filter_candidates( op, wc, f, save, tmp,
513 save+WT_IDL_UM_SIZE );
516 /* TODO: error handling */
518 if ( rc == DB_LOCK_DEADLOCK )
521 if ( ftype == LDAP_FILTER_AND ) {
529 if ( ftype == LDAP_FILTER_AND ) {
531 WT_IDL_CPY( ids, save );
533 wt_idl_intersection( ids, save );
535 if( WT_IDL_IS_ZERO( ids ) )
539 WT_IDL_CPY( ids, save );
541 wt_idl_union( ids, save );
546 if( rc == LDAP_SUCCESS ) {
547 Debug( LDAP_DEBUG_FILTER,
548 "<= wt_list_candidates: id=%ld first=%ld last=%ld\n",
550 (long) WT_IDL_FIRST(ids),
551 (long) WT_IDL_LAST(ids) );
554 Debug( LDAP_DEBUG_FILTER,
555 "<= wt_list_candidates: undefined rc=%d\n",
563 wt_filter_candidates(
571 struct wt_info *wi = (struct wt_info *)op->o_bd->be_private;
573 Debug( LDAP_DEBUG_FILTER, "=> wt_filter_candidates\n", 0, 0, 0 );
575 if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
580 switch ( f->f_choice ) {
581 case SLAPD_FILTER_COMPUTED:
582 switch( f->f_result ) {
583 case SLAPD_COMPARE_UNDEFINED:
584 /* This technically is not the same as FALSE, but it
585 * certainly will produce no matches.
588 case LDAP_COMPARE_FALSE:
591 case LDAP_COMPARE_TRUE: {
593 WT_IDL_ALL( wi, ids );
596 /* this is a pre-computed scope, leave it alone */
600 case LDAP_FILTER_PRESENT:
601 Debug( LDAP_DEBUG_FILTER, "\tPRESENT\n", 0, 0, 0 );
602 rc = presence_candidates( op, wc, f->f_desc, ids );
605 case LDAP_FILTER_EQUALITY:
606 Debug( LDAP_DEBUG_FILTER, "\tEQUALITY\n", 0, 0, 0 );
607 rc = equality_candidates( op, wc, f->f_ava, ids, tmp );
610 case LDAP_FILTER_APPROX:
611 Debug( LDAP_DEBUG_FILTER, "\tAPPROX\n", 0, 0, 0 );
612 rc = approx_candidates( op, wc, f->f_ava, ids, tmp );
615 case LDAP_FILTER_SUBSTRINGS:
616 Debug( LDAP_DEBUG_FILTER, "\tSUBSTRINGS\n", 0, 0, 0 );
617 rc = substring_candidates( op, wc, f->f_sub, ids, tmp );
621 /* if no GE index, use pres */
622 /* TODO: not implement yet */
623 rc = presence_candidates( op, wc, f->f_ava->aa_desc, ids );
627 /* if no LE index, use pres */
628 /* TODO: not implement yet */
629 Debug( LDAP_DEBUG_FILTER, "\tLE\n", 0, 0, 0 );
630 rc = presence_candidates( op, wc, f->f_ava->aa_desc, ids );
633 case LDAP_FILTER_NOT:
634 /* no indexing to support NOT filters */
635 Debug( LDAP_DEBUG_FILTER, "\tNOT\n", 0, 0, 0 );
636 WT_IDL_ALL( wi, ids );
639 case LDAP_FILTER_AND:
640 Debug( LDAP_DEBUG_FILTER, "\tAND\n", 0, 0, 0 );
641 rc = list_candidates( op, wc,
642 f->f_and, LDAP_FILTER_AND, ids, tmp, stack );
646 Debug( LDAP_DEBUG_FILTER, "\tOR\n", 0, 0, 0 );
647 rc = list_candidates( op, wc,
648 f->f_or, LDAP_FILTER_OR, ids, tmp, stack );
651 case LDAP_FILTER_EXT:
652 /* TODO: not implement yet */
653 Debug( LDAP_DEBUG_FILTER, "\tEXT\n", 0, 0, 0 );
654 rc = presence_candidates( op, wc, f->f_ava->aa_desc, ids );
658 Debug( LDAP_DEBUG_FILTER, "\tUNKNOWN %lu\n",
659 (unsigned long) f->f_choice, 0, 0 );
660 /* Must not return NULL, otherwise extended filters break */
661 WT_IDL_ALL( wi, ids );
665 Debug( LDAP_DEBUG_FILTER,
666 "<= wt_filter_candidates: id=%ld first=%ld last=%ld\n",
668 (long) WT_IDL_FIRST( ids ),
669 (long) WT_IDL_LAST( ids ) );
675 * indent-tabs-mode: t