From: Pierangelo Masarati Date: Fri, 24 Sep 2004 16:09:15 +0000 (+0000) Subject: import improvements from HEAD X-Git-Tag: OPENLDAP_REL_ENG_2_2_18~19 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=baadd3535578507e0c2d72ec59c5089822453f80;p=openldap import improvements from HEAD --- diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index a938b16978..ea216b905e 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -35,16 +35,186 @@ * - the first occurrence of objectClass, which is used * to determine how to build the SQL entry (FIXME ?!?) * - operational attributes - * empty attributes (FIXME ?!?) + * - empty attributes (FIXME ?!?) */ #define backsql_attr_skip(ad,vals) \ ( \ ( (ad) == slap_schema.si_ad_objectClass \ - && (vals)[ 1 ].bv_val == NULL ) \ + && BER_BVISNULL( &((vals)[ 1 ]) ) ) \ || is_at_operational( (ad)->ad_type ) \ - || ( (vals)[ 0 ].bv_val == NULL ) \ + || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \ ) +int +backsql_modify_delete_all_values( + Operation *op, + SlapReply *rs, + SQLHDBC dbh, + backsql_entryID *e_id, + backsql_at_map_rec *at ) +{ + backsql_info *bi = (backsql_info *)op->o_bd->be_private; + RETCODE rc; + SQLHSTMT asth; + BACKSQL_ROW_NTS row; + + rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "error preparing query\n", 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + asth, rc ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + return LDAP_SUCCESS; + } + +#ifdef BACKSQL_ARBITRARY_KEY + rc = backsql_BindParamStr( asth, 1, + e_id->eid_keyval.bv_val, + BACKSQL_MAX_KEY_LEN ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + rc = backsql_BindParamID( asth, 1, &e_id->eid_keyval ); +#endif /* ! BACKSQL_ARBITRARY_KEY */ + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "error binding key value parameter\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + asth, rc ); + SQLFreeStmt( asth, SQL_DROP ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + + return LDAP_SUCCESS; + } + + rc = SQLExecute( asth ); + if ( !BACKSQL_SUCCESS( rc ) ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "error executing attribute query\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + asth, rc ); + SQLFreeStmt( asth, SQL_DROP ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + + return LDAP_SUCCESS; + } + + backsql_BindRowAsStrings( asth, &row ); + for ( rc = SQLFetch( asth ); + BACKSQL_SUCCESS( rc ); + rc = SQLFetch( asth ) ) + { + int i; + /* first parameter no, parameter order */ + SQLUSMALLINT pno, po; + /* procedure return code */ + int prc; + + for ( i = 0; i < row.ncols; i++ ) { + SQLHSTMT sth; + + rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "error preparing query %s\n", + at->bam_delete_proc, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + sth, rc ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + return LDAP_SUCCESS; + } + + if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) { + pno = 1; + SQLBindParameter( sth, 1, + SQL_PARAM_OUTPUT, + SQL_C_ULONG, + SQL_INTEGER, + 0, 0, &prc, 0, 0 ); + } else { + pno = 0; + } + po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0; +#ifdef BACKSQL_ARBITRARY_KEY + SQLBindParameter( sth, pno + 1 + po, + SQL_PARAM_INPUT, + SQL_C_CHAR, SQL_VARCHAR, + 0, 0, e_id->eid_keyval.bv_val, + 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values() arg%d=%s\n", + pno + 1 + po, e_id->eid_keyval.bv_val, 0 ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + SQLBindParameter( sth, pno + 1 + po, + SQL_PARAM_INPUT, + SQL_C_ULONG, SQL_INTEGER, + 0, 0, &e_id->eid_keyval, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values() arg%d=%lu\n", + pno + 1 + po, e_id->eid_keyval, 0 ); +#endif /* ! BACKSQL_ARBITRARY_KEY */ + + /* + * check for syntax needed here + * maybe need binary bind? + */ + SQLBindParameter( sth, pno + 2 - po, + SQL_PARAM_INPUT, + SQL_C_CHAR, SQL_CHAR, + 0, 0, row.cols[ i ], + strlen( row.cols[ i ] ), 0 ); + + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "arg%d=%s; executing \"%s\"\n", + pno + 2 - po, row.cols[ i ], + at->bam_delete_proc ); + rc = SQLExecute( sth ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_delete_all_values(): " + "delete_proc " + "execution failed\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, + dbh, sth, rc ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + SQLFreeStmt( sth, SQL_DROP ); + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + } + SQLFreeStmt( sth, SQL_DROP ); + } + } + backsql_FreeRow( &row ); + SQLFreeStmt( asth, SQL_DROP ); + + return LDAP_SUCCESS; +} + int backsql_modify_internal( Operation *op, @@ -62,34 +232,38 @@ backsql_modify_internal( Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): " "traversing modifications list\n", 0, 0, 0 ); -#ifndef BACKSQL_REALLOC_STMT - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ - for ( ml = modlist; ml != NULL; ml = ml->sml_next ) { AttributeDescription *ad; + int sm_op; + static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL }; + + BerVarray sm_values; +#if 0 + /* NOTE: some time we'll have to pass + * the normalized values as well */ + BerVarray nvalues; +#endif backsql_at_map_rec *at = NULL; struct berval *at_val; - Modification *c_mod; int i; /* first parameter no, parameter order */ SQLUSMALLINT pno, po; /* procedure return code */ int prc; - -#ifdef BACKSQL_REALLOC_STMT - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ - - c_mod = &ml->sml_mod; - ad = c_mod->sm_desc; + + ad = ml->sml_mod.sm_desc; + sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP ); + sm_values = ml->sml_mod.sm_values; +#if 0 + sm_nvalues = ml->sml_mod.sm_nvalues; +#endif Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " - "modifying attribute \"%s\" according to " + "modifying attribute \"%s\" (%s) according to " "mappings for objectClass \"%s\"\n", - ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 ); + ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) ); - if ( backsql_attr_skip( ad, c_mod->sm_values ) ) { + if ( backsql_attr_skip( ad, sm_values ) ) { continue; } @@ -98,7 +272,7 @@ backsql_modify_internal( Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " "attribute \"%s\" is not registered " "in objectClass \"%s\"\n", - ad->ad_cname.bv_val, oc, 0 ); + ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 ); if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; @@ -110,11 +284,8 @@ backsql_modify_internal( continue; } - switch( c_mod->sm_op ) { + switch ( sm_op ) { case LDAP_MOD_REPLACE: { - SQLHSTMT asth; - BACKSQL_ROW_NTS row; - Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " "replacing values for attribute \"%s\"\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); @@ -162,141 +333,22 @@ backsql_modify_internal( } del_all: - rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 ); - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_modify_internal(): " - "error preparing query\n", 0, 0, 0 ); - backsql_PrintErrors( bi->db_env, dbh, - asth, rc ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } - - break; - } - -#ifdef BACKSQL_ARBITRARY_KEY - rc = backsql_BindParamStr( asth, 1, - e_id->eid_keyval.bv_val, - BACKSQL_MAX_KEY_LEN ); -#else /* ! BACKSQL_ARBITRARY_KEY */ - rc = backsql_BindParamID( asth, 1, &e_id->eid_keyval ); -#endif /* ! BACKSQL_ARBITRARY_KEY */ - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_modify_internal(): " - "error binding key value parameter\n", - 0, 0, 0 ); - backsql_PrintErrors( bi->db_env, dbh, - asth, rc ); - SQLFreeStmt( asth, SQL_DROP ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } - - break; + rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto done; } - - rc = SQLExecute( asth ); - if ( !BACKSQL_SUCCESS( rc ) ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_modify_internal(): " - "error executing attribute query\n", - 0, 0, 0 ); - backsql_PrintErrors( bi->db_env, dbh, - asth, rc ); - SQLFreeStmt( asth, SQL_DROP ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } + /* LDAP_MOD_DELETE gets here if all values must be deleted */ + if ( sm_op == LDAP_MOD_DELETE ) { break; } - - backsql_BindRowAsStrings( asth, &row ); - rc = SQLFetch( asth ); - for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) { - for ( i = 0; i < row.ncols; i++ ) { - if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) { - pno = 1; - SQLBindParameter(sth, 1, - SQL_PARAM_OUTPUT, - SQL_C_ULONG, - SQL_INTEGER, - 0, 0, &prc, 0, 0 ); - } else { - pno = 0; - } - po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0; -#ifdef BACKSQL_ARBITRARY_KEY - SQLBindParameter( sth, pno + 1 + po, - SQL_PARAM_INPUT, - SQL_C_CHAR, SQL_VARCHAR, - 0, 0, e_id->eid_keyval.bv_val, - 0, 0 ); -#else /* ! BACKSQL_ARBITRARY_KEY */ - SQLBindParameter( sth, pno + 1 + po, - SQL_PARAM_INPUT, - SQL_C_ULONG, SQL_INTEGER, - 0, 0, &e_id->eid_keyval, 0, 0 ); -#endif /* ! BACKSQL_ARBITRARY_KEY */ - - /* - * check for syntax needed here - * maybe need binary bind? - */ - SQLBindParameter(sth, pno + 2 - po, - SQL_PARAM_INPUT, - SQL_C_CHAR, SQL_CHAR, - 0, 0, row.cols[ i ], - strlen( row.cols[ i ] ), 0 ); - - Debug( LDAP_DEBUG_TRACE, - " backsql_modify_internal(): " - "executing \"%s\"\n", - at->bam_delete_proc, 0, 0 ); - rc = SQLExecDirect( sth, - at->bam_delete_proc, SQL_NTS ); - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_modify_internal(): " - "delete_proc " - "execution failed\n", - 0, 0, 0 ); - backsql_PrintErrors( bi->db_env, - dbh, sth, rc ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } - } -#ifdef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_DROP ); - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ - } - } - backsql_FreeRow( &row ); - SQLFreeStmt( asth, SQL_DROP ); } /* * PASSTHROUGH - to add new attributes -- do NOT add break */ case LDAP_MOD_ADD: - case SLAP_MOD_SOFTADD: + /* case SLAP_MOD_SOFTADD: */ add_only:; if ( at->bam_add_proc == NULL ) { Debug( LDAP_DEBUG_TRACE, @@ -318,9 +370,23 @@ add_only:; Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " "adding new values for attribute \"%s\"\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); - for ( i = 0, at_val = c_mod->sm_values; - at_val->bv_val != NULL; - i++, at_val++ ) { + for ( i = 0, at_val = sm_values; + !BER_BVISNULL( at_val ); + i++, at_val++ ) + { + rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_internal(): " + "error preparing add query\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) { pno = 1; SQLBindParameter( sth, 1, @@ -357,8 +423,7 @@ add_only:; " backsql_modify_internal(): " "executing \"%s\"\n", at->bam_add_proc, 0, 0 ); - rc = SQLExecDirect( sth, at->bam_add_proc, - SQL_NTS ); + rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " @@ -368,15 +433,13 @@ add_only:; dbh, sth, rc ); if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; goto done; } } -#ifdef BACKSQL_REALLOC_STMT SQLFreeStmt( sth, SQL_DROP ); - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ } break; @@ -398,7 +461,7 @@ add_only:; break; } - if ( c_mod->sm_values == NULL ) { + if ( sm_values == NULL ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " "no values given to delete " @@ -412,9 +475,23 @@ add_only:; "deleting values for attribute \"%s\"\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); - for ( i = 0, at_val = c_mod->sm_values; - at_val->bv_val != NULL; - i++, at_val++ ) { + for ( i = 0, at_val = sm_values; + !BER_BVISNULL( at_val ); + i++, at_val++ ) + { + rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modify_internal(): " + "error preparing delete query\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) { pno = 1; SQLBindParameter( sth, 1, @@ -450,8 +527,7 @@ add_only:; " backsql_modify_internal(): " "executing \"%s\"\n", at->bam_delete_proc, 0, 0 ); - rc = SQLExecDirect( sth, at->bam_delete_proc, - SQL_NTS ); + rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " @@ -461,33 +537,32 @@ add_only:; dbh, sth, rc ); if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; goto done; } } -#ifdef BACKSQL_REALLOC_STMT SQLFreeStmt( sth, SQL_DROP ); - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ + } + break; + + case LDAP_MOD_INCREMENT: + Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): " + "increment not supported yet\n", 0, 0, 0 ); + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; } break; } -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_RESET_PARAMS ); -#else /* BACKSQL_REALLOC_STMT */ - SQLFreeStmt( sth, SQL_DROP ); -#endif /* BACKSQL_REALLOC_STMT */ } done:; - -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_DROP ); -#endif /* BACKSQL_REALLOC_STMT */ - - Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%d%s\n", - rs->sr_err, rs->sr_text ? ": " : "", + Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n", + rs->sr_err, + rs->sr_text ? ": " : "", rs->sr_text ? rs->sr_text : "" ); /* @@ -496,6 +571,144 @@ done:; return rs->sr_err; } +static int +backsql_add_attr( + Operation *op, + SlapReply *rs, + SQLHDBC dbh, + backsql_oc_map_rec *oc, + Attribute *at, + unsigned long new_keyval ) +{ + backsql_info *bi = (backsql_info*)op->o_bd->be_private; + backsql_at_map_rec *at_rec = NULL; + struct berval *at_val; + unsigned long i; + RETCODE rc; + /* first parameter #, parameter order */ + SQLUSMALLINT pno, po; + /* procedure return code */ + int prc; + SQLUSMALLINT currpos; + SQLHSTMT sth; + + at_rec = backsql_ad2at( oc, at->a_desc ); + + if ( at_rec == NULL ) { + Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): " + "attribute \"%s\" is not registered " + "in objectclass \"%s\"\n", + op->oq_add.rs_e->e_name.bv_val, + at->a_desc->ad_cname.bv_val, + BACKSQL_OC_NAME( oc ) ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "operation not permitted " + "within namingContext"; + return rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + + return LDAP_SUCCESS; + } + + if ( at_rec->bam_add_proc == NULL ) { + Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): " + "add procedure is not defined " + "for attribute \"%s\" " + "of structuralObjectClass \"%s\"\n", + op->oq_add.rs_e->e_name.bv_val, + at->a_desc->ad_cname.bv_val, + BACKSQL_OC_NAME( oc ) ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "operation not permitted " + "within namingContext"; + return rs->sr_err = LDAP_UNWILLING_TO_PERFORM; + } + + return LDAP_SUCCESS; + } + + for ( i = 0, at_val = &at->a_vals[ i ]; + !BER_BVISNULL( at_val ); + i++, at_val = &at->a_vals[ i ] ) + { + char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL"; + + /* + * Do not deal with the objectClass that is used + * to build the entry + */ + if ( at->a_desc == slap_schema.si_ad_objectClass ) { + if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) ) + { + continue; + } + } + + rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 ); + if ( rc != SQL_SUCCESS ) { + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + + return LDAP_SUCCESS; + } + + if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) { + pno = 1; + SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, + SQL_C_ULONG, SQL_INTEGER, + 0, 0, &prc, 0, 0 ); + } else { + pno = 0; + } + + po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0; + currpos = pno + 1 + po; + SQLBindParameter( sth, currpos, + SQL_PARAM_INPUT, SQL_C_ULONG, + SQL_INTEGER, 0, 0, &new_keyval, 0, 0 ); + currpos = pno + 2 - po; + + /* + * check for syntax needed here + * maybe need binary bind? + */ + + backsql_BindParamStr( sth, currpos, + at_val->bv_val, at_val->bv_len + 1 ); + +#ifdef LDAP_DEBUG + snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu", + i, new_keyval ); + Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): " + "executing \"%s\" %s\n", + op->oq_add.rs_e->e_name.bv_val, + at_rec->bam_add_proc, logbuf ); +#endif + rc = SQLExecute( sth ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_add_attr(\"%s\"): " + "add_proc execution failed\n", + op->oq_add.rs_e->e_name.bv_val, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + + if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { + SQLFreeStmt( sth, SQL_DROP ); + rs->sr_text = "SQL-backend error"; + return rs->sr_err = LDAP_OTHER; + } + } + SQLFreeStmt( sth, SQL_DROP ); + } + + return LDAP_SUCCESS; +} + int backsql_add( Operation *op, SlapReply *rs ) { @@ -503,20 +716,15 @@ backsql_add( Operation *op, SlapReply *rs ) SQLHDBC dbh; SQLHSTMT sth; unsigned long new_keyval = 0; - long i; RETCODE rc; backsql_oc_map_rec *oc = NULL; - backsql_at_map_rec *at_rec = NULL; backsql_entryID parent_id = BACKSQL_ENTRYID_INIT; Entry p; - Attribute *at; - struct berval *at_val; + Attribute *at, + *at_objectClass = NULL; struct berval pdn; - /* first parameter #, parameter order */ - SQLUSMALLINT pno, po; - /* procedure return code */ - int prc; - struct berval realdn, realpdn; + struct berval realdn = BER_BVNULL, + realpdn = BER_BVNULL; Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n", op->oq_add.rs_e->e_name.bv_val, 0, 0 ); @@ -616,9 +824,15 @@ backsql_add( Operation *op, SlapReply *rs ) } /* - * Check if parent exists + * Get the parent dn and see if the corresponding entry exists. */ - dnParent( &op->oq_add.rs_e->e_name, &pdn ); + if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) { + pdn = slap_empty_bv; + + } else { + dnParent( &op->oq_add.rs_e->e_nname, &pdn ); + } + realpdn = pdn; if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " @@ -640,60 +854,73 @@ backsql_add( Operation *op, SlapReply *rs ) } /* - * Look for matched + * no parent! + * if not attempting to add entry at suffix or with parent "" */ - while ( 1 ) { - struct berval dn; - char *matched = NULL; - - if ( realpdn.bv_val != pdn.bv_val ) { - ch_free( realpdn.bv_val ); - } - - dn = pdn; - dnParent( &dn, &pdn ); - + if ( ( ( !be_isroot( op ) && !be_shadow_update( op ) ) + || !BER_BVISEMPTY( &pdn ) ) && !is_entry_glue( op->oq_add.rs_e ) ) + { + Debug( LDAP_DEBUG_TRACE, " backsql_add: %s denied\n", + BER_BVISEMPTY( &pdn ) ? "suffix" : "entry at root", + 0, 0 ); /* - * Empty DN ("") defaults to LDAP_SUCCESS + * Look for matched */ - realpdn = pdn; - if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_add(\"%s\"): " - "backsql_api_dn2odbc failed\n", - op->oq_add.rs_e->e_name.bv_val, 0, 0 ); - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; + while ( 1 ) { + struct berval dn; + char *matched = NULL; + + if ( realpdn.bv_val != pdn.bv_val ) { + ch_free( realpdn.bv_val ); + } + + dn = pdn; + dnParent( &dn, &pdn ); + + /* + * Empty DN ("") defaults to LDAP_SUCCESS + */ + realpdn = pdn; + if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_add(\"%s\"): " + "backsql_api_dn2odbc failed\n", + op->oq_add.rs_e->e_name.bv_val, 0, 0 ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + + rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn ); + switch ( rs->sr_err ) { + case LDAP_NO_SUCH_OBJECT: + if ( !BER_BVISEMPTY( &pdn ) ) { + break; + } + /* fail over to next case */ + + case LDAP_SUCCESS: + matched = pdn.bv_val; + /* fail over to next case */ + + default: + rs->sr_err = LDAP_NO_SUCH_OBJECT; + rs->sr_matched = matched; + goto done; + } } + } else { - rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn ); - switch ( rs->sr_err ) { - case LDAP_NO_SUCH_OBJECT: - if ( pdn.bv_len > 0 ) { - break; - } - /* fail over to next case */ - - case LDAP_SUCCESS: - matched = pdn.bv_val; - /* fail over to next case */ - - default: - rs->sr_err = LDAP_NO_SUCH_OBJECT; - rs->sr_matched = matched; - goto done; - } +#ifdef BACKSQL_ARBITRARY_KEY + ber_str2bv( "SUFFIX", 0, 1, &parent_id.eid_id ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + parent_id.eid_id = 0; +#endif /* ! BACKSQL_ARBITRARY_KEY */ + rs->sr_err = LDAP_SUCCESS; } } - /* - * create_proc is executed; if expect_return is set, then - * an output parameter is bound, which should contain - * the id of the added row; otherwise the procedure - * is expected to return the id as the first column of a select - */ - + /* check "children" pseudo-attribute access to parent */ p.e_attrs = NULL; p.e_name = pdn; dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname ); @@ -703,6 +930,13 @@ backsql_add( Operation *op, SlapReply *rs ) goto done; } + /* + * create_proc is executed; if expect_return is set, then + * an output parameter is bound, which should contain + * the id of the added row; otherwise the procedure + * is expected to return the id as the first column of a select + */ + rc = SQLAllocStmt( dbh, &sth ); if ( rc != SQL_SUCCESS ) { rs->sr_err = LDAP_OTHER; @@ -728,6 +962,7 @@ backsql_add( Operation *op, SlapReply *rs ) rs->sr_text = "SQL-backend error"; goto done; } + if ( op->o_noop ) { SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK ); } @@ -737,9 +972,6 @@ backsql_add( Operation *op, SlapReply *rs ) SQLINTEGER value_len; if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) { -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_RESET_PARAMS ); -#else /* BACKSQL_REALLOC_STMT */ SQLFreeStmt( sth, SQL_DROP ); rc = SQLAllocStmt( dbh, &sth ); if ( rc != SQL_SUCCESS ) { @@ -747,7 +979,6 @@ backsql_add( Operation *op, SlapReply *rs ) rs->sr_text = "SQL-backend error"; goto done; } -#endif /* BACKSQL_REALLOC_STMT */ rc = SQLExecDirect( sth, oc->bom_create_keyval, SQL_NTS ); if ( rc != SQL_SUCCESS ) { @@ -820,19 +1051,13 @@ backsql_add( Operation *op, SlapReply *rs ) } } -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_RESET_PARAMS ); -#else /* BACKSQL_REALLOC_STMT */ SQLFreeStmt( sth, SQL_DROP ); -#endif /* BACKSQL_REALLOC_STMT */ Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " "create_proc returned keyval=%ld\n", op->oq_add.rs_e->e_name.bv_val, new_keyval, 0 ); for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) { - SQLUSMALLINT currpos; - Debug( LDAP_DEBUG_TRACE, " backsql_add(): " "adding attribute \"%s\"\n", at->a_desc->ad_cname.bv_val, 0, 0 ); @@ -840,151 +1065,33 @@ backsql_add( Operation *op, SlapReply *rs ) /* * Skip: * - the first occurrence of objectClass, which is used - * to determine how to bulid the SQL entry (FIXME ?!?) + * to determine how to build the SQL entry (FIXME ?!?) * - operational attributes - * empty attributes (FIXME ?!?) + * - empty attributes (FIXME ?!?) */ if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) { continue; } - at_rec = backsql_ad2at( oc, at->a_desc ); - - if ( at_rec == NULL ) { - Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " - "attribute \"%s\" is not registered " - "in objectclass \"%s\"\n", - op->oq_add.rs_e->e_name.bv_val, - at->a_desc->ad_cname.bv_val, - BACKSQL_OC_NAME( oc ) ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_UNWILLING_TO_PERFORM; - rs->sr_text = "operation not permitted " - "within namingContext"; - goto done; - } - + if ( at->a_desc == slap_schema.si_ad_objectClass ) { + at_objectClass = at; continue; } - - if ( at_rec->bam_add_proc == NULL ) { - Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " - "add procedure is not defined " - "for attribute \"%s\" " - "of structuralObjectClass \"%s\"\n", - op->oq_add.rs_e->e_name.bv_val, - at->a_desc->ad_cname.bv_val, - BACKSQL_OC_NAME( oc ) ); - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_UNWILLING_TO_PERFORM; - rs->sr_text = "operation not permitted " - "within namingContext"; - goto done; - } - - continue; - } - -#ifdef BACKSQL_REALLOC_STMT - rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 ); - if ( rc != SQL_SUCCESS ) { - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } - - continue; - } -#endif /* BACKSQL_REALLOC_STMT */ - - if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) { - pno = 1; - SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, - SQL_C_ULONG, SQL_INTEGER, - 0, 0, &prc, 0, 0 ); - } else { - pno = 0; - } - - po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0; - currpos = pno + 1 + po; - SQLBindParameter( sth, currpos, - SQL_PARAM_INPUT, SQL_C_ULONG, - SQL_INTEGER, 0, 0, &new_keyval, 0, 0 ); - currpos = pno + 2 - po; - - for ( i = 0, at_val = &at->a_vals[ i ]; - at_val->bv_val != NULL; - i++, at_val = &at->a_vals[ i ] ) { - char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL"; - - /* - * Do not deal with the objectClass that is used - * to build the entry - */ - if ( at->a_desc == slap_schema.si_ad_objectClass ) { - if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) ) { - continue; - } - } - - /* - * check for syntax needed here - * maybe need binary bind? - */ - - backsql_BindParamStr( sth, currpos, - at_val->bv_val, at_val->bv_len + 1 ); - -#ifdef LDAP_DEBUG - snprintf( logbuf, sizeof( logbuf ), "val[%d], id=%ld", - i, new_keyval ); - Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " - "executing \"%s\" %s\n", - op->oq_add.rs_e->e_name.bv_val, - at_rec->bam_add_proc, logbuf ); -#endif -#ifndef BACKSQL_REALLOC_STMT - rc = SQLExecDirect( sth, at_rec->bam_add_proc, SQL_NTS ); -#else /* BACKSQL_REALLOC_STMT */ - rc = SQLExecute( sth ); -#endif /* BACKSQL_REALLOC_STMT */ - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, - " backsql_add(\"%s\"): " - "add_proc execution failed\n", - op->oq_add.rs_e->e_name.bv_val, 0, 0 ); - backsql_PrintErrors( bi->db_env, dbh, sth, rc ); - - if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) { - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - goto done; - } - } + rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto done; } -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_RESET_PARAMS ); -#else /* BACKSQL_REALLOC_STMT */ - SQLFreeStmt( sth, SQL_DROP ); -#endif /* BACKSQL_REALLOC_STMT */ } -#ifdef BACKSQL_REALLOC_STMT rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 ); if ( rc != SQL_SUCCESS ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; goto done; } -#endif /* BACKSQL_REALLOC_STMT */ - backsql_BindParamStr( sth, 1, op->oq_add.rs_e->e_name.bv_val, - BACKSQL_MAX_DN_LEN ); + backsql_BindParamStr( sth, 1, realdn.bv_val, BACKSQL_MAX_DN_LEN ); SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &oc->bom_id, 0, 0 ); #ifdef BACKSQL_ARBITRARY_KEY @@ -1008,11 +1115,7 @@ backsql_add( Operation *op, SlapReply *rs ) "parent_id=%ld, keyval=%ld\n", oc->bom_id, parent_id.eid_id, new_keyval ); #endif /* ! BACKSQL_ARBITRARY_KEY */ -#ifndef BACKSQL_REALLOC_STMT - rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS ); -#else /* BACKSQL_REALLOC_STMT */ rc = SQLExecute( sth ); -#endif /* BACKSQL_REALLOC_STMT */ if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " "could not insert ldap_entries record\n", @@ -1027,14 +1130,27 @@ backsql_add( Operation *op, SlapReply *rs ) rs->sr_text = "SQL-backend error"; goto done; } - + + /* FIXME: need ldap_entries.id of newly added entry */ + if ( at_objectClass ) { + rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at_objectClass, new_keyval ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto done; + } + } + SQLFreeStmt( sth, SQL_DROP ); +done:; /* * Commit only if all operations succeed */ - SQLTransact( SQL_NULL_HENV, dbh, - op->o_noop ? SQL_ROLLBACK : SQL_COMMIT ); + if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { + SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT ); + + } else { + SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK ); + } /* * FIXME: NOOP does not work for add -- it works for all @@ -1047,16 +1163,17 @@ backsql_add( Operation *op, SlapReply *rs ) * in deleting that row. */ -done:; send_ldap_result( op, rs ); - if ( realdn.bv_val != op->oq_add.rs_e->e_name.bv_val ) { + if ( !BER_BVISNULL( &realdn ) + && realdn.bv_val != op->oq_add.rs_e->e_name.bv_val ) + { ch_free( realdn.bv_val ); } - if ( realpdn.bv_val != pdn.bv_val ) { + if ( !BER_BVISNULL( &realpdn ) && realpdn.bv_val != pdn.bv_val ) { ch_free( realpdn.bv_val ); } - if ( parent_id.eid_dn.bv_val != NULL ) { + if ( !BER_BVISNULL( &parent_id.eid_dn ) ) { backsql_free_entryID( &parent_id, 0 ); } diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index 4046bb3057..08370e7abe 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -98,6 +98,18 @@ */ #undef BACKSQL_ARBITRARY_KEY +/* + * define to the appropriate aliasing string + */ +#define BACKSQL_ALIASING "AS " +/* #define BACKSQL_ALIASING "" */ + +/* + * define to the appropriate quoting char + */ +/* #define BACKSQL_ALIASING_QUOTE '"' */ +/* #define BACKSQL_ALIASING_QUOTE '\'' */ + /* * API */ @@ -250,6 +262,7 @@ typedef struct backsql_srch_info { time_t bsi_stoptime; backsql_entryID *bsi_id_list, + **bsi_id_listtail, *bsi_c_eid; int bsi_n_candidates; int bsi_abandon; @@ -284,7 +297,10 @@ typedef struct { struct berval subtree_cond; struct berval children_cond; char *oc_query, *at_query; - char *insentry_query,*delentry_query; + char *insentry_query, + *delentry_query, + *delobjclasses_query, + *delreferrals_query; char *id_query; char *has_children_query; @@ -336,6 +352,9 @@ typedef struct { #define BACKSQL_SUCCESS( rc ) \ ( (rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO ) +#define BACKSQL_AVL_STOP 0 +#define BACKSQL_AVL_CONTINUE 1 + #endif /* __BACKSQL_H__ */ diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c index 21906b22f4..2f8d31c2c0 100644 --- a/servers/slapd/back-sql/bind.c +++ b/servers/slapd/back-sql/bind.c @@ -101,22 +101,33 @@ backsql_bind( Operation *op, SlapReply *rs ) backsql_init_search( &bsi, &dn, LDAP_SCOPE_BASE, -1, -1, -1, NULL, dbh, op, rs, anlist ); - e = backsql_id2entry( &bsi, &user_entry, &user_id ); - if ( e == NULL ) { + bsi.bsi_e = &user_entry; + rc = backsql_id2entry( &bsi, &user_id ); + if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " - "error in backsql_id2entry() - auth failed\n", - 0, 0, 0 ); - rs->sr_err = LDAP_OTHER; + "error %d in backsql_id2entry() " + "- auth failed\n", rc, 0, 0 ); + rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } + e = &user_entry; if ( ! access_allowed( op, e, password, NULL, ACL_AUTH, NULL ) ) { +#if 1 + rs->sr_err = LDAP_INVALID_CREDENTIALS; +#else rs->sr_err = LDAP_INSUFFICIENT_ACCESS; +#endif goto error_return; } - if ( ( a = attr_find( e->e_attrs, password ) ) == NULL ) { + a = attr_find( e->e_attrs, password ); + if ( a == NULL ) { +#if 1 + rs->sr_err = LDAP_INVALID_CREDENTIALS; +#else rs->sr_err = LDAP_INAPPROPRIATE_AUTH; +#endif goto error_return; } diff --git a/servers/slapd/back-sql/compare.c b/servers/slapd/back-sql/compare.c index 3526389a42..f92feb8327 100644 --- a/servers/slapd/back-sql/compare.c +++ b/servers/slapd/back-sql/compare.c @@ -35,7 +35,7 @@ backsql_compare( Operation *op, SlapReply *rs ) backsql_entryID user_id = BACKSQL_ENTRYID_INIT; SQLHDBC dbh; Entry *e = NULL, user_entry; - Attribute *a = NULL, *a_op = NULL; + Attribute *a = NULL; backsql_srch_info bsi; int rc; AttributeName anlist[2]; @@ -79,55 +79,42 @@ backsql_compare( Operation *op, SlapReply *rs ) goto return_results; } + memset( &anlist[0], 0, 2 * sizeof( AttributeName ) ); anlist[0].an_name = op->oq_compare.rs_ava->aa_desc->ad_cname; anlist[0].an_desc = op->oq_compare.rs_ava->aa_desc; - anlist[1].an_name.bv_val = NULL; - /* - * Try to get attr as dynamic operational - */ - if ( is_at_operational( op->oq_compare.rs_ava->aa_desc->ad_type ) ) { - AttributeName *an_old; - Entry *e_old; - - user_entry.e_attrs = NULL; - user_entry.e_name = op->o_req_dn; - user_entry.e_nname = op->o_req_ndn; - - an_old = rs->sr_attrs; - e_old = rs->sr_entry; - - rs->sr_attrs = anlist; - rs->sr_entry = &user_entry; - rs->sr_err = backsql_operational( op, rs, 0, &a_op ); - rs->sr_attrs = an_old; - rs->sr_entry = e_old; - - if ( rs->sr_err != LDAP_SUCCESS ) { - goto return_results; - } - - } - - /* - * attr was dynamic operational - */ - if ( a_op != NULL ) { - user_entry.e_attrs = a_op; - e = &user_entry; - - } else { + /* + * Try to get attr as dynamic operational + */ + if ( is_at_operational( op->oq_compare.rs_ava->aa_desc->ad_type ) ) { + SlapReply nrs = { 0 }; + + user_entry.e_attrs = NULL; + user_entry.e_name = op->o_req_dn; + user_entry.e_nname = op->o_req_ndn; + + nrs.sr_attrs = anlist; + nrs.sr_entry = &user_entry; + rs->sr_err = backsql_operational( op, &nrs, 0, &user_entry.e_attrs ); + + if ( rs->sr_err != LDAP_SUCCESS ) { + goto return_results; + } + + } else { backsql_init_search( &bsi, &dn, LDAP_SCOPE_BASE, - -1, -1, -1, NULL, dbh, op, rs, anlist ); - e = backsql_id2entry( &bsi, &user_entry, &user_id ); - if ( e == NULL ) { + -1, -1, -1, NULL, dbh, op, rs, anlist ); + bsi.bsi_e = &user_entry; + rc = backsql_id2entry( &bsi, &user_id ); + if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_compare(): " - "error in backsql_id2entry() " - "- compare failed\n", 0, 0, 0 ); - rs->sr_err = LDAP_OTHER; + "error %d in backsql_id2entry() " + "- compare failed\n", rc, 0, 0 ); + rs->sr_err = rc; goto return_results; } } + e = &user_entry; if ( ! access_allowed( op, e, op->oq_compare.rs_ava->aa_desc, &op->oq_compare.rs_ava->aa_value, @@ -162,17 +149,7 @@ return_results:; } if ( e != NULL ) { - if ( e->e_name.bv_val != NULL ) { - free( e->e_name.bv_val ); - } - - if ( e->e_nname.bv_val != NULL ) { - free( e->e_nname.bv_val ); - } - - if ( e->e_attrs != NULL ) { - attrs_free( e->e_attrs ); - } + entry_clean( e ); } Debug(LDAP_DEBUG_TRACE,"<==backsql_compare()\n",0,0,0); diff --git a/servers/slapd/back-sql/config.c b/servers/slapd/back-sql/config.c index bce6198045..02795c64ef 100644 --- a/servers/slapd/back-sql/config.c +++ b/servers/slapd/back-sql/config.c @@ -274,6 +274,32 @@ backsql_db_config( Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " "delentry_query=%s\n", si->delentry_query, 0, 0 ); + } else if ( !strcasecmp( argv[ 0 ], "delobjclasses_query" ) ) { + if ( argc < 2 ) { + Debug( LDAP_DEBUG_TRACE, + "<==backsql_db_config (%s line %d): " + "missing SQL statement " + "in \"delobjclasses_query\" directive\n", + fname, lineno, 0 ); + return 1; + } + si->delobjclasses_query = ch_strdup( argv[ 1 ] ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " + "delobjclasses_query=%s\n", si->delobjclasses_query, 0, 0 ); + + } else if ( !strcasecmp( argv[ 0 ], "delreferrals_query" ) ) { + if ( argc < 2 ) { + Debug( LDAP_DEBUG_TRACE, + "<==backsql_db_config (%s line %d): " + "missing SQL statement " + "in \"delreferrals_query\" directive\n", + fname, lineno, 0 ); + return 1; + } + si->delreferrals_query = ch_strdup( argv[ 1 ] ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " + "delreferrals_query=%s\n", si->delreferrals_query, 0, 0 ); + } else if ( !strcasecmp( argv[ 0 ], "has_ldapinfo_dn_ru") ) { if ( argc < 2 ) { Debug( LDAP_DEBUG_TRACE, diff --git a/servers/slapd/back-sql/delete.c b/servers/slapd/back-sql/delete.c index 3f4cfb99a4..31d0ef8c10 100644 --- a/servers/slapd/back-sql/delete.c +++ b/servers/slapd/back-sql/delete.c @@ -30,6 +30,55 @@ #include "ldap_pvt.h" #include "proto-sql.h" +typedef struct backsql_delete_attr_t { + Operation *op; + SlapReply *rs; + SQLHDBC dbh; + backsql_entryID *e_id; +} backsql_delete_attr_t; + +static int +backsql_delete_attr_f( void *v_at, void *v_bda ) +{ + backsql_at_map_rec *at = (backsql_at_map_rec *)v_at; + backsql_delete_attr_t *bda = (backsql_delete_attr_t *)v_bda; + int rc; + + rc = backsql_modify_delete_all_values( bda->op, + bda->rs, bda->dbh, bda->e_id, at ); + + if ( rc != LDAP_SUCCESS ) { + return BACKSQL_AVL_STOP; + } + + return BACKSQL_AVL_CONTINUE; +} + +static int +backsql_delete_all_attrs( + Operation *op, + SlapReply *rs, + SQLHDBC dbh, + backsql_entryID *e_id, + backsql_oc_map_rec *oc ) +{ + backsql_delete_attr_t bda; + int rc; + + bda.op = op; + bda.rs = rs; + bda.dbh = dbh; + bda.e_id = e_id; + + rc = avl_apply( oc->bom_attrs, backsql_delete_attr_f, &bda, + BACKSQL_AVL_STOP, AVL_INORDER ); + if ( rc == BACKSQL_AVL_STOP ) { + return rs->sr_err; + } + + return LDAP_SUCCESS; +} + int backsql_delete( Operation *op, SlapReply *rs ) { @@ -114,7 +163,11 @@ backsql_delete( Operation *op, SlapReply *rs ) goto done; } - SQLAllocStmt( dbh, &sth ); + /* avl_apply ... */ + rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, &e_id, oc ); + if ( rs->sr_err != LDAP_SUCCESS ) { + goto done; + } rc = backsql_Prepare( dbh, &sth, oc->bom_delete_proc, 0 ); if ( rc != SQL_SUCCESS ) { @@ -157,13 +210,91 @@ backsql_delete( Operation *op, SlapReply *rs ) rs->sr_text = "SQL-backend error"; goto done; } -#ifndef BACKSQL_REALLOC_STMT - SQLFreeStmt( sth, SQL_RESET_PARAMS ); -#else /* BACKSQL_REALLOC_STMT */ SQLFreeStmt( sth, SQL_DROP ); - SQLAllocStmt( dbh, &sth ); -#endif /* BACKSQL_REALLOC_STMT */ + /* delete "auxiliary" objectClasses, if any... */ + rc = backsql_Prepare( dbh, &sth, bi->delobjclasses_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_delete(): " + "error preparing ldap_entry_objclasses delete query\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + +#ifdef BACKSQL_ARBITRARY_KEY + SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, + 0, 0, e_id.eid_id.bv_val, 0, 0 ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, + 0, 0, &e_id.eid_id, 0, 0 ); +#endif /* ! BACKSQL_ARBITRARY_KEY */ + rc = SQLExecute( sth ); + switch ( rc ) { + case SQL_NO_DATA: + /* apparently there were no "auxiliary" objectClasses + * for this entry... */ + case SQL_SUCCESS: + break; + + default: + Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " + "failed to delete record from ldap_entry_objclasses\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + SQLFreeStmt( sth, SQL_DROP ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + SQLFreeStmt( sth, SQL_DROP ); + + /* delete referrals, if any... */ + rc = backsql_Prepare( dbh, &sth, bi->delreferrals_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_delete(): " + "error preparing ldap_referrals delete query\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + +#ifdef BACKSQL_ARBITRARY_KEY + SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, + 0, 0, e_id.eid_id.bv_val, 0, 0 ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, + 0, 0, &e_id.eid_id, 0, 0 ); +#endif /* ! BACKSQL_ARBITRARY_KEY */ + rc = SQLExecute( sth ); + switch ( rc ) { + case SQL_NO_DATA: + /* apparently there were no referrals + * for this entry... */ + case SQL_SUCCESS: + break; + + default: + Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " + "failed to delete record from ldap_referrals\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + SQLFreeStmt( sth, SQL_DROP ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + SQLFreeStmt( sth, SQL_DROP ); + + /* delete entry... */ rc = backsql_Prepare( dbh, &sth, bi->delentry_query, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, @@ -195,6 +326,7 @@ backsql_delete( Operation *op, SlapReply *rs ) rs->sr_text = "SQL-backend error"; goto done; } + SQLFreeStmt( sth, SQL_DROP ); /* * Commit only if all operations succeed diff --git a/servers/slapd/back-sql/entry-id.c b/servers/slapd/back-sql/entry-id.c index 051e4f12ad..26c2165379 100644 --- a/servers/slapd/back-sql/entry-id.c +++ b/servers/slapd/back-sql/entry-id.c @@ -341,6 +341,18 @@ backsql_get_attr_vals( void *v_at, void *v_bsi ) return 1; } +#ifdef BACKSQL_TRACE +#ifdef BACKSQL_ARBITRARY_KEY + Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): " + "query=\"%s\" keyval=%s\n", at->bam_query, + bsi->bsi_c_eid->eid_keyval.bv_val, 0 ); +#else /* !BACKSQL_ARBITRARY_KEY */ + Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): " + "query=\"%s\" keyval=%d\n", at->bam_query, + bsi->bsi_c_eid->eid_keyval, 0 ); +#endif /* ! BACKSQL_ARBITRARY_KEY */ +#endif /* BACKSQL_TRACE */ + rc = SQLExecute( sth ); if ( ! BACKSQL_SUCCESS( rc ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): " @@ -396,8 +408,8 @@ backsql_get_attr_vals( void *v_at, void *v_bsi ) return 1; } -Entry * -backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid ) +int +backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid ) { int i; int rc; @@ -405,35 +417,44 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid ) Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 ); - rc = dnPrettyNormal( NULL, &eid->eid_dn, &e->e_name, &e->e_nname, + assert( bsi->bsi_e ); + + memset( bsi->bsi_e, 0, sizeof( Entry ) ); + + rc = dnPrettyNormal( NULL, &eid->eid_dn, + &bsi->bsi_e->e_name, &bsi->bsi_e->e_nname, bsi->bsi_op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { - return NULL; + return rc; } + bsi->bsi_e->e_attrs = NULL; + bsi->bsi_e->e_private = NULL; + bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private, eid->eid_oc_id ); - bsi->bsi_e = e; bsi->bsi_c_eid = eid; - e->e_attrs = NULL; - e->e_private = NULL; #ifndef BACKSQL_ARBITRARY_KEY - e->e_id = eid->eid_id; + bsi->bsi_e->e_id = eid->eid_id; #endif /* ! BACKSQL_ARBITRARY_KEY */ + rc = attr_merge_normalize_one( bsi->bsi_e, ad_oc, + &bsi->bsi_oc->bom_oc->soc_cname, + bsi->bsi_op->o_tmpmemctx ); + if ( rc != LDAP_SUCCESS ) { + entry_clean( bsi->bsi_e ); + return rc; + } + if ( bsi->bsi_attrs != NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " "custom attribute list\n", 0, 0, 0 ); for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) { backsql_at_map_rec **vat; - AttributeName *attr = &bsi->bsi_attrs[ i ]; + AttributeName *an = &bsi->bsi_attrs[ i ]; int j; - if ( attr->an_desc == ad_oc ) { - continue; - } - /* if one of the attributes listed here is * a subtype of another, it must be ignored, * because subtypes are already dealt with @@ -446,18 +467,19 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid ) } /* skip subtypes */ - if ( is_at_subtype( attr->an_desc->ad_type, bsi->bsi_attrs[ j ].an_desc->ad_type ) ) + if ( is_at_subtype( an->an_desc->ad_type, + bsi->bsi_attrs[ j ].an_desc->ad_type ) ) { goto next; } } - rc = backsql_supad2at( bsi->bsi_oc, attr->an_desc, &vat ); + rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat ); if ( rc != 0 || vat == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " "attribute \"%s\" is not defined " "for objectlass \"%s\"\n", - attr->an_name.bv_val, + an->an_name.bv_val, BACKSQL_OC_NAME( bsi->bsi_oc ), 0 ); continue; } @@ -478,13 +500,6 @@ next:; bsi, 0, AVL_INORDER ); } - if ( attr_merge_normalize_one( bsi->bsi_e, ad_oc, - &bsi->bsi_oc->bom_oc->soc_cname, - bsi->bsi_op->o_tmpmemctx ) ) { - entry_free( e ); - return NULL; - } - if ( global_schemacheck ) { const char *text = NULL; char textbuf[ 1024 ]; @@ -499,8 +514,12 @@ next:; rc = structural_class( bv, &soc, NULL, &text, textbuf, textlen ); if ( rc != LDAP_SUCCESS ) { - entry_free( e ); - return NULL; + Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " + "structural_class() failed %d (%s)\n", + bsi->bsi_e->e_name.bv_val, + rc, text ? text : "" ); + entry_clean( bsi->bsi_e ); + return rc; } if ( ( bsi->bsi_flags | BSQL_SF_ALL_OPER ) @@ -509,15 +528,15 @@ next:; slap_schema.si_ad_structuralObjectClass, &soc, bsi->bsi_op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { - entry_free( e ); - return NULL; + entry_clean( bsi->bsi_e ); + return rc; } } } Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 ); - return e; + return LDAP_SUCCESS; } #endif /* SLAPD_SQL */ diff --git a/servers/slapd/back-sql/external.h b/servers/slapd/back-sql/external.h index 527172aa1b..57c05321be 100644 --- a/servers/slapd/back-sql/external.h +++ b/servers/slapd/back-sql/external.h @@ -23,7 +23,7 @@ LDAP_BEGIN_DECL -extern BI_init sql_back_initialize; +extern BI_init backsql_initialize; extern BI_destroy backsql_destroy; extern BI_db_init backsql_db_init; diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index b188a679df..9924349930 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -24,6 +24,7 @@ #include #include +#include "ac/string.h" #include "slap.h" #include "ldap_pvt.h" @@ -40,7 +41,7 @@ init_module( memset( &bi, '\0', sizeof( bi ) ); bi.bi_type = "sql"; - bi.bi_init = sql_back_initialize; + bi.bi_init = backsql_initialize; backend_add( &bi ); return 0; @@ -49,7 +50,7 @@ init_module( #endif /* SLAPD_SQL == SLAPD_MOD_DYNAMIC */ int -sql_back_initialize( +backsql_initialize( BackendInfo *bi ) { static char *controls[] = { @@ -161,6 +162,8 @@ backsql_db_destroy( free( si->at_query ); free( si->insentry_query ); free( si->delentry_query ); + free( si->delobjclasses_query ); + free( si->delreferrals_query ); free( si ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 ); @@ -176,7 +179,7 @@ backsql_db_open( ber_len_t idq_len; struct berbuf bb = BB_NULL; - Operation otmp; + Operation otmp = { 0 }; Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): " "testing RDBMS connection\n", 0, 0, 0 ); @@ -247,9 +250,9 @@ backsql_db_open( */ struct berval concat; struct berval values[] = { - { sizeof( "'%'" ) - 1, "'%'" }, - { sizeof( "?" ) - 1, "?" }, - { 0, NULL } + BER_BVC( "'%'" ), + BER_BVC( "?" ), + BER_BVNULL }; struct berbuf bb = BB_NULL; @@ -273,7 +276,7 @@ backsql_db_open( backsql_strfcat( &bb, "blbbb", &si->upper_func, - (ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1, + (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ), "(ldap_entries.dn) LIKE ", &si->upper_func_open, &concat, @@ -286,7 +289,7 @@ backsql_db_open( */ backsql_strfcat( &bb, "lb", - (ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ), "ldap_entries.dn LIKE ", &concat ); } @@ -309,10 +312,10 @@ backsql_db_open( backsql_strfcat( &bb, "blbl", &si->upper_func, - (ber_len_t)sizeof( "(ldap_entries.dn)=" ) - 1, + (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ), "(ldap_entries.dn)=", &si->upper_func, - (ber_len_t)sizeof( "(?)" ) - 1, "(?)" ); + (ber_len_t)STRLENOF( "(?)" ), "(?)" ); } else { @@ -321,7 +324,7 @@ backsql_db_open( */ backsql_strfcat( &bb, "l", - (ber_len_t)sizeof( "ldap_entries.dn=?" ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.dn=?" ), "ldap_entries.dn=?"); } @@ -382,7 +385,29 @@ backsql_db_open( si->delentry_query = ch_strdup( backsql_def_delentry_query ); } - otmp.o_connid = -1; + if ( si->delobjclasses_query == NULL ) { + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "objclasses deletion SQL statement not specified " + "(use \"delobjclasses_query\" directive in slapd.conf)\n", + 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "setting \"%s\" by default\n", + backsql_def_delobjclasses_query, 0, 0 ); + si->delobjclasses_query = ch_strdup( backsql_def_delobjclasses_query ); + } + + if ( si->delreferrals_query == NULL ) { + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "referrals deletion SQL statement not specified " + "(use \"delreferrals_query\" directive in slapd.conf)\n", + 0, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "setting \"%s\" by default\n", + backsql_def_delreferrals_query, 0, 0 ); + si->delreferrals_query = ch_strdup( backsql_def_delreferrals_query ); + } + + otmp.o_connid = (unsigned long)(-1); otmp.o_bd = bd; if ( backsql_get_db_conn( &otmp, &dbh ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " @@ -398,6 +423,7 @@ backsql_db_open( if ( si->upper_func.bv_val == NULL ) { backsql_strcat( &bb, backsql_id_query, "dn=?", NULL ); + } else { if ( BACKSQL_HAS_LDAPINFO_DN_RU( si ) ) { backsql_strcat( &bb, backsql_id_query, @@ -407,12 +433,12 @@ backsql_db_open( backsql_strfcat( &bb, "sbl", backsql_id_query, &si->upper_func, - (ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" ); + (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" ); } else { backsql_strfcat( &bb, "sblbcb", backsql_id_query, &si->upper_func, - (ber_len_t)sizeof( "(dn)=" ) - 1, "(dn)=", + (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=", &si->upper_func_open, '?', &si->upper_func_close ); @@ -460,13 +486,14 @@ backsql_db_close( int backsql_connection_destroy( Backend *bd, Connection *c ) { - Operation o; + Operation o = { 0 }; o.o_bd = bd; o.o_connid = c->c_connid; Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 ); backsql_free_db_conn( &o ); Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 ); + return 0; } diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index ee05c7d8f1..419065ccf6 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -39,16 +39,17 @@ backsql_modrdn( Operation *op, SlapReply *rs ) RETCODE rc; backsql_entryID e_id = BACKSQL_ENTRYID_INIT, pe_id = BACKSQL_ENTRYID_INIT, - new_pid = BACKSQL_ENTRYID_INIT; + new_pe_id = BACKSQL_ENTRYID_INIT; backsql_oc_map_rec *oc = NULL; - struct berval p_dn, p_ndn, + struct berval p_dn = BER_BVNULL, p_ndn = BER_BVNULL, *new_pdn = NULL, *new_npdn = NULL, - new_dn, new_ndn; + new_dn = BER_BVNULL, new_ndn = BER_BVNULL; LDAPRDN new_rdn = NULL; LDAPRDN old_rdn = NULL; Entry e; - Modifications *mod; + Modifications *mod = NULL; struct berval *newSuperior = op->oq_modrdn.rs_newSup; + char *next; Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", " "newrdn=\"%s\", newSuperior=\"%s\"\n", @@ -68,7 +69,8 @@ backsql_modrdn( Operation *op, SlapReply *rs ) rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "could not lookup entry id\n", 0, 0, 0 ); + "could not lookup entry id (%d)\n", + rs->sr_err, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; send_ldap_result( op, rs ); @@ -174,9 +176,10 @@ backsql_modrdn( Operation *op, SlapReply *rs ) goto modrdn_return; } - build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn, NULL ); + build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn, + op->o_tmpmemctx ); rs->sr_err = dnNormalize( 0, NULL, NULL, &new_dn, &new_ndn, - op->o_tmpmemctx ); + op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "new dn is invalid (\"%s\") - aborting\n", @@ -209,7 +212,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) backsql_free_entryID( &pe_id, 0 ); - rs->sr_err = backsql_dn2id( bi, &new_pid, dbh, new_npdn ); + rs->sr_err = backsql_dn2id( bi, &new_pe_id, dbh, new_npdn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not lookup new parent entry id\n", 0, 0, 0 ); @@ -221,16 +224,29 @@ backsql_modrdn( Operation *op, SlapReply *rs ) #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "new parent entry id=%s\n", new_pid.eid_id.bv_val, 0, 0 ); + "new parent entry id=%s\n", new_pe_id.eid_id.bv_val, 0, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " - "new parent entry id=%ld\n", new_pid.eid_id, 0, 0 ); + "new parent entry id=%ld\n", new_pe_id.eid_id, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "executing delentry_query\n", 0, 0, 0 ); - SQLAllocStmt( dbh, &sth ); + + rc = backsql_Prepare( dbh, &sth, bi->delentry_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modrdn(): " + "error preparing delentry_query\n", 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + sth, rc ); + + rs->sr_text = "SQL-backend error"; + rs->sr_err = LDAP_OTHER; + goto done; + } + #ifdef BACKSQL_ARBITRARY_KEY SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, e_id.eid_id.bv_val, 0, 0 ); @@ -238,100 +254,95 @@ backsql_modrdn( Operation *op, SlapReply *rs ) SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.eid_id, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ - rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS ); + rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "failed to delete record from ldap_entries\n", 0, 0, 0 ); backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; send_ldap_result( op, rs ); - goto modrdn_return; + goto done; } - SQLFreeStmt( sth, SQL_RESET_PARAMS ); + SQLFreeStmt( sth, SQL_DROP ); Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "executing insentry_query\n", 0, 0, 0 ); + + rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + " backsql_modrdn(): " + "error preparing insentry_query\n", 0, 0, 0 ); + backsql_PrintErrors( bi->db_env, dbh, + sth, rc ); + + rs->sr_text = "SQL-backend error"; + rs->sr_err = LDAP_OTHER; + goto done; + } + backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN ); SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &e_id.eid_oc_id, 0, 0 ); #ifdef BACKSQL_ARBITRARY_KEY SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, - 0, 0, new_pid.eid_id.bv_val, 0, 0 ); + 0, 0, new_pe_id.eid_id.bv_val, 0, 0 ); SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 0, 0, e_id.eid_keyval.bv_val, 0, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, - 0, 0, &new_pid.eid_id, 0, 0 ); + 0, 0, &new_pe_id.eid_id, 0, 0 ); SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, 0, 0, &e_id.eid_keyval, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ - rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS ); + rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not insert ldap_entries record\n", 0, 0, 0 ); backsql_PrintErrors( bi->db_env, dbh, sth, rc ); + SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; send_ldap_result( op, rs ); - goto modrdn_return; + goto done; } + SQLFreeStmt( sth, SQL_DROP ); /* * Get attribute type and attribute value of our new rdn, * we will need to add that to our new entry */ - if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn, - (char **)&rs->sr_text, - LDAP_DN_FORMAT_LDAP ) ) { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, - " backsql_modrdn: can't figure out " - "type(s)/values(s) of newrdn\n", - 0, 0, 0 ); -#else + if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn, &next, + LDAP_DN_FORMAT_LDAP ) ) + { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn: can't figure out " "type(s)/values(s) of newrdn\n", 0, 0, 0 ); -#endif rs->sr_err = LDAP_INVALID_DN_SYNTAX; - goto modrdn_return; + goto done; } -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, RESULTS, - " backsql_modrdn: new_rdn_type=\"%s\", " - "new_rdn_val=\"%s\"\n", - new_rdn[ 0 ]->la_attr.bv_val, - new_rdn[ 0 ]->la_value.bv_val, 0 ); -#else Debug( LDAP_DEBUG_TRACE, " backsql_modrdn: new_rdn_type=\"%s\", " "new_rdn_val=\"%s\"\n", new_rdn[ 0 ]->la_attr.bv_val, new_rdn[ 0 ]->la_value.bv_val, 0 ); -#endif if ( op->oq_modrdn.rs_deleteoldrdn ) { - if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn, - (char **)&rs->sr_text, - LDAP_DN_FORMAT_LDAP ) ) { -#ifdef NEW_LOGGING - LDAP_LOG ( OPERATION, ERR, - " backsql_modrdn: can't figure out " - "type(s)/values(s) of old_rdn\n", - 0, 0, 0 ); -#else + if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn, &next, + LDAP_DN_FORMAT_LDAP ) ) + { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn: can't figure out " "the old_rdn type(s)/value(s)\n", 0, 0, 0 ); -#endif rs->sr_err = LDAP_OTHER; - goto modrdn_return; + goto done; } } @@ -350,24 +361,24 @@ backsql_modrdn( Operation *op, SlapReply *rs ) oc = backsql_id2oc( bi, e_id.eid_oc_id ); rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod ); - if ( rs->sr_err == LDAP_SUCCESS ) { +done:; + /* + * Commit only if all operations succeed + */ + if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { + SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT ); - /* - * Commit only if all operations succeed - */ - SQLTransact( SQL_NULL_HENV, dbh, - op->o_noop ? SQL_ROLLBACK : SQL_COMMIT ); + } else { + SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK ); } -modrdn_return: - SQLFreeStmt( sth, SQL_DROP ); - - if ( new_dn.bv_val ) { - ch_free( new_dn.bv_val ); +modrdn_return:; + if ( !BER_BVISNULL( &new_dn ) ) { + slap_sl_free( new_dn.bv_val, op->o_tmpmemctx ); } - if ( new_ndn.bv_val ) { - ch_free( new_ndn.bv_val ); + if ( !BER_BVISNULL( &new_ndn ) ) { + slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx ); } /* LDAP v2 supporting correct attribute handling. */ @@ -379,14 +390,14 @@ modrdn_return: } if ( mod != NULL ) { Modifications *tmp; - for (; mod; mod=tmp ) { + for (; mod; mod = tmp ) { tmp = mod->sml_next; free( mod ); } } - if ( new_pid.eid_dn.bv_val ) { - backsql_free_entryID( &pe_id, 0 ); + if ( new_pe_id.eid_dn.bv_val ) { + backsql_free_entryID( &new_pe_id, 0 ); } send_ldap_result( op, rs ); diff --git a/servers/slapd/back-sql/proto-sql.h b/servers/slapd/back-sql/proto-sql.h index e57e9b4d4f..8e3fbc3e99 100644 --- a/servers/slapd/back-sql/proto-sql.h +++ b/servers/slapd/back-sql/proto-sql.h @@ -79,6 +79,13 @@ /* * add.c */ +int backsql_modify_delete_all_values( + Operation *op, + SlapReply *rs, + SQLHDBC dbh, + backsql_entryID *e_id, + backsql_at_map_rec *at ); + int backsql_modify_internal( Operation *op, SlapReply *rs, @@ -115,8 +122,7 @@ int backsql_has_children( backsql_info *bi, SQLHDBC dbh, struct berval *dn ); backsql_entryID *backsql_free_entryID( backsql_entryID *id, int freeit ); /* turns an ID into an entry */ -Entry *backsql_id2entry( backsql_srch_info *bsi, Entry *e, - backsql_entryID *id ); +int backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id ); /* * schema-map.c @@ -190,6 +196,8 @@ extern char backsql_def_at_query[], backsql_def_delentry_query[], backsql_def_insentry_query[], + backsql_def_delobjclasses_query[], + backsql_def_delreferrals_query[], backsql_def_subtree_cond[], backsql_def_upper_subtree_cond[], backsql_id_query[], diff --git a/servers/slapd/back-sql/schema-map.c b/servers/slapd/back-sql/schema-map.c index 88ee4496c8..cd539e8316 100644 --- a/servers/slapd/back-sql/schema-map.c +++ b/servers/slapd/back-sql/schema-map.c @@ -33,21 +33,34 @@ #define BACKSQL_DUPLICATE (-1) +/* NOTE: by default, cannot just compare pointers because + * objectClass/attributeType order would be machine-dependent + * (and tests would fail!); however, if you don't want to run + * tests, or see attributeTypes written in the same order + * they are defined, define */ +/* #undef BACKSQL_USE_PTR_CMP */ + /* * Uses the pointer to the ObjectClass structure */ static int backsql_cmp_oc( const void *v_m1, const void *v_m2 ) { - const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2; + const backsql_oc_map_rec *m1 = v_m1, + *m2 = v_m2; +#ifdef BACKSQL_USE_PTR_CMP return SLAP_PTRCMP( m1->bom_oc, m2->bom_oc ); +#else /* ! BACKSQL_USE_PTR_CMP */ + return ber_bvcmp( &m1->bom_oc->soc_cname, &m2->bom_oc->soc_cname ); +#endif /* ! BACKSQL_USE_PTR_CMP */ } static int backsql_cmp_oc_id( const void *v_m1, const void *v_m2 ) { - const backsql_oc_map_rec *m1 = v_m1, *m2 = v_m2; + const backsql_oc_map_rec *m1 = v_m1, + *m2 = v_m2; return ( m1->bom_id < m2->bom_id ? -1 : ( m1->bom_id > m2->bom_id ? 1 : 0 ) ); } @@ -58,18 +71,27 @@ backsql_cmp_oc_id( const void *v_m1, const void *v_m2 ) static int backsql_cmp_attr( const void *v_m1, const void *v_m2 ) { - const backsql_at_map_rec *m1 = v_m1, *m2 = v_m2; + const backsql_at_map_rec *m1 = v_m1, + *m2 = v_m2; +#ifdef BACKSQL_USE_PTR_CMP return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad ); +#else /* ! BACKSQL_USE_PTR_CMP */ + return ber_bvcmp( &m1->bam_ad->ad_cname, &m2->bam_ad->ad_cname ); +#endif /* ! BACKSQL_USE_PTR_CMP */ } int backsql_dup_attr( void *v_m1, void *v_m2 ) { - backsql_at_map_rec *m1 = v_m1, *m2 = v_m2; + backsql_at_map_rec *m1 = v_m1, + *m2 = v_m2; assert( m1->bam_ad == m2->bam_ad ); - + + /* duplicate definitions of attributeTypes are appended; + * this allows to define multiple rules for the same + * attributeType. Use with care! */ for ( ; m1->bam_next ; m1 = m1->bam_next ); m1->bam_next = m2; m2->bam_next = NULL; @@ -84,25 +106,54 @@ backsql_make_attr_query( { struct berbuf bb = BB_NULL; +#ifdef BACKSQL_ALIASING_QUOTE + backsql_strfcat( &bb, "lblcbclblbcbl", + (ber_len_t)STRLENOF( "SELECT " ), "SELECT ", + &at_map->bam_sel_expr, + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), " " BACKSQL_ALIASING, + BACKSQL_ALIASING_QUOTE, + &at_map->bam_ad->ad_cname, + BACKSQL_ALIASING_QUOTE, + (ber_len_t)STRLENOF( " FROM " ), " FROM ", + &at_map->bam_from_tbls, + (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", + &oc_map->bom_keytbl, + '.', + &oc_map->bom_keycol, + (ber_len_t)STRLENOF( "=?" ), "=?" ); +#else /* ! BACKSQL_ALIASING_QUOTE */ backsql_strfcat( &bb, "lblblblbcbl", - (ber_len_t)sizeof( "SELECT " ) - 1, "SELECT ", + (ber_len_t)STRLENOF( "SELECT " ), "SELECT ", &at_map->bam_sel_expr, - (ber_len_t)sizeof( " AS " ) - 1, " AS ", + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), " " BACKSQL_ALIASING, &at_map->bam_ad->ad_cname, - (ber_len_t)sizeof( " FROM " ) - 1, " FROM ", + (ber_len_t)STRLENOF( " FROM " ), " FROM ", &at_map->bam_from_tbls, - (ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ", + (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", &oc_map->bom_keytbl, '.', &oc_map->bom_keycol, - (ber_len_t)sizeof( "=?" ) - 1, "=?" ); + (ber_len_t)STRLENOF( "=?" ), "=?" ); +#endif /* ! BACKSQL_ALIASING_QUOTE */ - if ( at_map->bam_join_where.bv_val != NULL ) { + if ( !BER_BVISNULL( &at_map->bam_join_where ) ) { backsql_strfcat( &bb, "lb", - (ber_len_t)sizeof( " AND ") - 1, " AND ", + (ber_len_t)STRLENOF( " AND " ), " AND ", &at_map->bam_join_where ); } +#ifdef BACKSQL_ALIASING_QUOTE + backsql_strfcat( &bb, "lcbc", + (ber_len_t)STRLENOF( " ORDER BY " ), " ORDER BY ", + BACKSQL_ALIASING_QUOTE, + &at_map->bam_sel_expr, + BACKSQL_ALIASING_QUOTE ); +#else /* ! BACKSQL_ALIASING_QUOTE */ + backsql_strfcat( &bb, "lb", + (ber_len_t)STRLENOF( " ORDER BY " ), " ORDER BY ", + &at_map->bam_sel_expr ); +#endif /* ! BACKSQL_ALIASING_QUOTE */ + at_map->bam_query = bb.bb_val.bv_val; return 0; @@ -113,13 +164,14 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map ) { backsql_at_map_rec *at_map; char s[] = "+9223372036854775807L"; - ber_len_t slen; + struct berval sbv; struct berbuf bb; - + sbv.bv_val = s; snprintf( s, sizeof( s ), "%ld", oc_map->bom_id ); - slen = strlen( s ); + sbv.bv_len = strlen( s ); + /* extra objectClasses */ at_map = (backsql_at_map_rec *)ch_calloc(1, sizeof( backsql_at_map_rec ) ); at_map->bam_ad = slap_schema.si_ad_objectClass; @@ -133,23 +185,56 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map ) backsql_merge_from_clause( &bb, &oc_map->bom_keytbl ); at_map->bam_from_tbls = bb.bb_val; - bb.bb_val.bv_val = NULL; - bb.bb_val.bv_len = 0; + BER_BVZERO( &bb.bb_val ); bb.bb_len = 0; - backsql_strfcat( &bb, "lbcbll", - (ber_len_t)sizeof( "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=" ) - 1, - "ldap_entries.id=ldap_entry_objclasses.entry_id and ldap_entries.keyval=", + backsql_strfcat( &bb, "lbcblb", + (ber_len_t)STRLENOF( "ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entries.keyval=" ), + "ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entries.keyval=", &oc_map->bom_keytbl, '.', &oc_map->bom_keycol, - (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1, + (ber_len_t)STRLENOF( " and ldap_entries.oc_map_id=" ), " and ldap_entries.oc_map_id=", - slen, s ); + &sbv ); + at_map->bam_join_where = bb.bb_val; at_map->bam_oc = oc_map->bom_oc; - at_map->bam_join_where = bb.bb_val; + at_map->bam_add_proc = NULL; + { + char tmp[] = + "INSERT INTO ldap_entry_objclasses " + "(entry_id,oc_name) VALUES " + "((SELECT id FROM ldap_entries " + "WHERE oc_map_id=" + "18446744073709551615UL " /* 64 bit ULONG */ + "AND keyval=?),?)"; + snprintf( tmp, sizeof(tmp), + "INSERT INTO ldap_entry_objclasses " + "(entry_id,oc_name) VALUES " + "((SELECT id FROM ldap_entries " + "WHERE oc_map_id=%lu " + "AND keyval=?),?)", oc_map->bom_id ); + at_map->bam_add_proc = ch_strdup( tmp ); + } + at_map->bam_delete_proc = NULL; + { + char tmp[] = + "DELETE FROM ldap_entry_objclasses " + "WHERE entry_id=(SELECT id FROM ldap_entries " + "WHERE oc_map_id=" + "18446744073709551615UL " /* 64 bit ULONG */ + "AND keyval=?) AND oc_name=?"; + snprintf( tmp, sizeof(tmp), + "DELETE FROM ldap_entry_objclasses " + "WHERE entry_id=(SELECT id FROM ldap_entries " + "WHERE oc_map_id=%lu" + "AND keyval=?) AND oc_name=?", + oc_map->bom_id ); + at_map->bam_delete_proc = ch_strdup( tmp ); + } + at_map->bam_param_order = 0; at_map->bam_expect_return = 0; at_map->bam_next = NULL; @@ -162,35 +247,85 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map ) oc_map->bom_oc->soc_cname.bv_val, 0 ); } + /* FIXME: we need to correct the objectClass join_where + * after the attribute query is built */ + ch_free( at_map->bam_join_where.bv_val ); + BER_BVZERO( &bb.bb_val ); + bb.bb_len = 0; + backsql_strfcat( &bb, "lbcblb", + (ber_len_t)STRLENOF( /* "ldap_entries.id=ldap_entry_objclasses.entry_id AND " */ "ldap_entries.keyval=" ), + /* "ldap_entries.id=ldap_entry_objclasses.entry_id AND " */ "ldap_entries.keyval=", + &oc_map->bom_keytbl, + '.', + &oc_map->bom_keycol, + (ber_len_t)STRLENOF( " AND ldap_entries.oc_map_id=" ), + " AND ldap_entries.oc_map_id=", + &sbv ); + at_map->bam_join_where = bb.bb_val; + + /* referral attribute */ at_map = (backsql_at_map_rec *)ch_calloc( 1, sizeof( backsql_at_map_rec ) ); at_map->bam_ad = slap_schema.si_ad_ref; ber_str2bv( "ldap_referrals.url", 0, 1, &at_map->bam_sel_expr ); ber_str2bv( "ldap_referrals,ldap_entries", 0, 1, &at_map->bam_from_tbls ); - - bb.bb_val.bv_val = NULL; - bb.bb_val.bv_len = 0; + bb.bb_len = at_map->bam_from_tbls.bv_len + 1; + bb.bb_val = at_map->bam_from_tbls; backsql_merge_from_clause( &bb, &oc_map->bom_keytbl ); at_map->bam_from_tbls = bb.bb_val; - bb.bb_val.bv_val = NULL; - bb.bb_val.bv_len = 0; + BER_BVZERO( &bb.bb_val ); bb.bb_len = 0; - backsql_strfcat( &bb, "lbcbll", - (ber_len_t)sizeof( "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=" ) - 1, - "ldap_entries.id=ldap_referrals.entry_id and ldap_entries.keyval=", + backsql_strfcat( &bb, "lbcblb", + (ber_len_t)STRLENOF( "ldap_entries.id=ldap_referrals.entry_id AND ldap_entries.keyval=" ), + "ldap_entries.id=ldap_referrals.entry_id AND ldap_entries.keyval=", &oc_map->bom_keytbl, '.', &oc_map->bom_keycol, - (ber_len_t)sizeof( " and ldap_entries.oc_map_id=" ) - 1, - " and ldap_entries.oc_map_id=", - slen, s ); + (ber_len_t)STRLENOF( " AND ldap_entries.oc_map_id=" ), + " AND ldap_entries.oc_map_id=", + &sbv ); - at_map->bam_oc = NULL; at_map->bam_join_where = bb.bb_val; + + at_map->bam_oc = NULL; + at_map->bam_add_proc = NULL; + { + char tmp[] = + "INSERT INTO ldap_referrals " + "(entry_id,url) VALUES " + "((SELECT id FROM ldap_entries " + "WHERE oc_map_id=" + "18446744073709551615UL " /* 64 bit ULONG */ + "AND keyval=?),?)"; + snprintf( tmp, sizeof(tmp), + "INSERT INTO ldap_referrals " + "(entry_id,url) VALUES " + "((SELECT id FROM ldap_entries " + "WHERE oc_map_id=%lu " + "AND keyval=?),?)", oc_map->bom_id ); + at_map->bam_add_proc = ch_strdup( tmp ); + } + at_map->bam_delete_proc = NULL; + { + char tmp[] = + "DELETE FROM ldap_referrals " + "WHERE entry_id=(SELECT id FROM ldap_entries " + "WHERE oc_map_id=" + "18446744073709551615UL " /* 64 bit ULONG */ + "AND keyval=?) and url=?"; + snprintf( tmp, sizeof(tmp), + "DELETE FROM ldap_referrals " + "WHERE entry_id=(SELECT id FROM ldap_entries " + "WHERE oc_map_id=%lu" + "AND keyval=?) and url=?", + oc_map->bom_id ); + at_map->bam_delete_proc = ch_strdup( tmp ); + } + at_map->bam_param_order = 0; at_map->bam_expect_return = 0; at_map->bam_next = NULL; @@ -206,15 +341,165 @@ backsql_add_sysmaps( backsql_oc_map_rec *oc_map ) return 1; } +struct backsql_attr_schema_info { + backsql_info *bas_si; + SQLHDBC bas_dbh; + SQLHSTMT bas_sth; + unsigned long *bas_oc_id; + int bas_rc; +}; + +static int +backsql_oc_get_attr_mapping( void *v_oc, void *v_bas ) +{ + RETCODE rc; + BACKSQL_ROW_NTS at_row; + backsql_oc_map_rec *oc_map = (backsql_oc_map_rec *)v_oc; + backsql_at_map_rec *at_map; + struct backsql_attr_schema_info *bas = (struct backsql_attr_schema_info *)v_bas; + + /* bas->bas_oc_id has been bound to bas->bas_sth */ + *bas->bas_oc_id = oc_map->bom_id; + + Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): " + "executing at_query\n" + " \"%s\"\n" + " for objectClass \"%s\"\n" + " with param oc_id=\"%lu\"\n", + bas->bas_si->at_query, + BACKSQL_OC_NAME( oc_map ), + *bas->bas_oc_id ); + + rc = SQLExecute( bas->bas_sth ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): " + "error executing at_query\n" + " \"%s\"\n" + " for objectClass \"%s\"\n" + " with param oc_id=\"%lu\"\n", + bas->bas_si->at_query, + BACKSQL_OC_NAME( oc_map ), + *bas->bas_oc_id ); + backsql_PrintErrors( SQL_NULL_HENV, bas->bas_dbh, bas->bas_sth, rc ); + bas->bas_rc = LDAP_OTHER; + return BACKSQL_AVL_STOP; + } + + backsql_BindRowAsStrings( bas->bas_sth, &at_row ); + for ( ; rc = SQLFetch( bas->bas_sth ), BACKSQL_SUCCESS( rc ); ) { + const char *text = NULL; + struct berval bv; + struct berbuf bb = BB_NULL; + + Debug( LDAP_DEBUG_TRACE, + "attributeType:\n" + "\tname=\"%s\"\n" + "\tsel_expr=\"%s\"\n" + "\tfrom=\"%s\"\n", + at_row.cols[ 0 ], at_row.cols[ 1 ], + at_row.cols[ 2 ] ); + Debug( LDAP_DEBUG_TRACE, + "\tjoin_where=\"%s\"\n" + "\tadd_proc=\"%s\"\n" + "\tdelete_proc=\"%s\"\n", + at_row.cols[ 3 ], at_row.cols[ 4 ], + at_row.cols[ 5 ]); + /* TimesTen */ + Debug( LDAP_DEBUG_TRACE, "\tsel_expr_u=\"%s\"\n", + at_row.cols[ 8 ], 0, 0 ); + at_map = (backsql_at_map_rec *)ch_calloc( 1, + sizeof( backsql_at_map_rec ) ); + rc = slap_str2ad( at_row.cols[ 0 ], + &at_map->bam_ad, &text ); + if ( rc != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): " + "attribute \"%s\" for objectClass \"%s\" " + "is not defined in schema: %s\n", + at_row.cols[ 0 ], + BACKSQL_OC_NAME( oc_map ), text ); + bas->bas_rc = LDAP_CONSTRAINT_VIOLATION; + return BACKSQL_AVL_STOP; + } + + ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr ); + if ( at_row.value_len[ 8 ] < 0 ) { + BER_BVZERO( &at_map->bam_sel_expr_u ); + + } else { + ber_str2bv( at_row.cols[ 8 ], 0, 1, + &at_map->bam_sel_expr_u ); + } + + ber_str2bv( at_row.cols[ 2 ], 0, 0, &bv ); + backsql_merge_from_clause( &bb, &bv ); + at_map->bam_from_tbls = bb.bb_val; + if ( at_row.value_len[ 3 ] < 0 ) { + BER_BVZERO( &at_map->bam_join_where ); + + } else { + ber_str2bv( at_row.cols[ 3 ], 0, 1, + &at_map->bam_join_where ); + } + at_map->bam_add_proc = NULL; + if ( at_row.value_len[ 4 ] > 0 ) { + at_map->bam_add_proc = ch_strdup( at_row.cols[4] ); + } + at_map->bam_delete_proc = NULL; + if ( at_row.value_len[ 5 ] > 0 ) { + at_map->bam_delete_proc = ch_strdup( at_row.cols[ 5 ] ); + } + at_map->bam_param_order = strtol( at_row.cols[ 6 ], + NULL, 0 ); + at_map->bam_expect_return = strtol( at_row.cols[ 7 ], + NULL, 0 ); + backsql_make_attr_query( oc_map, at_map ); + Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): " + "preconstructed query \"%s\"\n", + at_map->bam_query, 0, 0 ); + at_map->bam_next = NULL; + if ( avl_insert( &oc_map->bom_attrs, at_map, backsql_cmp_attr, backsql_dup_attr ) == BACKSQL_DUPLICATE ) { + Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_attr_mapping(): " + "duplicate attribute \"%s\" " + "in objectClass \"%s\" map\n", + at_map->bam_ad->ad_cname.bv_val, + oc_map->bom_oc->soc_cname.bv_val, 0 ); + } + + if ( !BER_BVISNULL( &bas->bas_si->upper_func ) && + BER_BVISNULL( &at_map->bam_sel_expr_u ) ) + { + struct berbuf bb = BB_NULL; + + backsql_strfcat( &bb, "bcbc", + &bas->bas_si->upper_func, + '(' /* ) */ , + &at_map->bam_sel_expr, + /* ( */ ')' ); + at_map->bam_sel_expr_u = bb.bb_val; + } + } + backsql_FreeRow( &at_row ); + SQLFreeStmt( bas->bas_sth, SQL_CLOSE ); + + Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(\"%s\"): " + "autoadding 'objectClass' and 'ref' mappings\n", + BACKSQL_OC_NAME( oc_map ), 0, 0 ); + + (void)backsql_add_sysmaps( oc_map ); + + return BACKSQL_AVL_CONTINUE; +} + + int backsql_load_schema_map( backsql_info *si, SQLHDBC dbh ) { - SQLHSTMT oc_sth, at_sth; - RETCODE rc; - BACKSQL_ROW_NTS oc_row, at_row; - unsigned long oc_id; - backsql_oc_map_rec *oc_map; - backsql_at_map_rec *at_map; + SQLHSTMT sth; + RETCODE rc; + BACKSQL_ROW_NTS oc_row; + unsigned long oc_id; + backsql_oc_map_rec *oc_map; + struct backsql_attr_schema_info bas; Debug( LDAP_DEBUG_TRACE, "==>backsql_load_schema_map()\n", 0, 0, 0 ); @@ -222,7 +507,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh ) * TimesTen : See if the ldap_entries.dn_ru field exists in the schema */ if ( !BACKSQL_DONTCHECK_LDAPINFO_DN_RU( si ) ) { - rc = backsql_Prepare( dbh, &oc_sth, + rc = backsql_Prepare( dbh, &sth, backsql_check_dn_ru_query, 0 ); if ( rc == SQL_SUCCESS ) { /* Yes, the field exists */ @@ -234,49 +519,32 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh ) si->bsql_flags &= ~BSQLF_HAS_LDAPINFO_DN_RU; } - SQLFreeStmt( oc_sth, SQL_DROP ); + SQLFreeStmt( sth, SQL_DROP ); } + Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): oc_query \"%s\"\n", + si->oc_query, 0, 0 ); - rc = backsql_Prepare( dbh, &oc_sth, si->oc_query, 0 ); + rc = backsql_Prepare( dbh, &sth, si->oc_query, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " "error preparing oc_query: \"%s\"\n", si->oc_query, 0, 0 ); - backsql_PrintErrors( si->db_env, dbh, oc_sth, rc ); - return LDAP_OTHER; - } - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): at_query \"%s\"\n", - si->at_query, 0, 0 ); - - rc = backsql_Prepare( dbh, &at_sth, si->at_query, 0 ); - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "error preparing at_query: \"%s\"\n", - si->at_query, 0, 0 ); - backsql_PrintErrors( si->db_env, dbh, at_sth, rc ); + backsql_PrintErrors( si->db_env, dbh, sth, rc ); return LDAP_OTHER; } - rc = backsql_BindParamID( at_sth, 1, &oc_id ); - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "error binding param for at_query: \n", 0, 0, 0 ); - backsql_PrintErrors( si->db_env, dbh, at_sth, rc ); - return LDAP_OTHER; - } - - rc = SQLExecute( oc_sth ); + rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " "error executing oc_query: \n", 0, 0, 0 ); - backsql_PrintErrors( si->db_env, dbh, oc_sth, rc ); + backsql_PrintErrors( si->db_env, dbh, sth, rc ); return LDAP_OTHER; } - backsql_BindRowAsStrings( oc_sth, &oc_row ); - rc = SQLFetch( oc_sth ); - for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( oc_sth ) ) { + backsql_BindRowAsStrings( sth, &oc_row ); + rc = SQLFetch( sth ); + for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) { int colnum; oc_map = (backsql_oc_map_rec *)ch_calloc( 1, @@ -347,119 +615,48 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh ) "add=%d, del=%d; attributes:\n", BACKSQL_IS_ADD( oc_map->bom_expect_return ), BACKSQL_IS_DEL( oc_map->bom_expect_return ), 0 ); + } - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "autoadding 'objectClass' and 'ref' mappings\n", - 0, 0, 0 ); - backsql_add_sysmaps( oc_map ); - rc = SQLExecute( at_sth ); - if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "error executing at_query: \n", 0, 0, 0 ); - backsql_PrintErrors( SQL_NULL_HENV, dbh, at_sth, rc ); - return LDAP_OTHER; - } + backsql_FreeRow( &oc_row ); + SQLFreeStmt( sth, SQL_DROP ); - backsql_BindRowAsStrings( at_sth, &at_row ); - rc = SQLFetch( at_sth ); - for ( ; BACKSQL_SUCCESS(rc); rc = SQLFetch( at_sth ) ) { - const char *text = NULL; - struct berval bv; - struct berbuf bb = BB_NULL; + /* prepare for attribute fetching */ + Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): at_query \"%s\"\n", + si->at_query, 0, 0 ); - Debug( LDAP_DEBUG_TRACE, - "attributeType:\n" - "\tname=\"%s\"\n" - "\tsel_expr=\"%s\"\n" - "\tfrom=\"%s\"\n", - at_row.cols[ 0 ], at_row.cols[ 1 ], - at_row.cols[ 2 ] ); - Debug( LDAP_DEBUG_TRACE, - "\tjoin_where=\"%s\"\n" - "\tadd_proc=\"%s\"\n" - "\tdelete_proc=\"%s\"\n", - at_row.cols[ 3 ], at_row.cols[ 4 ], - at_row.cols[ 5 ]); - /* TimesTen */ - Debug( LDAP_DEBUG_TRACE, "\tsel_expr_u=\"%s\"\n", - at_row.cols[ 8 ], 0, 0 ); - at_map = (backsql_at_map_rec *)ch_calloc( 1, - sizeof( backsql_at_map_rec ) ); - rc = slap_str2ad( at_row.cols[ 0 ], - &at_map->bam_ad, &text ); - if ( rc != LDAP_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "attribute \"%s\" for objectClass \"%s\" " - "is not defined in schema: %s\n", - at_row.cols[ 0 ], - BACKSQL_OC_NAME( oc_map ), text ); - return LDAP_CONSTRAINT_VIOLATION; - } + rc = backsql_Prepare( dbh, &sth, si->at_query, 0 ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " + "error preparing at_query: \"%s\"\n", + si->at_query, 0, 0 ); + backsql_PrintErrors( si->db_env, dbh, sth, rc ); + return LDAP_OTHER; + } - ber_str2bv( at_row.cols[ 1 ], 0, 1, &at_map->bam_sel_expr ); - if ( at_row.value_len[ 8 ] < 0 ) { - at_map->bam_sel_expr_u.bv_val = NULL; - at_map->bam_sel_expr_u.bv_len = 0; - } else { - ber_str2bv( at_row.cols[ 8 ], 0, 1, - &at_map->bam_sel_expr_u ); - } + rc = backsql_BindParamID( sth, 1, &oc_id ); + if ( rc != SQL_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " + "error binding param \"oc_id\" for at_query\n", 0, 0, 0 ); + backsql_PrintErrors( si->db_env, dbh, sth, rc ); + return LDAP_OTHER; + } - ber_str2bv( at_row.cols[ 2 ], 0, 0, &bv ); - backsql_merge_from_clause( &bb, &bv ); - at_map->bam_from_tbls = bb.bb_val; - if ( at_row.value_len[ 3 ] < 0 ) { - at_map->bam_join_where.bv_val = NULL; - at_map->bam_join_where.bv_len = 0; - } else { - ber_str2bv( at_row.cols[ 3 ], 0, 1, - &at_map->bam_join_where ); - } - at_map->bam_add_proc = NULL; - if ( at_row.value_len[ 4 ] > 0 ) { - at_map->bam_add_proc = ch_strdup( at_row.cols[4] ); - } - at_map->bam_delete_proc = NULL; - if ( at_row.value_len[ 5 ] > 0 ) { - at_map->bam_delete_proc = ch_strdup( at_row.cols[ 5 ] ); - } - at_map->bam_param_order = strtol( at_row.cols[ 6 ], - NULL, 0 ); - at_map->bam_expect_return = strtol( at_row.cols[ 7 ], - NULL, 0 ); - backsql_make_attr_query( oc_map, at_map ); - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "preconstructed query \"%s\"\n", - at_map->bam_query, 0, 0 ); - at_map->bam_next = NULL; - if ( avl_insert( &oc_map->bom_attrs, at_map, backsql_cmp_attr, backsql_dup_attr ) == BACKSQL_DUPLICATE ) { - Debug( LDAP_DEBUG_TRACE, "backsql_load_schema_map(): " - "duplicate attribute \"%s\" " - "in objectClass \"%s\" map\n", - at_map->bam_ad->ad_cname.bv_val, - oc_map->bom_oc->soc_cname.bv_val, 0 ); - } + bas.bas_si = si; + bas.bas_dbh = dbh; + bas.bas_sth = sth; + bas.bas_oc_id = &oc_id; + bas.bas_rc = LDAP_SUCCESS; - if ( si->upper_func.bv_val && at_map->bam_sel_expr_u.bv_val == NULL ) { - struct berbuf bb = BB_NULL; + (void)avl_apply( si->oc_by_oc, backsql_oc_get_attr_mapping, + &bas, BACKSQL_AVL_STOP, AVL_INORDER ); + + SQLFreeStmt( sth, SQL_DROP ); - backsql_strfcat( &bb, "bcbc", - &si->upper_func, - '(' /* ) */ , - &at_map->bam_sel_expr, - /* ( */ ')' ); - at_map->bam_sel_expr_u = bb.bb_val; - } - } - backsql_FreeRow( &at_row ); - SQLFreeStmt( at_sth, SQL_CLOSE ); - } - backsql_FreeRow( &oc_row ); - SQLFreeStmt( at_sth, SQL_DROP ); - SQLFreeStmt( oc_sth, SQL_DROP ); si->bsql_flags |= BSQLF_SCHEMA_LOADED; + Debug( LDAP_DEBUG_TRACE, "<==backsql_load_schema_map()\n", 0, 0, 0 ); - return LDAP_SUCCESS; + + return bas.bas_rc; } backsql_oc_map_rec * @@ -667,10 +864,10 @@ backsql_free_attr( void *v_at ) Debug( LDAP_DEBUG_TRACE, "==>free_attr(): \"%s\"\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); ch_free( at->bam_sel_expr.bv_val ); - if ( at->bam_from_tbls.bv_val != NULL ) { + if ( !BER_BVISNULL( &at->bam_from_tbls ) ) { ch_free( at->bam_from_tbls.bv_val ); } - if ( at->bam_join_where.bv_val != NULL ) { + if ( !BER_BVISNULL( &at->bam_join_where ) ) { ch_free( at->bam_join_where.bv_val ); } if ( at->bam_add_proc != NULL ) { @@ -684,7 +881,7 @@ backsql_free_attr( void *v_at ) } /* TimesTen */ - if ( at->bam_sel_expr_u.bv_val ) { + if ( !BER_BVISNULL( &at->bam_sel_expr_u ) ) { ch_free( at->bam_sel_expr_u.bv_val ); } diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index c4a74dedb0..31fac986ca 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -25,15 +25,13 @@ #include #include #include "ac/string.h" +#include "ac/ctype.h" #include "slap.h" #include "lber_pvt.h" #include "ldap_pvt.h" #include "proto-sql.h" -#define BACKSQL_STOP 0 -#define BACKSQL_CONTINUE 1 - static int backsql_process_filter( backsql_srch_info *bsi, Filter *f ); static int backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, @@ -63,7 +61,7 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) return 1; } - for ( ; bsi->bsi_attrs[ n_attrs ].an_name.bv_val; n_attrs++ ) { + for ( ; !BER_BVISNULL( &bsi->bsi_attrs[ n_attrs ].an_name ); n_attrs++ ) { an = &bsi->bsi_attrs[ n_attrs ]; Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): " @@ -89,8 +87,7 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) an[ n_attrs ].an_name = ad->ad_cname; an[ n_attrs ].an_desc = ad; - an[ n_attrs + 1 ].an_name.bv_val = NULL; - an[ n_attrs + 1 ].an_name.bv_len = 0; + BER_BVZERO( &an[ n_attrs + 1 ].an_name ); bsi->bsi_attrs = an; @@ -130,12 +127,13 @@ backsql_init_search( bsi->bsi_attrs = NULL; } else { + int is_oc = 0; + bsi->bsi_attrs = (AttributeName *)ch_calloc( 1, sizeof( AttributeName ) ); - bsi->bsi_attrs[ 0 ].an_name.bv_val = NULL; - bsi->bsi_attrs[ 0 ].an_name.bv_len = 0; + BER_BVZERO( &bsi->bsi_attrs[ 0 ].an_name ); - for ( p = attrs; p->an_name.bv_val; p++ ) { + for ( p = attrs; !BER_BVISNULL( &p->an_name ); p++ ) { /* * ignore "1.1"; handle "+" */ @@ -145,27 +143,35 @@ backsql_init_search( } else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) { continue; + + } else if ( p->an_desc == slap_schema.si_ad_objectClass ) { + is_oc = 1; } backsql_attrlist_add( bsi, p->an_desc ); } + + if ( is_oc == 0 ) { + /* add objectClass if not present, + * because it is required to understand + * if an entry is a referral, an alias + * or so... */ + backsql_attrlist_add( bsi, slap_schema.si_ad_objectClass ); + } } bsi->bsi_abandon = 0; bsi->bsi_id_list = NULL; + bsi->bsi_id_listtail = &bsi->bsi_id_list; bsi->bsi_n_candidates = 0; bsi->bsi_stoptime = stoptime; - bsi->bsi_sel.bb_val.bv_val = NULL; - bsi->bsi_sel.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_sel.bb_val ); bsi->bsi_sel.bb_len = 0; - bsi->bsi_from.bb_val.bv_val = NULL; - bsi->bsi_from.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_from.bb_val ); bsi->bsi_from.bb_len = 0; - bsi->bsi_join_where.bb_val.bv_val = NULL; - bsi->bsi_join_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_join_where.bb_val ); bsi->bsi_join_where.bb_len = 0; - bsi->bsi_flt_where.bb_val.bv_val = NULL; - bsi->bsi_flt_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_flt_where.bb_val ); bsi->bsi_flt_where.bb_len = 0; bsi->bsi_filter_oc = NULL; @@ -201,13 +207,13 @@ backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op ) switch ( op ) { case LDAP_FILTER_AND: backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( " AND " ) - 1, + (ber_len_t)STRLENOF( " AND " ), " AND " ); break; case LDAP_FILTER_OR: backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( " OR " ) - 1, + (ber_len_t)STRLENOF( " OR " ), " OR " ); break; } @@ -254,7 +260,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, * val LIKE '%1%2%3%4%' */ - bv.bv_len = 0; + BER_BVZERO( &bv ); if ( f->f_sub_initial.bv_val ) { bv.bv_len += f->f_sub_initial.bv_len; } @@ -270,7 +276,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, bv.bv_val = ch_malloc( bv.bv_len + 1 ); s = 0; - if ( f->f_sub_initial.bv_val ) { + if ( !BER_BVISNULL( &f->f_sub_initial ) ) { bv.bv_val[ s ] = f->f_sub_initial.bv_val[ 0 ]; for ( i = 1; i < f->f_sub_initial.bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; @@ -281,7 +287,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, } if ( f->f_sub_any != NULL ) { - for ( a = 0; f->f_sub_any[ a ].bv_val != NULL; a++ ) { + for ( a = 0; !BER_BVISNULL( &f->f_sub_any[ a ] ); a++ ) { bv.bv_val[ s ] = f->f_sub_any[ a ].bv_val[ 0 ]; for ( i = 1; i < f->f_sub_any[ a ].bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; @@ -292,7 +298,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, } } - if ( f->f_sub_final.bv_val ) { + if ( !BER_BVISNULL( &f->f_sub_final ) ) { bv.bv_val[ s ] = f->f_sub_final.bv_val[ 0 ]; for ( i = 1; i < f->f_sub_final.bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; @@ -332,16 +338,16 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, backsql_strfcat( &bsi->bsi_flt_where, "bl", &at->bam_sel_expr_u, - (ber_len_t)sizeof( " LIKE '" ) - 1, + (ber_len_t)STRLENOF( " LIKE '" ), " LIKE '" ); } else { backsql_strfcat( &bsi->bsi_flt_where, "bl", &at->bam_sel_expr, - (ber_len_t)sizeof( " LIKE '" ) - 1, " LIKE '" ); + (ber_len_t)STRLENOF( " LIKE '" ), " LIKE '" ); } - if ( f->f_sub_initial.bv_val != NULL ) { + if ( !BER_BVISNULL( &f->f_sub_initial ) ) { ber_len_t start; #ifdef BACKSQL_TRACE @@ -362,7 +368,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, backsql_strfcat( &bsi->bsi_flt_where, "c", '%' ); if ( f->f_sub_any != NULL ) { - for ( i = 0; f->f_sub_any[ i ].bv_val != NULL; i++ ) { + for ( i = 0; !BER_BVISNULL( &f->f_sub_any[ i ] ); i++ ) { ber_len_t start; #ifdef BACKSQL_TRACE @@ -386,7 +392,7 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, } } - if ( f->f_sub_final.bv_val != NULL ) { + if ( !BER_BVISNULL( &f->f_sub_final ) ) { ber_len_t start; #ifdef BACKSQL_TRACE @@ -405,11 +411,55 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, } backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( /* (' */ "')" ) - 1, /* ( */ "')" ); + (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); return 1; } +static int +backsql_merge_from_tbls( backsql_srch_info *bsi, struct berval *from_tbls ) +{ + if ( BER_BVISNULL( from_tbls ) ) { + return LDAP_SUCCESS; + } + + if ( !BER_BVISNULL( &bsi->bsi_from.bb_val ) ) { + char *start, *end, *tmp; + + tmp = ch_strdup( from_tbls->bv_val ); + + for ( start = tmp, end = strchr( start, ',' ); start; ) { + if ( end ) { + end[0] = '\0'; + } + + if ( strstr( bsi->bsi_from.bb_val.bv_val, start) == NULL ) + { + backsql_strfcat( &bsi->bsi_from, "cs", ',', start ); + } + + if ( end ) { + /* in case there are spaces after the comma... */ + for ( start = &end[1]; isspace( start[0] ); start++ ); + if ( start[0] ) { + end = strchr( start, ',' ); + } else { + start = NULL; + } + } else { + start = NULL; + } + } + + ch_free( tmp ); + + } else { + backsql_strfcat( &bsi->bsi_from, "b", from_tbls ); + } + + return LDAP_SUCCESS; +} + static int backsql_process_filter( backsql_srch_info *bsi, Filter *f ) { @@ -442,7 +492,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) case LDAP_FILTER_NOT: backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "NOT (" /* ) */ ) - 1, + (ber_len_t)STRLENOF( "NOT (" /* ) */ ), "NOT (" /* ) */ ); rc = backsql_process_filter( bsi, f->f_not ); backsql_strfcat( &bsi->bsi_flt_where, "c", /* ( */ ')' ); @@ -465,7 +515,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) * like '%attributeName=value%'" */ backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); + (ber_len_t)STRLENOF( "1=1" ), "1=1" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; goto done; @@ -519,19 +569,32 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) * - a search for "top" will return everything */ if ( is_object_subclass( oc, bsi->bsi_oc->bom_oc ) ) { - goto filter_oc_success; + static struct berval ldap_entry_objclasses = BER_BVC( "ldap_entry_objclasses" ); + + backsql_merge_from_tbls( bsi, &ldap_entry_objclasses ); + + backsql_strfcat( &bsi->bsi_flt_where, "lbl", + (ber_len_t)STRLENOF( "1=1 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ), + "1=1 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */, + &bsi->bsi_oc->bom_oc->soc_cname, + (ber_len_t)STRLENOF( /* (' */ "')" ), + /* (' */ "')" ); + bsi->bsi_status = LDAP_SUCCESS; + rc = 1; + goto done; } break; } case LDAP_FILTER_PRESENT: -filter_oc_success:; backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); + (ber_len_t)STRLENOF( "1=1" ), "1=1" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; goto done; + + /* FIXME: LDAP_FILTER_EXT? */ default: Debug( LDAP_DEBUG_TRACE, @@ -560,7 +623,7 @@ filter_oc_success:; * candidate. */ backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); + (ber_len_t)STRLENOF( "1=1" ), "1=1" ); if ( ad == slap_schema.si_ad_hasSubordinates ) { /* * instruct candidate selection algorithm @@ -593,7 +656,7 @@ filter_oc_success:; /* search anyway; other parts of the filter * may succeeed */ backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); + (ber_len_t)STRLENOF( "1=1" ), "1=1" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; goto done; @@ -616,7 +679,7 @@ next:; /* if more definitions of the same attr, apply */ if ( vat[i]->bam_next ) { backsql_strfcat( &bsi->bsi_flt_where, "l", - sizeof( " OR " ) - 1, " OR " ); + STRLENOF( " OR " ), " OR " ); vat[i] = vat[i]->bam_next; goto next; } @@ -625,7 +688,7 @@ next:; i++; if ( vat[i] ) { backsql_strfcat( &bsi->bsi_flt_where, "l", - sizeof( " OR " ) - 1, " OR " ); + STRLENOF( " OR " ), " OR " ); goto next; } @@ -664,14 +727,14 @@ backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, backsql_strfcat( &bsi->bsi_flt_where, "cbl", '(', /* ) */ &at->bam_sel_expr_u, - (ber_len_t)sizeof( "='" ) - 1, + (ber_len_t)STRLENOF( "='" ), "='" ); start = bsi->bsi_flt_where.bb_val.bv_len; backsql_strfcat( &bsi->bsi_flt_where, "bl", filter_value, - (ber_len_t)sizeof( /* (' */ "')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); @@ -680,9 +743,9 @@ backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, backsql_strfcat( &bsi->bsi_flt_where, "cblbl", '(', /* ) */ &at->bam_sel_expr, - (ber_len_t)sizeof( "='" ) - 1, "='", + (ber_len_t)STRLENOF( "='" ), "='", filter_value, - (ber_len_t)sizeof( /* (' */ "')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); } @@ -705,14 +768,14 @@ backsql_process_filter_like( backsql_srch_info *bsi, backsql_at_map_rec *at, backsql_strfcat( &bsi->bsi_flt_where, "cbl", '(', /* ) */ &at->bam_sel_expr_u, - (ber_len_t)sizeof( " LIKE '%" ) - 1, + (ber_len_t)STRLENOF( " LIKE '%" ), " LIKE '%" ); start = bsi->bsi_flt_where.bb_val.bv_len; backsql_strfcat( &bsi->bsi_flt_where, "bl", filter_value, - (ber_len_t)sizeof( /* (' */ "%')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "%')" ), /* (' */ "%')" ); ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); @@ -721,10 +784,10 @@ backsql_process_filter_like( backsql_srch_info *bsi, backsql_at_map_rec *at, backsql_strfcat( &bsi->bsi_flt_where, "cblbl", '(', /* ) */ &at->bam_sel_expr, - (ber_len_t)sizeof( " LIKE '%" ) - 1, + (ber_len_t)STRLENOF( " LIKE '%" ), " LIKE '%", filter_value, - (ber_len_t)sizeof( /* (' */ "%')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "%')" ), /* (' */ "%')" ); } @@ -743,18 +806,20 @@ backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, backsql_at_map_r Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter_attr(%s)\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); - backsql_merge_from_clause( &bsi->bsi_from, &at->bam_from_tbls ); - /* * need to add this attribute to list of attrs to load, * so that we can do test_filter() later */ backsql_attrlist_add( bsi, at->bam_ad ); - if ( at->bam_join_where.bv_val != NULL - && strstr( bsi->bsi_join_where.bb_val.bv_val, at->bam_join_where.bv_val ) == NULL ) { + backsql_merge_from_tbls( bsi, &at->bam_from_tbls ); + + if ( !BER_BVISNULL( &at->bam_join_where ) + && strstr( bsi->bsi_join_where.bb_val.bv_val, + at->bam_join_where.bv_val ) == NULL ) + { backsql_strfcat( &bsi->bsi_join_where, "lb", - (ber_len_t)sizeof( " AND " ) - 1, " AND ", + (ber_len_t)STRLENOF( " AND " ), " AND ", &at->bam_join_where ); } @@ -811,6 +876,23 @@ equality_match:; break; } + /* NOTE: this is required by objectClass inheritance + * and auxiliary objectClass use in filters for slightly + * more efficient candidate selection. */ + /* FIXME: a bit too many specializations to deal with + * very specific cases... */ + if ( at->bam_ad == slap_schema.si_ad_objectClass + || at->bam_ad == slap_schema.si_ad_structuralObjectClass ) + { + backsql_strfcat( &bsi->bsi_flt_where, "lbl", + (ber_len_t)STRLENOF( "(ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ), + "(ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */, + filter_value, + (ber_len_t)STRLENOF( /* (' */ "')" ), + /* (' */ "')" ); + break; + } + /* * maybe we should check type of at->sel_expr here somehow, * to know whether upper_func is applicable, but for now @@ -851,7 +933,7 @@ equality_match:; backsql_strfcat( &bsi->bsi_flt_where, "bl", filter_value, - (ber_len_t)sizeof( /* (' */ "')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); @@ -863,17 +945,17 @@ equality_match:; &ordering, '\'', &f->f_av_value, - (ber_len_t)sizeof( /* (' */ "')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "')" ), /* ( */ "')" ); } break; case LDAP_FILTER_PRESENT: backsql_strfcat( &bsi->bsi_flt_where, "lbl", - (ber_len_t)sizeof( "NOT (" /* ) */) - 1, + (ber_len_t)STRLENOF( "NOT (" /* ) */), "NOT (", /* ) */ &at->bam_sel_expr, - (ber_len_t)sizeof( /* ( */ " IS NULL)" ) - 1, + (ber_len_t)STRLENOF( /* ( */ " IS NULL)" ), /* ( */ " IS NULL)" ); break; @@ -897,7 +979,7 @@ equality_match:; /* unhandled filter type; should not happen */ assert( 0 ); backsql_strfcat( &bsi->bsi_flt_where, "l", - (ber_len_t)sizeof( "1=1" ) - 1, "1=1" ); + (ber_len_t)STRLENOF( "1=1" ), "1=1" ); break; } @@ -915,38 +997,34 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) int rc; assert( query ); - query->bv_val = NULL; - query->bv_len = 0; + BER_BVZERO( query ); Debug( LDAP_DEBUG_TRACE, "==>backsql_srch_query()\n", 0, 0, 0 ); - bsi->bsi_sel.bb_val.bv_val = NULL; - bsi->bsi_sel.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_sel.bb_val ); + BER_BVZERO( &bsi->bsi_sel.bb_val ); bsi->bsi_sel.bb_len = 0; - bsi->bsi_from.bb_val.bv_val = NULL; - bsi->bsi_from.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_from.bb_val ); bsi->bsi_from.bb_len = 0; - bsi->bsi_join_where.bb_val.bv_val = NULL; - bsi->bsi_join_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_join_where.bb_val ); bsi->bsi_join_where.bb_len = 0; - bsi->bsi_flt_where.bb_val.bv_val = NULL; - bsi->bsi_flt_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_flt_where.bb_val ); bsi->bsi_flt_where.bb_len = 0; backsql_strfcat( &bsi->bsi_sel, "lbcbc", - (ber_len_t)sizeof( "SELECT DISTINCT ldap_entries.id," ) - 1, + (ber_len_t)STRLENOF( "SELECT DISTINCT ldap_entries.id," ), "SELECT DISTINCT ldap_entries.id,", &bsi->bsi_oc->bom_keytbl, '.', &bsi->bsi_oc->bom_keycol, ',' ); - if ( bi->strcast_func.bv_val ) { + if ( !BER_BVISNULL( &bi->strcast_func ) ) { backsql_strfcat( &bsi->bsi_sel, "blbl", &bi->strcast_func, - (ber_len_t)sizeof( "('" /* ') */ ) - 1, + (ber_len_t)STRLENOF( "('" /* ') */ ), "('" /* ') */ , &bsi->bsi_oc->bom_oc->soc_cname, - (ber_len_t)sizeof( /* (' */ "')" ) - 1, + (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); } else { backsql_strfcat( &bsi->bsi_sel, "cbc", @@ -954,21 +1032,33 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) &bsi->bsi_oc->bom_oc->soc_cname, '\'' ); } +#ifdef BACKSQL_ALIASING_QUOTE + backsql_strfcat( &bsi->bsi_sel, "lclcl", + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), + " " BACKSQL_ALIASING, + BACKSQL_ALIASING_QUOTE, + (ber_len_t)STRLENOF( "objectClass" ), + "objectClass", + BACKSQL_ALIASING_QUOTE, + (ber_len_t)STRLENOF( ",ldap_entries.dn " BACKSQL_ALIASING "dn" ), + ",ldap_entries.dn " BACKSQL_ALIASING "dn" ); +#else /* ! BACKSQL_ALIASING_QUOTE */ backsql_strfcat( &bsi->bsi_sel, "l", - (ber_len_t)sizeof( " AS objectClass,ldap_entries.dn AS dn" ) - 1, - " AS objectClass,ldap_entries.dn AS dn" ); + (ber_len_t)STRLENOF( " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ), + " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ); +#endif /* ! BACKSQL_ALIASING_QUOTE */ backsql_strfcat( &bsi->bsi_from, "lb", - (ber_len_t)sizeof( " FROM ldap_entries," ) - 1, + (ber_len_t)STRLENOF( " FROM ldap_entries," ), " FROM ldap_entries,", &bsi->bsi_oc->bom_keytbl ); backsql_strfcat( &bsi->bsi_join_where, "lbcbl", - (ber_len_t)sizeof( " WHERE " ) - 1, " WHERE ", + (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", &bsi->bsi_oc->bom_keytbl, '.', &bsi->bsi_oc->bom_keycol, - (ber_len_t)sizeof( "=ldap_entries.keyval AND ldap_entries.oc_map_id=? AND " ) - 1, + (ber_len_t)STRLENOF( "=ldap_entries.keyval AND ldap_entries.oc_map_id=? AND " ), "=ldap_entries.keyval AND ldap_entries.oc_map_id=? AND " ); switch ( bsi->bsi_scope ) { @@ -976,11 +1066,11 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) if ( BACKSQL_CANUPPERCASE( bi ) ) { backsql_strfcat( &bsi->bsi_join_where, "bl", &bi->upper_func, - (ber_len_t)sizeof( "(ldap_entries.dn)=?" ) - 1, + (ber_len_t)STRLENOF( "(ldap_entries.dn)=?" ), "(ldap_entries.dn)=?" ); } else { backsql_strfcat( &bsi->bsi_join_where, "l", - (ber_len_t)sizeof( "ldap_entries.dn=?" ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.dn=?" ), "ldap_entries.dn=?" ); } break; @@ -989,18 +1079,18 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) if ( BACKSQL_CANUPPERCASE( bi ) ) { backsql_strfcat( &bsi->bsi_join_where, "bl", &bi->upper_func, - (ber_len_t)sizeof( "(ldap_entries.dn) LIKE ?" ) - 1, + (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE ?" ), "(ldap_entries.dn) LIKE ?" ); } else { backsql_strfcat( &bsi->bsi_join_where, "l", - (ber_len_t)sizeof( "ldap_entries.dn LIKE ?" ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.dn LIKE ?" ), "ldap_entries.dn LIKE ?" ); } break; case LDAP_SCOPE_ONELEVEL: backsql_strfcat( &bsi->bsi_join_where, "l", - (ber_len_t)sizeof( "ldap_entries.parent=?" ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.parent=?" ), "ldap_entries.parent=?" ); break; @@ -1008,11 +1098,11 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) if ( BACKSQL_CANUPPERCASE( bi ) ) { backsql_strfcat( &bsi->bsi_join_where, "bl", &bi->upper_func, - (ber_len_t)sizeof( "(ldap_entries.dn) LIKE ?" ) - 1, + (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE ?" ), "(ldap_entries.dn) LIKE ?" ); } else { backsql_strfcat( &bsi->bsi_join_where, "l", - (ber_len_t)sizeof( "ldap_entries.dn LIKE ?" ) - 1, + (ber_len_t)STRLENOF( "ldap_entries.dn LIKE ?" ), "ldap_entries.dn LIKE ?" ); } @@ -1030,7 +1120,7 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) &bsi->bsi_sel.bb_val, &bsi->bsi_from.bb_val, &bsi->bsi_join_where.bb_val, - (ber_len_t)sizeof( " AND " ) - 1, " AND ", + (ber_len_t)STRLENOF( " AND " ), " AND ", &bsi->bsi_flt_where.bb_val ); *query = bb.bb_val; @@ -1041,20 +1131,20 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) * anything. No need to issue the query */ free( query->bv_val ); - query->bv_val = NULL; + BER_BVZERO( query ); } free( bsi->bsi_sel.bb_val.bv_val ); - bsi->bsi_sel.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_sel.bb_val ); bsi->bsi_sel.bb_len = 0; free( bsi->bsi_from.bb_val.bv_val ); - bsi->bsi_from.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_from.bb_val ); bsi->bsi_from.bb_len = 0; free( bsi->bsi_join_where.bb_val.bv_val ); - bsi->bsi_join_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_join_where.bb_val ); bsi->bsi_join_where.bb_len = 0; free( bsi->bsi_flt_where.bb_val.bv_val ); - bsi->bsi_flt_where.bb_val.bv_len = 0; + BER_BVZERO( &bsi->bsi_flt_where.bb_val ); bsi->bsi_flt_where.bb_len = 0; Debug( LDAP_DEBUG_TRACE, "<==backsql_srch_query() returns %s\n", @@ -1097,7 +1187,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) /* should never get here */ assert( 0 ); bsi->bsi_status = LDAP_ADMINLIMIT_EXCEEDED; - return BACKSQL_STOP; + return BACKSQL_AVL_STOP; } bsi->bsi_oc = oc; @@ -1118,21 +1208,21 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) default: bsi->bsi_status = LDAP_SUCCESS; /* try next */ - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; case LDAP_ADMINLIMIT_EXCEEDED: case LDAP_OTHER: /* don't try any more */ - return BACKSQL_STOP; + return BACKSQL_AVL_STOP; } } - if ( query.bv_val == NULL ) { + if ( BER_BVISNULL( &query ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "could not construct query for objectclass \"%s\"\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); bsi->bsi_status = LDAP_SUCCESS; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } Debug( LDAP_DEBUG_TRACE, "Constructed query: %s\n", @@ -1140,12 +1230,13 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) rc = backsql_Prepare( bsi->bsi_dbh, &sth, query.bv_val, 0 ); free( query.bv_val ); + BER_BVZERO( &query ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error preparing query\n", 0, 0, 0 ); backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } Debug( LDAP_DEBUG_TRACE, "id: '%ld'\n", bsi->bsi_oc->bom_id, 0, 0 ); @@ -1154,7 +1245,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding objectclass id parameter\n", 0, 0, 0 ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } switch ( bsi->bsi_scope ) { @@ -1166,7 +1257,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) */ if ( bsi->bsi_base_dn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } AC_MEMCPY( temp_base_dn, bsi->bsi_base_dn->bv_val, @@ -1189,7 +1280,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } break; @@ -1200,7 +1291,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) */ if ( bsi->bsi_base_dn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } /* @@ -1249,7 +1340,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } break; } @@ -1263,7 +1354,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) res == LDAP_NO_SUCH_OBJECT ? ": no such entry" : "", 0, 0 ); bsi->bsi_status = res; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } #ifdef BACKSQL_ARBITRARY_KEY @@ -1283,7 +1374,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding base id parameter\n", 0, 0, 0 ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } break; } @@ -1295,7 +1386,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); bsi->bsi_status = LDAP_OTHER; - return BACKSQL_CONTINUE; + return BACKSQL_AVL_CONTINUE; } backsql_BindRowAsStrings( sth, &row ); @@ -1327,9 +1418,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) c_id->eid_dn = dn; } - c_id->eid_next = bsi->bsi_id_list; - bsi->bsi_id_list = c_id; - bsi->bsi_n_candidates--; + /* append at end of list ... */ + c_id->eid_next = NULL; + *bsi->bsi_id_listtail = c_id; + bsi->bsi_id_listtail = &c_id->eid_next; #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " @@ -1342,6 +1434,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) c_id->eid_id, c_id->eid_keyval, row.cols[ 3 ] ); #endif /* ! BACKSQL_ARBITRARY_KEY */ + /* count candidates, for unchecked limit */ + bsi->bsi_n_candidates--; if ( bsi->bsi_n_candidates == -1 ) { break; } @@ -1352,7 +1446,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates(): %d\n", n_candidates - bsi->bsi_n_candidates, 0, 0 ); - return ( bsi->bsi_n_candidates == -1 ? BACKSQL_STOP : BACKSQL_CONTINUE ); + return ( bsi->bsi_n_candidates == -1 ? BACKSQL_AVL_STOP : BACKSQL_AVL_CONTINUE ); } int @@ -1361,7 +1455,7 @@ backsql_search( Operation *op, SlapReply *rs ) backsql_info *bi = (backsql_info *)op->o_bd->be_private; SQLHDBC dbh; int sres; - Entry *entry, *res; + Entry user_entry = { 0 }; int manageDSAit; time_t stoptime = 0; backsql_srch_info srch_info; @@ -1383,7 +1477,7 @@ backsql_search( Operation *op, SlapReply *rs ) if ( op->o_req_ndn.bv_len > BACKSQL_MAX_DN_LEN ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " - "search base length (%ld) exceeds max length (%ld)\n", + "search base length (%ld) exceeds max length (%d)\n", op->o_req_ndn.bv_len, BACKSQL_MAX_DN_LEN, 0 ); /* * FIXME: a LDAP_NO_SUCH_OBJECT could be appropriate @@ -1436,7 +1530,7 @@ backsql_search( Operation *op, SlapReply *rs ) ( op->ors_limit->lms_s_unchecked == -1 ? -2 : ( op->ors_limit->lms_s_unchecked ) ) ); avl_apply( bi->oc_by_oc, backsql_oc_get_candidates, - &srch_info, BACKSQL_STOP, AVL_INORDER ); + &srch_info, BACKSQL_AVL_STOP, AVL_INORDER ); if ( op->ors_limit != NULL /* isroot == TRUE */ && op->ors_limit->lms_s_unchecked != -1 && srch_info.bsi_n_candidates == -1 ) @@ -1451,8 +1545,11 @@ backsql_search( Operation *op, SlapReply *rs ) * mentioned in attrs and filter), test it against full filter * and then send to client */ - for ( eid = srch_info.bsi_id_list; eid != NULL; - eid = backsql_free_entryID( eid, 1 ) ) { + for ( eid = srch_info.bsi_id_list; + eid != NULL; + eid = backsql_free_entryID( eid, 1 ) ) + { + int rc; Attribute *hasSubordinate = NULL, *a = NULL; @@ -1485,24 +1582,73 @@ backsql_search( Operation *op, SlapReply *rs ) eid->eid_id, eid->eid_oc_id, eid->eid_keyval ); #endif /* ! BACKSQL_ARBITRARY_KEY */ - entry = (Entry *)ch_calloc( sizeof( Entry ), 1 ); - res = backsql_id2entry( &srch_info, entry, eid ); - if ( res == NULL ) { + srch_info.bsi_e = &user_entry; + rc = backsql_id2entry( &srch_info, eid ); + if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " - "error in backsql_id2entry() " - "- skipping entry\n", 0, 0, 0 ); + "error %d in backsql_id2entry() " + "- skipping\n", rc, 0, 0 ); continue; } + /* check scope */ + switch ( op->ors_scope ) { + case LDAP_SCOPE_BASE: + case BACKSQL_SCOPE_BASE_LIKE: + if ( !bvmatch( &user_entry.e_nname, &op->o_req_ndn ) ) { + goto next_entry; + } + break; + + case LDAP_SCOPE_ONE: + { + struct berval rdn = user_entry.e_nname; + rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); + if ( !dnIsOneLevelRDN( &rdn ) ) { + goto next_entry; + } + /* fall thru */ + } + + case LDAP_SCOPE_SUBTREE: + if ( !dnIsSuffix( &user_entry.e_nname, &op->o_req_ndn ) ) { + goto next_entry; + } + break; + } + if ( !manageDSAit && op->ors_scope != LDAP_SCOPE_BASE && op->ors_scope != BACKSQL_SCOPE_BASE_LIKE && - is_entry_referral( entry ) ) { + is_entry_referral( &user_entry ) ) + { BerVarray refs; struct berval matched_dn; - ber_dupbv( &matched_dn, &entry->e_name ); - refs = get_entry_referrals( op, entry ); + ber_dupbv( &matched_dn, &user_entry.e_name ); + refs = get_entry_referrals( op, &user_entry ); + if ( !refs ) { + backsql_srch_info srch_info2 = { 0 }; + Entry user_entry2 = { 0 }; + + /* retry with the full entry... */ + backsql_init_search( &srch_info2, + &user_entry.e_name, + LDAP_SCOPE_BASE, + -1, -1, -1, NULL, + dbh, op, rs, NULL ); + srch_info2.bsi_e = &user_entry2; + rc = backsql_id2entry( &srch_info2, eid ); + if ( rc == LDAP_SUCCESS ) { + if ( is_entry_referral( &user_entry2 ) ) + { + refs = get_entry_referrals( op, + &user_entry2 ); + } /* else: FIXME: inconsistency! */ + entry_clean( &user_entry2 ); + } + } + if ( refs ) { rs->sr_ref = referral_rewrite( refs, &matched_dn, &op->o_req_dn, @@ -1523,7 +1669,7 @@ backsql_search( Operation *op, SlapReply *rs ) ber_memfree( matched_dn.bv_val ); rs->sr_matched = NULL; - continue; + goto next_entry; } /* @@ -1532,16 +1678,14 @@ backsql_search( Operation *op, SlapReply *rs ) * filter_has_subordinates() */ if ( srch_info.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) { - int rc; - - rc = backsql_has_children( bi, dbh, &entry->e_nname ); + rc = backsql_has_children( bi, dbh, &user_entry.e_nname ); - switch( rc ) { + switch ( rc ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: hasSubordinate = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE ); if ( hasSubordinate != NULL ) { - for ( a = entry->e_attrs; + for ( a = user_entry.e_attrs; a && a->a_next; a = a->a_next ); @@ -1556,15 +1700,11 @@ backsql_search( Operation *op, SlapReply *rs ) "has_children failed( %d)\n", rc, 0, 0 ); rc = 1; - break; - } - - if ( rc ) { - continue; + goto next_entry; } } - if ( test_filter( op, entry, op->ors_filter ) + if ( test_filter( op, &user_entry, op->ors_filter ) == LDAP_COMPARE_TRUE ) { if ( hasSubordinate && !( srch_info.bsi_flags & BSQL_SF_ALL_OPER ) && !ad_inlist( slap_schema.si_ad_hasSubordinates, op->ors_attrs ) ) { @@ -1573,38 +1713,31 @@ backsql_search( Operation *op, SlapReply *rs ) hasSubordinate = NULL; } -#if 0 /* noop is masked SLAP_CTRL_UPDATE */ - if ( op->o_noop ) { - sres = 0; - } else -#endif - { - rs->sr_attrs = op->ors_attrs; - rs->sr_entry = entry; - rs->sr_flags = REP_ENTRY_MODIFIABLE; - sres = send_search_entry( op, rs ); - rs->sr_entry = NULL; - rs->sr_attrs = NULL; - } + rs->sr_attrs = op->ors_attrs; + rs->sr_entry = &user_entry; + rs->sr_flags = REP_ENTRY_MODIFIABLE; + sres = send_search_entry( op, rs ); + rs->sr_entry = NULL; + rs->sr_attrs = NULL; switch ( sres ) { case 0: break; - case -1: - Debug( LDAP_DEBUG_TRACE, "backsql_search(): " - "connection lost\n", 0, 0, 0 ); - goto end_of_search; - default: /* * FIXME: send_search_entry failed; * better stop */ - break; + case -1: + Debug( LDAP_DEBUG_TRACE, "backsql_search(): " + "connection lost\n", 0, 0, 0 ); + goto end_of_search; } } - entry_free( entry ); + +next_entry:; + entry_clean( &user_entry ); if ( op->ors_slimit != SLAP_NO_LIMIT && rs->sr_nentries >= op->ors_slimit ) @@ -1616,11 +1749,14 @@ backsql_search( Operation *op, SlapReply *rs ) } end_of_search:; + /* in case we got here accidentally */ + entry_clean( &user_entry ); if ( rs->sr_nentries > 0 ) { rs->sr_ref = rs->sr_v2ref; rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS : LDAP_REFERRAL; + } else { rs->sr_err = srch_info.bsi_status; } diff --git a/servers/slapd/back-sql/sql-wrap.c b/servers/slapd/back-sql/sql-wrap.c index 86b4689316..ff0fa3d941 100644 --- a/servers/slapd/back-sql/sql-wrap.c +++ b/servers/slapd/back-sql/sql-wrap.c @@ -32,8 +32,8 @@ #define MAX_ATTR_LEN 16384 -typedef struct backsql_conn { - int ldap_cid; +typedef struct backsql_db_conn { + unsigned long ldap_cid; SQLHDBC dbh; } backsql_db_conn; @@ -145,6 +145,7 @@ backsql_BindRowAsStrings( SQLHSTMT sth, BACKSQL_ROW_NTS *row ) #endif /* BACKSQL_TRACE */ backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc ); + } else { #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: " @@ -270,6 +271,7 @@ int backsql_init_db_env( backsql_info *si ) { RETCODE rc; + int ret = SQL_SUCCESS; Debug( LDAP_DEBUG_TRACE, "==>backsql_init_db_env()\n", 0, 0, 0 ); rc = SQLAllocEnv( &si->db_env ); @@ -278,9 +280,10 @@ backsql_init_db_env( backsql_info *si ) 0, 0, 0 ); backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, SQL_NULL_HENV, rc ); + ret = SQL_ERROR; } - Debug( LDAP_DEBUG_TRACE, "<==backsql_init_db_env()\n", 0, 0, 0 ); - return SQL_SUCCESS; + Debug( LDAP_DEBUG_TRACE, "<==backsql_init_db_env()=%d\n", ret, 0, 0 ); + return ret; } int @@ -303,7 +306,7 @@ backsql_free_db_env( backsql_info *si ) } static int -backsql_open_db_conn( backsql_info *si, int ldap_cid, backsql_db_conn **pdbc ) +backsql_open_db_conn( backsql_info *si, unsigned long ldap_cid, backsql_db_conn **pdbc ) { /* TimesTen */ char DBMSName[ 32 ]; @@ -325,8 +328,10 @@ backsql_open_db_conn( backsql_info *si, int ldap_cid, backsql_db_conn **pdbc ) return LDAP_UNAVAILABLE; } - rc = SQLConnect( dbc->dbh, si->dbname, SQL_NTS, si->dbuser, - SQL_NTS, si->dbpasswd, SQL_NTS ); + rc = SQLConnect( dbc->dbh, + (SQLCHAR*)si->dbname, SQL_NTS, + (SQLCHAR*)si->dbuser, SQL_NTS, + (SQLCHAR*)si->dbpasswd, SQL_NTS ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn: " "SQLConnect() to database \"%s\" as user \"%s\" " @@ -389,7 +394,8 @@ int backsql_free_db_conn( Operation *op ) { backsql_info *si = (backsql_info *)op->o_bd->be_private; - backsql_db_conn tmp, *conn; + backsql_db_conn tmp = { 0 }, + *conn; Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 ); tmp.ldap_cid = op->o_connid; @@ -414,8 +420,8 @@ int backsql_get_db_conn( Operation *op, SQLHDBC *dbh ) { backsql_info *si = (backsql_info *)op->o_bd->be_private; - backsql_db_conn *dbc; - backsql_db_conn tmp; + backsql_db_conn *dbc, + tmp = { 0 }; int rc = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 ); diff --git a/servers/slapd/back-sql/util.c b/servers/slapd/back-sql/util.c index 1bb975f434..16084ef4ef 100644 --- a/servers/slapd/back-sql/util.c +++ b/servers/slapd/back-sql/util.c @@ -52,6 +52,10 @@ char backsql_def_delentry_query[] = "DELETE FROM ldap_entries WHERE id=?"; char backsql_def_insentry_query[] = "INSERT INTO ldap_entries (dn,oc_map_id,parent,keyval) " "VALUES (?,?,?,?)"; +char backsql_def_delobjclasses_query[] = "DELETE FROM ldap_entry_objclasses " + "WHERE entry_id=?"; +char backsql_def_delreferrals_query[] = "DELETE FROM ldap_referrals " + "WHERE entry_id=?"; char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)"; char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)"; char backsql_id_query[] = "SELECT id,keyval,oc_map_id FROM ldap_entries WHERE "; @@ -59,7 +63,7 @@ char backsql_id_query[] = "SELECT id,keyval,oc_map_id FROM ldap_entries WHERE "; char backsql_def_concat_func[] = "CONCAT(?,?)"; /* TimesTen */ -char backsql_check_dn_ru_query[] = "SELECT dn_ru from ldap_entries"; +char backsql_check_dn_ru_query[] = "SELECT dn_ru FROM ldap_entries"; struct berbuf * backsql_strcat( struct berbuf *dest, ... ) @@ -110,7 +114,8 @@ backsql_strcat( struct berbuf *dest, ... ) #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_strcat(): " - "new buflen=%d, dest=%p\n", dest->bb_len, dest, 0 ); + "new buflen=%d, dest=%p\n", + dest->bb_len, dest, 0 ); #endif /* BACKSQL_TRACE */ } AC_MEMCPY( dest->bb_val.bv_val + cdlen, cstr, cslen + 1 ); @@ -120,7 +125,7 @@ backsql_strcat( struct berbuf *dest, ... ) #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "<==backsql_strcat() (dest=\"%s\")\n", - dest, 0, 0 ); + dest->bb_val.bv_val, 0, 0 ); #endif /* BACKSQL_TRACE */ dest->bb_val.bv_len = cdlen; @@ -172,7 +177,7 @@ backsql_strfcat( struct berbuf *dest, const char *fmt, ... ) cslen = va_arg( strs, ber_len_t ); cstr = va_arg( strs, char * ); break; - + /* string */ case 's': cstr = va_arg( strs, char * ); @@ -231,7 +236,7 @@ backsql_strfcat( struct berbuf *dest, const char *fmt, ... ) #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "<==backsql_strfcat() (dest=\"%s\")\n", - dest, 0, 0 ); + dest->bb_val.bv_val, 0, 0 ); #endif /* BACKSQL_TRACE */ dest->bb_val.bv_len = cdlen; @@ -313,18 +318,18 @@ backsql_get_table_spec( char **p ) s = q; BACKSQL_NEXT_WORD; - if ( !strcasecmp( s, "as" ) ) { + if ( strcasecmp( s, "AS" ) == 0 ) { s = q; BACKSQL_NEXT_WORD; } -#if 0 - backsql_strcat( &res, " AS ", s, NULL ); - /* oracle doesn't understand AS :( and other RDBMSes don't need it */ -#endif - - /* table alias */ - backsql_strfcat( &res, "cs", ' ', s ); + /* oracle doesn't understand "AS" :( and other RDBMSes don't need it */ +#ifdef BACKSQL_ALIASING_QUOTE + backsql_strfcat( &res, "scsc", " " BACKSQL_ALIASING, + BACKSQL_ALIASING_QUOTE, s, BACKSQL_ALIASING_QUOTE ); +#else /* ! BACKSQL_ALIASING */ + backsql_strcat( &res, " " BACKSQL_ALIASING, s, NULL ); +#endif /* ! BACKSQL_ALIASING */ return res.bb_val.bv_val; } @@ -340,7 +345,8 @@ backsql_merge_from_clause( #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "==>backsql_merge_from_clause(): " "dest_from=\"%s\",src_from=\"%s\"\n", - dest_from ? dest_from->bb_val.bv_val : "", src_from, 0 ); + dest_from ? dest_from->bb_val.bv_val : "", + src_from->bv_val, 0 ); #endif /* BACKSQL_TRACE */ srcc = ch_strdup( src_from->bv_val );