mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-18 18:18:06 -05:00
use syntax and matching rules knowledge when preparing SQL filters (to reduce pseudo-normalization efforts and search candidate number)
This commit is contained in:
parent
fc7e29e0c5
commit
d9d5912383
6 changed files with 92 additions and 32 deletions
|
|
@ -101,6 +101,9 @@ typedef struct {
|
||||||
char *insentry_query,*delentry_query;
|
char *insentry_query,*delentry_query;
|
||||||
char *id_query;
|
char *id_query;
|
||||||
char *has_children_query;
|
char *has_children_query;
|
||||||
|
|
||||||
|
MatchingRule *bi_caseIgnoreMatch;
|
||||||
|
|
||||||
struct berval upper_func;
|
struct berval upper_func;
|
||||||
struct berval upper_func_open;
|
struct berval upper_func_open;
|
||||||
struct berval upper_func_close;
|
struct berval upper_func_close;
|
||||||
|
|
|
||||||
|
|
@ -413,8 +413,6 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
|
||||||
size_t textlen = sizeof( textbuf );
|
size_t textlen = sizeof( textbuf );
|
||||||
struct berval bv[ 2 ];
|
struct berval bv[ 2 ];
|
||||||
struct berval soc;
|
struct berval soc;
|
||||||
AttributeDescription *ad_soc
|
|
||||||
= slap_schema.si_ad_structuralObjectClass;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
bv[ 0 ] = bsi->oc->oc->soc_cname;
|
bv[ 0 ] = bsi->oc->oc->soc_cname;
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,10 @@ backsql_db_open(
|
||||||
ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close );
|
ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* normalize filter values only if necessary */
|
||||||
|
si->bi_caseIgnoreMatch = mr_find( "caseIgnoreMatch" );
|
||||||
|
|
||||||
if ( si->dbuser == NULL ) {
|
if ( si->dbuser == NULL ) {
|
||||||
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): "
|
||||||
"user name not specified "
|
"user name not specified "
|
||||||
|
|
@ -385,11 +388,14 @@ backsql_db_open(
|
||||||
backsql_strcat( &bb, backsql_id_query,
|
backsql_strcat( &bb, backsql_id_query,
|
||||||
"dn_ru=?", NULL );
|
"dn_ru=?", NULL );
|
||||||
} else {
|
} else {
|
||||||
|
#if 0
|
||||||
if ( BACKSQL_USE_REVERSE_DN( si ) ) {
|
if ( BACKSQL_USE_REVERSE_DN( si ) ) {
|
||||||
|
#endif
|
||||||
backsql_strfcat( &bb, "sbl",
|
backsql_strfcat( &bb, "sbl",
|
||||||
backsql_id_query,
|
backsql_id_query,
|
||||||
&si->upper_func,
|
&si->upper_func,
|
||||||
(ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" );
|
(ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" );
|
||||||
|
#if 0
|
||||||
} else {
|
} else {
|
||||||
backsql_strfcat( &bb, "sblbcb",
|
backsql_strfcat( &bb, "sblbcb",
|
||||||
backsql_id_query,
|
backsql_id_query,
|
||||||
|
|
@ -399,6 +405,7 @@ backsql_db_open(
|
||||||
'?',
|
'?',
|
||||||
&si->upper_func_close );
|
&si->upper_func_close );
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
si->id_query = bb.bb_val.bv_val;
|
si->id_query = bb.bb_val.bv_val;
|
||||||
|
|
|
||||||
|
|
@ -205,11 +205,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
|
||||||
int i;
|
int i;
|
||||||
backsql_at_map_rec *at;
|
backsql_at_map_rec *at;
|
||||||
backsql_info *bi = (backsql_info *)bsi->op->o_bd->be_private;
|
backsql_info *bi = (backsql_info *)bsi->op->o_bd->be_private;
|
||||||
|
int casefold = 0;
|
||||||
|
|
||||||
if ( !f ) {
|
if ( !f ) {
|
||||||
return 0;
|
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 );
|
at = backsql_ad2at( bsi->oc, f->f_sub_desc );
|
||||||
|
|
||||||
assert( at );
|
assert( at );
|
||||||
|
|
@ -225,7 +231,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
|
||||||
/* TimesTen */
|
/* TimesTen */
|
||||||
Debug( LDAP_DEBUG_TRACE, "expr: '%s' '%s'\n", at->sel_expr.bv_val,
|
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 : "<NULL>", 0 );
|
at->sel_expr_u.bv_val ? at->sel_expr_u.bv_val : "<NULL>", 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
|
* 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;
|
start = bsi->flt_where.bb_val.bv_len;
|
||||||
backsql_strfcat( &bsi->flt_where, "b",
|
backsql_strfcat( &bsi->flt_where, "b",
|
||||||
&f->f_sub_initial );
|
&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 ] );
|
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",
|
"bc",
|
||||||
&f->f_sub_any[ i ],
|
&f->f_sub_any[ i ],
|
||||||
'%' );
|
'%' );
|
||||||
if ( bi->upper_func.bv_val ) {
|
if ( casefold && bi->upper_func.bv_val ) {
|
||||||
/*
|
/*
|
||||||
* Note: toupper('%') = '%'
|
* Note: toupper('%') = '%'
|
||||||
*/
|
*/
|
||||||
|
|
@ -294,7 +300,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
|
||||||
start = bsi->flt_where.bb_val.bv_len;
|
start = bsi->flt_where.bb_val.bv_len;
|
||||||
backsql_strfcat( &bsi->flt_where, "b",
|
backsql_strfcat( &bsi->flt_where, "b",
|
||||||
&f->f_sub_final );
|
&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 ] );
|
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 };
|
BER_BVNULL, NULL, NULL, NULL };
|
||||||
AttributeDescription *ad = NULL;
|
AttributeDescription *ad = NULL;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
/* TimesTen */
|
int casefold = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct berval *filter_value = NULL;
|
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 );
|
Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter()\n", 0, 0, 0 );
|
||||||
if ( f == NULL || f->f_choice == SLAPD_FILTER_COMPUTED ) {
|
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 ) {
|
switch ( f->f_choice ) {
|
||||||
case LDAP_FILTER_EQUALITY:
|
case LDAP_FILTER_EQUALITY:
|
||||||
filter_value = &f->f_av_value;
|
filter_value = &f->f_av_value;
|
||||||
|
matching_rule = ad->ad_type->sat_equality;
|
||||||
|
|
||||||
goto equality_match;
|
goto equality_match;
|
||||||
|
|
||||||
/* fail over next case */
|
/* fail over into next case */
|
||||||
|
|
||||||
case LDAP_FILTER_EXT:
|
case LDAP_FILTER_EXT:
|
||||||
filter_value = &f->f_mra->ma_value;
|
filter_value = &f->f_mra->ma_value;
|
||||||
|
matching_rule = f->f_mr_rule;
|
||||||
|
|
||||||
equality_match:;
|
equality_match:;
|
||||||
|
if ( SLAP_MR_ASSOCIATED( matching_rule,
|
||||||
|
bi->bi_caseIgnoreMatch ) ) {
|
||||||
|
casefold = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* maybe we should check type of at->sel_expr here somehow,
|
* maybe we should check type of at->sel_expr here somehow,
|
||||||
* to know whether upper_func is applicable, but for now
|
* to know whether upper_func is applicable, but for now
|
||||||
* upper_func stuff is made for Oracle, where UPPER is
|
* upper_func stuff is made for Oracle, where UPPER is
|
||||||
* safely applicable to NUMBER etc.
|
* safely applicable to NUMBER etc.
|
||||||
*/
|
*/
|
||||||
if ( bi->upper_func.bv_val ) {
|
if ( casefold && bi->upper_func.bv_val ) {
|
||||||
size_t start;
|
size_t start;
|
||||||
|
|
||||||
if ( at->sel_expr_u.bv_val ) {
|
if ( at->sel_expr_u.bv_val ) {
|
||||||
|
|
@ -511,27 +527,58 @@ equality_match:;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LDAP_FILTER_GE:
|
case LDAP_FILTER_GE:
|
||||||
/*
|
ordering.bv_val = ">=";
|
||||||
* FIXME: should we uppercase the operands?
|
|
||||||
*/
|
/* fall thru to next case */
|
||||||
backsql_strfcat( &bsi->flt_where, "cblbc",
|
|
||||||
'(' /* ) */ ,
|
|
||||||
&at->sel_expr,
|
|
||||||
(ber_len_t)sizeof( ">=" ) - 1, ">=",
|
|
||||||
&f->f_av_value,
|
|
||||||
/* ( */ ')' );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LDAP_FILTER_LE:
|
case LDAP_FILTER_LE:
|
||||||
|
if ( SLAP_MR_ASSOCIATED( ad->ad_type->sat_ordering,
|
||||||
|
bi->bi_caseIgnoreMatch ) ) {
|
||||||
|
casefold = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: should we uppercase the operands?
|
* FIXME: should we uppercase the operands?
|
||||||
*/
|
*/
|
||||||
backsql_strfcat( &bsi->flt_where, "cblbc",
|
if ( casefold && bi->upper_func.bv_val ) {
|
||||||
'(' /* ) */ ,
|
size_t start;
|
||||||
&at->sel_expr,
|
|
||||||
(ber_len_t)sizeof( "<=" ) - 1, "<=",
|
if ( at->sel_expr_u.bv_val ) {
|
||||||
&f->f_av_value,
|
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;
|
break;
|
||||||
|
|
||||||
case LDAP_FILTER_PRESENT:
|
case LDAP_FILTER_PRESENT:
|
||||||
|
|
@ -800,6 +847,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
|
||||||
BACKSQL_ROW_NTS row;
|
BACKSQL_ROW_NTS row;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
|
int n_candidates = bsi->n_candidates;
|
||||||
|
|
||||||
|
bsi->status = LDAP_SUCCESS;
|
||||||
|
|
||||||
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
|
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
|
||||||
BACKSQL_OC_NAME( oc ), 0, 0 );
|
BACKSQL_OC_NAME( oc ), 0, 0 );
|
||||||
|
|
@ -982,7 +1033,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
|
||||||
backsql_FreeRow( &row );
|
backsql_FreeRow( &row );
|
||||||
SQLFreeStmt( sth, SQL_DROP );
|
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 );
|
return ( bsi->n_candidates == -1 ? BACKSQL_STOP : BACKSQL_CONTINUE );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,6 @@
|
||||||
|
|
||||||
#define SLAP_NVALUES 1
|
#define SLAP_NVALUES 1
|
||||||
|
|
||||||
#define MR_ASSOCIATED(mr,amr) (((mr) == (amr)) || \
|
|
||||||
((mr)->smr_associated == (amr)))
|
|
||||||
|
|
||||||
/* not yet implemented */
|
/* not yet implemented */
|
||||||
#define objectIdentifierNormalize NULL
|
#define objectIdentifierNormalize NULL
|
||||||
#define integerOrderingMatch NULL
|
#define integerOrderingMatch NULL
|
||||||
|
|
@ -1005,7 +1002,7 @@ UTF8StringNormalize(
|
||||||
return LDAP_SUCCESS;
|
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;
|
? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
|
||||||
flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
|
flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
|
||||||
? LDAP_UTF8_APPROX : 0;
|
? LDAP_UTF8_APPROX : 0;
|
||||||
|
|
@ -1694,7 +1691,7 @@ IA5StringNormalize(
|
||||||
void *ctx )
|
void *ctx )
|
||||||
{
|
{
|
||||||
char *p, *q;
|
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 );
|
assert( val->bv_len );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -495,6 +495,9 @@ typedef struct slap_matching_rule {
|
||||||
*/
|
*/
|
||||||
struct slap_matching_rule *smr_associated;
|
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;
|
LDAP_SLIST_ENTRY(slap_matching_rule)smr_next;
|
||||||
|
|
||||||
#define smr_oid smr_mrule.mr_oid
|
#define smr_oid smr_mrule.mr_oid
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue