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 );
/* 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 : "<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
*/
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 ] );
}
}
"bc",
&f->f_sub_any[ i ],
'%' );
- if ( bi->upper_func.bv_val ) {
+ if ( casefold && bi->upper_func.bv_val ) {
/*
* Note: toupper('%') = '%'
*/
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 ] );
}
}
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 ) {
}
if ( rc == -1 ) {
- /* TimesTen : Don't run the query */
goto impossible;
}
* Note however that hasSubordinates is boolean,
* so a more appropriate filter would be
* '(hasSubordinates=FALSE)'
+ *
+ * A more robust search for hasSubordinates
+ * would * require joining the ldap_entries table
+ * selecting if there are descendants of the
+ * candidate.
*/
backsql_strfcat( &bsi->flt_where, "l",
(ber_len_t)sizeof( "1=1" ) - 1, "1=1" );
if ( ad == slap_schema.si_ad_hasSubordinates ) {
/*
- * We use this flag since we need to parse
- * the filter anyway; we should have used
- * the frontend API function
- * filter_has_subordinates()
+ * instruct candidate selection algorithm
+ * and attribute list to try to detect
+ * if an entry has subordinates
*/
bsi->bsi_flags |= BSQL_SF_FILTER_HASSUBORDINATE;
&at->join_where );
}
-#if 0
- /*
- * FIXME: this is not required any more; however, note that
- * attribute name syntax might collide with SQL legal aliases
- */
- if ( at != &oc_attr ) {
- backsql_strfcat( &bsi->sel, "cblb",
- ',',
- &at->sel_expr,
- (ber_len_t)sizeof( " AS " ) - 1, " AS ",
- &at->name );
- }
-#endif
-
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 ) {
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:
bsi->flt_where.bb_val.bv_len = 0;
bsi->flt_where.bb_len = 0;
-#if 0
- /*
- * FIXME: this query has been split in case a string cast function
- * is defined; more sophisticated (pattern based) function should
- * be used
- */
- backsql_strcat( &bsi->sel,
- "SELECT DISTINCT ldap_entries.id,",
- bsi->oc->keytbl.bv_val, ".", bsi->oc->keycol.bv_val,
- ",'", bsi->oc->name.bv_val, "' AS objectClass",
- ",ldap_entries.dn AS dn", NULL );
-#endif
-
backsql_strfcat( &bsi->sel, "lbcbc",
(ber_len_t)sizeof( "SELECT DISTINCT ldap_entries.id," ) - 1,
"SELECT DISTINCT ldap_entries.id,",
"ldap_entries.dn LIKE ?" );
}
-#if 0
- backsql_strfcat( &bsi->join_where, "b",
- &bi->subtree_cond );
-#endif
break;
default:
* Indicates that there's no possible way the filter matches
* anything. No need to issue the query
*/
- Debug( LDAP_DEBUG_TRACE,
- "<==backsql_srch_query() returns NULL\n", 0, 0, 0 );
free( query->bv_val );
query->bv_val = NULL;
}
bsi->flt_where.bb_val.bv_len = 0;
bsi->flt_where.bb_len = 0;
- Debug( LDAP_DEBUG_TRACE, "<==backsql_srch_query()\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "<==backsql_srch_query() returns %s\n",
+ query->bv_val ? query->bv_val : "NULL", 0, 0 );
- return ( query->bv_val == NULL ? 1 : 0 );
+ return ( rc <= 0 ? 1 : 0 );
}
static int
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 );
"unchecked limit has been overcome\n", 0, 0, 0 );
/* should never get here */
assert( 0 );
- bsi->status = LDAP_OTHER;
+ bsi->status = LDAP_ADMINLIMIT_EXCEEDED;
return BACKSQL_STOP;
}
bsi->oc = oc;
- if ( backsql_srch_query( bsi, &query ) ) {
+ res = backsql_srch_query( bsi, &query );
+ if ( res ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
- "could not construct query for objectclass\n",
- 0, 0, 0 );
- bsi->status = LDAP_OTHER;
+ "error while constructing query for objectclass '%s'\n",
+ oc->oc->soc_cname.bv_val, 0, 0 );
+ /*
+ * FIXME: need to separate errors from legally
+ * impossible filters
+ */
+ bsi->status = LDAP_SUCCESS;
+ return BACKSQL_CONTINUE;
+ }
+
+ if ( query.bv_val == NULL ) {
+ Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
+ "could not construct query for objectclass '%s'\n",
+ oc->oc->soc_cname.bv_val, 0, 0 );
+ bsi->status = LDAP_SUCCESS;
return BACKSQL_CONTINUE;
}
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 );
}