From d9d591238366b90d60bf6ccf0fc6b968f330c2ae Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 16 Apr 2003 10:22:33 +0000 Subject: [PATCH] use syntax and matching rules knowledge when preparing SQL filters (to reduce pseudo-normalization efforts and search candidate number) --- servers/slapd/back-sql/back-sql.h | 3 + servers/slapd/back-sql/entry-id.c | 2 - servers/slapd/back-sql/init.c | 9 ++- servers/slapd/back-sql/search.c | 100 +++++++++++++++++++++++------- servers/slapd/schema_init.c | 7 +-- servers/slapd/slap.h | 3 + 6 files changed, 92 insertions(+), 32 deletions(-) diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index 2fb5508670..63004112aa 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -101,6 +101,9 @@ typedef struct { char *insentry_query,*delentry_query; char *id_query; char *has_children_query; + + MatchingRule *bi_caseIgnoreMatch; + struct berval upper_func; struct berval upper_func_open; struct berval upper_func_close; diff --git a/servers/slapd/back-sql/entry-id.c b/servers/slapd/back-sql/entry-id.c index deb7c6a051..81729c8f30 100644 --- a/servers/slapd/back-sql/entry-id.c +++ b/servers/slapd/back-sql/entry-id.c @@ -413,8 +413,6 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid ) size_t textlen = sizeof( textbuf ); struct berval bv[ 2 ]; struct berval soc; - AttributeDescription *ad_soc - = slap_schema.si_ad_structuralObjectClass; int rc; bv[ 0 ] = bsi->oc->oc->soc_cname; diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index dd0e8320d9..712ac7aef6 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -215,7 +215,10 @@ backsql_db_open( ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close ); } } - + + /* normalize filter values only if necessary */ + si->bi_caseIgnoreMatch = mr_find( "caseIgnoreMatch" ); + if ( si->dbuser == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "user name not specified " @@ -385,11 +388,14 @@ backsql_db_open( backsql_strcat( &bb, backsql_id_query, "dn_ru=?", NULL ); } else { +#if 0 if ( BACKSQL_USE_REVERSE_DN( si ) ) { +#endif backsql_strfcat( &bb, "sbl", backsql_id_query, &si->upper_func, (ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" ); +#if 0 } else { backsql_strfcat( &bb, "sblbcb", backsql_id_query, @@ -399,6 +405,7 @@ backsql_db_open( '?', &si->upper_func_close ); } +#endif } } si->id_query = bb.bb_val.bv_val; diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 77f6e89537..f1cc0ada09 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -205,11 +205,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f ) int i; backsql_at_map_rec *at; backsql_info *bi = (backsql_info *)bsi->op->o_bd->be_private; + int casefold = 0; if ( !f ) { return 0; } + if ( SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr, + bi->bi_caseIgnoreMatch ) ) { + casefold = 1; + } + at = backsql_ad2at( bsi->oc, f->f_sub_desc ); assert( at ); @@ -225,7 +231,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f ) /* TimesTen */ Debug( LDAP_DEBUG_TRACE, "expr: '%s' '%s'\n", at->sel_expr.bv_val, at->sel_expr_u.bv_val ? at->sel_expr_u.bv_val : "", 0 ); - if ( bi->upper_func.bv_val ) { + if ( casefold && bi->upper_func.bv_val ) { /* * If a pre-upper-cased version of the column exists, use it */ @@ -257,7 +263,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f ) start = bsi->flt_where.bb_val.bv_len; backsql_strfcat( &bsi->flt_where, "b", &f->f_sub_initial ); - if ( bi->upper_func.bv_val ) { + if ( casefold && bi->upper_func.bv_val ) { ldap_pvt_str2upper( &bsi->flt_where.bb_val.bv_val[ start ] ); } } @@ -280,7 +286,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f ) "bc", &f->f_sub_any[ i ], '%' ); - if ( bi->upper_func.bv_val ) { + if ( casefold && bi->upper_func.bv_val ) { /* * Note: toupper('%') = '%' */ @@ -294,7 +300,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f ) start = bsi->flt_where.bb_val.bv_len; backsql_strfcat( &bsi->flt_where, "b", &f->f_sub_final ); - if ( bi->upper_func.bv_val ) { + if ( casefold && bi->upper_func.bv_val ) { ldap_pvt_str2upper( &bsi->flt_where.bb_val.bv_val[ start ] ); } } @@ -316,9 +322,11 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) BER_BVNULL, NULL, NULL, NULL }; AttributeDescription *ad = NULL; int done = 0; - /* TimesTen */ + int casefold = 0; int rc = 0; struct berval *filter_value = NULL; + MatchingRule *matching_rule = NULL; + struct berval ordering = BER_BVC("<="); Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter()\n", 0, 0, 0 ); if ( f == NULL || f->f_choice == SLAPD_FILTER_COMPUTED ) { @@ -457,21 +465,29 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) switch ( f->f_choice ) { case LDAP_FILTER_EQUALITY: filter_value = &f->f_av_value; + matching_rule = ad->ad_type->sat_equality; + goto equality_match; - /* fail over next case */ + /* fail over into next case */ case LDAP_FILTER_EXT: filter_value = &f->f_mra->ma_value; + matching_rule = f->f_mr_rule; equality_match:; + if ( SLAP_MR_ASSOCIATED( matching_rule, + bi->bi_caseIgnoreMatch ) ) { + casefold = 1; + } + /* * maybe we should check type of at->sel_expr here somehow, * to know whether upper_func is applicable, but for now * upper_func stuff is made for Oracle, where UPPER is * safely applicable to NUMBER etc. */ - if ( bi->upper_func.bv_val ) { + if ( casefold && bi->upper_func.bv_val ) { size_t start; if ( at->sel_expr_u.bv_val ) { @@ -511,27 +527,58 @@ equality_match:; break; case LDAP_FILTER_GE: - /* - * FIXME: should we uppercase the operands? - */ - backsql_strfcat( &bsi->flt_where, "cblbc", - '(' /* ) */ , - &at->sel_expr, - (ber_len_t)sizeof( ">=" ) - 1, ">=", - &f->f_av_value, - /* ( */ ')' ); - break; + ordering.bv_val = ">="; + + /* fall thru to next case */ case LDAP_FILTER_LE: + if ( SLAP_MR_ASSOCIATED( ad->ad_type->sat_ordering, + bi->bi_caseIgnoreMatch ) ) { + casefold = 1; + } + /* * FIXME: should we uppercase the operands? */ - backsql_strfcat( &bsi->flt_where, "cblbc", - '(' /* ) */ , - &at->sel_expr, - (ber_len_t)sizeof( "<=" ) - 1, "<=", - &f->f_av_value, - /* ( */ ')' ); + if ( casefold && bi->upper_func.bv_val ) { + size_t start; + + if ( at->sel_expr_u.bv_val ) { + backsql_strfcat( &bsi->flt_where, "cbbc", + '(', + &at->sel_expr_u, + &ordering, + '\'' ); + } else { + backsql_strfcat( &bsi->flt_where, "cbcbcbc", + '(' /* ) */ , + &bi->upper_func, + '(' /* ) */ , + &at->sel_expr, + /* ( */ ')', + &ordering, + '\'' ); + } + + start = bsi->flt_where.bb_val.bv_len; + + backsql_strfcat( &bsi->flt_where, "bl", + filter_value, + (ber_len_t)sizeof( /* (' */ "')" ) - 1, + /* (' */ "')" ); + + ldap_pvt_str2upper( &bsi->flt_where.bb_val.bv_val[ start ] ); + + } else { + backsql_strfcat( &bsi->flt_where, "cbbcbl", + '(' /* ) */ , + &at->sel_expr, + &ordering, + '\'', + &f->f_av_value, + (ber_len_t)sizeof( /* (' */ "')" ) - 1, + /* ( */ "')" ); + } break; case LDAP_FILTER_PRESENT: @@ -800,6 +847,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) BACKSQL_ROW_NTS row; int i; int j; + + int n_candidates = bsi->n_candidates; + + bsi->status = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n", BACKSQL_OC_NAME( oc ), 0, 0 ); @@ -982,7 +1033,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) backsql_FreeRow( &row ); SQLFreeStmt( sth, SQL_DROP ); - Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates()\n", 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates(): %d\n", + n_candidates - bsi->n_candidates, 0, 0 ); return ( bsi->n_candidates == -1 ? BACKSQL_STOP : BACKSQL_CONTINUE ); } diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 243bcea6cb..e023f39dc2 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -30,9 +30,6 @@ #define SLAP_NVALUES 1 -#define MR_ASSOCIATED(mr,amr) (((mr) == (amr)) || \ - ((mr)->smr_associated == (amr))) - /* not yet implemented */ #define objectIdentifierNormalize NULL #define integerOrderingMatch NULL @@ -1005,7 +1002,7 @@ UTF8StringNormalize( return LDAP_SUCCESS; } - flags = MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch ) + flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch ) ? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD; flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX ) ? LDAP_UTF8_APPROX : 0; @@ -1694,7 +1691,7 @@ IA5StringNormalize( void *ctx ) { char *p, *q; - int casefold = MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match ); + int casefold = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactIA5Match ); assert( val->bv_len ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index e72b55bb90..a6a3f4b5a9 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -495,6 +495,9 @@ typedef struct slap_matching_rule { */ struct slap_matching_rule *smr_associated; +#define SLAP_MR_ASSOCIATED(mr,amr) (((mr) == (amr)) || \ + ((mr)->smr_associated == (amr))) + LDAP_SLIST_ENTRY(slap_matching_rule)smr_next; #define smr_oid smr_mrule.mr_oid -- 2.39.5