Back to index

openldap  2.4.31
delete.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 1999 Dmitry Kovalev.
00006  * Portions Copyright 2002 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Dmitry Kovalev for inclusion
00019  * by OpenLDAP Software.  Additional significant contributors include
00020  * Pierangelo Masarati.
00021  */
00022 
00023 #include "portable.h"
00024 
00025 #include <stdio.h>
00026 #include <sys/types.h>
00027 #include "ac/string.h"
00028 
00029 #include "slap.h"
00030 #include "proto-sql.h"
00031 
00032 typedef struct backsql_delete_attr_t {
00033        Operation            *op;
00034        SlapReply            *rs;
00035        SQLHDBC                     dbh; 
00036        backsql_entryID             *e_id;
00037 } backsql_delete_attr_t;
00038 
00039 static int
00040 backsql_delete_attr_f( void *v_at, void *v_bda )
00041 {
00042        backsql_at_map_rec   *at = (backsql_at_map_rec *)v_at;
00043        backsql_delete_attr_t       *bda = (backsql_delete_attr_t *)v_bda;
00044        int                  rc;
00045 
00046        rc = backsql_modify_delete_all_values( bda->op,
00047                      bda->rs, bda->dbh, bda->e_id, at );
00048 
00049        if ( rc != LDAP_SUCCESS ) {
00050               return BACKSQL_AVL_STOP;
00051        }
00052 
00053        return BACKSQL_AVL_CONTINUE;
00054 }
00055 
00056 static int
00057 backsql_delete_all_attrs(
00058        Operation            *op,
00059        SlapReply            *rs,
00060        SQLHDBC                     dbh, 
00061        backsql_entryID             *eid )
00062 {
00063        backsql_delete_attr_t       bda;
00064        int                  rc;
00065 
00066        bda.op = op;
00067        bda.rs = rs;
00068        bda.dbh = dbh;
00069        bda.e_id = eid;
00070        
00071        rc = avl_apply( eid->eid_oc->bom_attrs, backsql_delete_attr_f, &bda,
00072                      BACKSQL_AVL_STOP, AVL_INORDER );
00073        if ( rc == BACKSQL_AVL_STOP ) {
00074               return rs->sr_err;
00075        }
00076 
00077        return LDAP_SUCCESS;
00078 }
00079 
00080 static int
00081 backsql_delete_int(
00082        Operation     *op,
00083        SlapReply     *rs,
00084        SQLHDBC              dbh,
00085        SQLHSTMT      *sthp,
00086        backsql_entryID      *eid,
00087        Entry         **ep )
00088 {
00089        backsql_info         *bi = (backsql_info*)op->o_bd->be_private;
00090        SQLHSTMT             sth = SQL_NULL_HSTMT;
00091        RETCODE                     rc;
00092        int                  prc = LDAP_SUCCESS;
00093        /* first parameter no */
00094        SQLUSMALLINT         pno = 0;
00095 
00096        sth = *sthp;
00097 
00098        /* avl_apply ... */
00099        rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, eid );
00100        if ( rs->sr_err != LDAP_SUCCESS ) {
00101               goto done;
00102        }
00103 
00104        rc = backsql_Prepare( dbh, &sth, eid->eid_oc->bom_delete_proc, 0 );
00105        if ( rc != SQL_SUCCESS ) {
00106               Debug( LDAP_DEBUG_TRACE,
00107                      "   backsql_delete(): "
00108                      "error preparing delete query\n", 
00109                      0, 0, 0 );
00110               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00111 
00112               rs->sr_err = LDAP_OTHER;
00113               rs->sr_text = "SQL-backend error";
00114               *ep = NULL;
00115               goto done;
00116        }
00117 
00118        if ( BACKSQL_IS_DEL( eid->eid_oc->bom_expect_return ) ) {
00119               pno = 1;
00120               rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
00121               if ( rc != SQL_SUCCESS ) {
00122                      Debug( LDAP_DEBUG_TRACE,
00123                             "   backsql_delete(): "
00124                             "error binding output parameter for objectClass %s\n",
00125                             eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
00126                      backsql_PrintErrors( bi->sql_db_env, dbh, 
00127                             sth, rc );
00128                      SQLFreeStmt( sth, SQL_DROP );
00129 
00130                      rs->sr_text = "SQL-backend error";
00131                      rs->sr_err = LDAP_OTHER;
00132                      *ep = NULL;
00133                      goto done;
00134               }
00135        }
00136 
00137        rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &eid->eid_keyval );
00138        if ( rc != SQL_SUCCESS ) {
00139               Debug( LDAP_DEBUG_TRACE,
00140                      "   backsql_delete(): "
00141                      "error binding keyval parameter for objectClass %s\n",
00142                      eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
00143               backsql_PrintErrors( bi->sql_db_env, dbh, 
00144                      sth, rc );
00145               SQLFreeStmt( sth, SQL_DROP );
00146 
00147               rs->sr_text = "SQL-backend error";
00148               rs->sr_err = LDAP_OTHER;
00149               *ep = NULL;
00150               goto done;
00151        }
00152 
00153        rc = SQLExecute( sth );
00154        if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
00155               rs->sr_err = LDAP_SUCCESS;
00156 
00157        } else {
00158               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00159                      "delete_proc execution failed (rc=%d, prc=%d)\n",
00160                      rc, prc, 0 );
00161 
00162 
00163               if ( prc != LDAP_SUCCESS ) {
00164                      /* SQL procedure executed fine 
00165                       * but returned an error */
00166                      rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
00167 
00168               } else {
00169                      backsql_PrintErrors( bi->sql_db_env, dbh,
00170                                    sth, rc );
00171                      rs->sr_err = LDAP_OTHER;
00172               }
00173               SQLFreeStmt( sth, SQL_DROP );
00174               goto done;
00175        }
00176        SQLFreeStmt( sth, SQL_DROP );
00177 
00178        /* delete "auxiliary" objectClasses, if any... */
00179        rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_stmt, 0 );
00180        if ( rc != SQL_SUCCESS ) {
00181               Debug( LDAP_DEBUG_TRACE,
00182                      "   backsql_delete(): "
00183                      "error preparing ldap_entry_objclasses delete query\n", 
00184                      0, 0, 0 );
00185               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00186 
00187               rs->sr_err = LDAP_OTHER;
00188               rs->sr_text = "SQL-backend error";
00189               *ep = NULL;
00190               goto done;
00191        }
00192 
00193        rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
00194        if ( rc != SQL_SUCCESS ) {
00195               Debug( LDAP_DEBUG_TRACE,
00196                      "   backsql_delete(): "
00197                      "error binding auxiliary objectClasses "
00198                      "entry ID parameter for objectClass %s\n",
00199                      eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
00200               backsql_PrintErrors( bi->sql_db_env, dbh, 
00201                      sth, rc );
00202               SQLFreeStmt( sth, SQL_DROP );
00203 
00204               rs->sr_text = "SQL-backend error";
00205               rs->sr_err = LDAP_OTHER;
00206               *ep = NULL;
00207               goto done;
00208        }
00209 
00210        rc = SQLExecute( sth );
00211        switch ( rc ) {
00212        case SQL_NO_DATA:
00213               /* apparently there were no "auxiliary" objectClasses
00214                * for this entry... */
00215        case SQL_SUCCESS:
00216               break;
00217 
00218        default:
00219               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00220                      "failed to delete record from ldap_entry_objclasses\n", 
00221                      0, 0, 0 );
00222               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00223               SQLFreeStmt( sth, SQL_DROP );
00224               rs->sr_err = LDAP_OTHER;
00225               rs->sr_text = "SQL-backend error";
00226               *ep = NULL;
00227               goto done;
00228        }
00229        SQLFreeStmt( sth, SQL_DROP );
00230 
00231        /* delete entry... */
00232        rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
00233        if ( rc != SQL_SUCCESS ) {
00234               Debug( LDAP_DEBUG_TRACE,
00235                      "   backsql_delete(): "
00236                      "error preparing ldap_entries delete query\n", 
00237                      0, 0, 0 );
00238               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00239 
00240               rs->sr_err = LDAP_OTHER;
00241               rs->sr_text = "SQL-backend error";
00242               *ep = NULL;
00243               goto done;
00244        }
00245 
00246        rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &eid->eid_id );
00247        if ( rc != SQL_SUCCESS ) {
00248               Debug( LDAP_DEBUG_TRACE,
00249                      "   backsql_delete(): "
00250                      "error binding entry ID parameter "
00251                      "for objectClass %s\n",
00252                      eid->eid_oc->bom_oc->soc_cname.bv_val, 0, 0 );
00253               backsql_PrintErrors( bi->sql_db_env, dbh, 
00254                      sth, rc );
00255               SQLFreeStmt( sth, SQL_DROP );
00256 
00257               rs->sr_text = "SQL-backend error";
00258               rs->sr_err = LDAP_OTHER;
00259               *ep = NULL;
00260               goto done;
00261        }
00262 
00263        rc = SQLExecute( sth );
00264        if ( rc != SQL_SUCCESS ) {
00265               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00266                      "failed to delete record from ldap_entries\n", 
00267                      0, 0, 0 );
00268               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00269               SQLFreeStmt( sth, SQL_DROP );
00270               rs->sr_err = LDAP_OTHER;
00271               rs->sr_text = "SQL-backend error";
00272               *ep = NULL;
00273               goto done;
00274        }
00275        SQLFreeStmt( sth, SQL_DROP );
00276 
00277        rs->sr_err = LDAP_SUCCESS;
00278        *ep = NULL;
00279 
00280 done:;
00281        *sthp = sth;
00282 
00283        return rs->sr_err;
00284 }
00285 
00286 typedef struct backsql_tree_delete_t {
00287        Operation     *btd_op;
00288        int           btd_rc;
00289        backsql_entryID      *btd_eid;
00290 } backsql_tree_delete_t;
00291 
00292 static int
00293 backsql_tree_delete_search_cb( Operation *op, SlapReply *rs )
00294 {
00295        if ( rs->sr_type == REP_SEARCH ) {
00296               backsql_tree_delete_t       *btd;
00297               backsql_entryID             *eid;
00298 
00299               btd = (backsql_tree_delete_t *)op->o_callback->sc_private;
00300 
00301               if ( !access_allowed( btd->btd_op, rs->sr_entry,
00302                      slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL )
00303                      || !access_allowed( btd->btd_op, rs->sr_entry,
00304                      slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) )
00305               {
00306                      btd->btd_rc = LDAP_INSUFFICIENT_ACCESS;
00307                      return rs->sr_err = LDAP_UNAVAILABLE;
00308               }
00309 
00310               assert( rs->sr_entry != NULL );
00311               assert( rs->sr_entry->e_private != NULL );
00312 
00313               eid = (backsql_entryID *)rs->sr_entry->e_private;
00314               assert( eid->eid_oc != NULL );
00315               if ( eid->eid_oc == NULL || eid->eid_oc->bom_delete_proc == NULL ) {
00316                      btd->btd_rc = LDAP_UNWILLING_TO_PERFORM;
00317                      return rs->sr_err = LDAP_UNAVAILABLE;
00318               }
00319 
00320               eid = backsql_entryID_dup( eid, op->o_tmpmemctx );
00321               eid->eid_next = btd->btd_eid;
00322               btd->btd_eid = eid;
00323        }
00324 
00325        return 0;
00326 }
00327 
00328 static int
00329 backsql_tree_delete(
00330        Operation     *op,
00331        SlapReply     *rs,
00332        SQLHDBC              dbh,
00333        SQLHSTMT      *sthp )
00334 {
00335        Operation            op2 = *op;
00336        slap_callback        sc = { 0 };
00337        SlapReply            rs2 = { REP_RESULT };
00338        backsql_tree_delete_t       btd = { 0 };
00339 
00340        int                  rc;
00341 
00342        /*
00343         * - perform an internal subtree search as the rootdn
00344         * - for each entry
00345         *     - check access
00346         *     - check objectClass and delete method(s)
00347         * - for each entry
00348         *     - delete
00349         * - if successful, commit
00350         */
00351 
00352        op2.o_tag = LDAP_REQ_SEARCH;
00353        op2.o_protocol = LDAP_VERSION3;
00354 
00355        btd.btd_op = op;
00356        sc.sc_private = &btd;
00357        sc.sc_response = backsql_tree_delete_search_cb;
00358        op2.o_callback = &sc;
00359 
00360        op2.o_dn = op->o_bd->be_rootdn;
00361        op2.o_ndn = op->o_bd->be_rootndn;
00362 
00363        op2.o_managedsait = SLAP_CONTROL_CRITICAL;
00364 
00365        op2.ors_scope = LDAP_SCOPE_SUBTREE;
00366        op2.ors_deref = LDAP_DEREF_NEVER;
00367        op2.ors_slimit = SLAP_NO_LIMIT;
00368        op2.ors_tlimit = SLAP_NO_LIMIT;
00369        op2.ors_filter = (Filter *)slap_filter_objectClass_pres;
00370        op2.ors_filterstr = *slap_filterstr_objectClass_pres;
00371        op2.ors_attrs = slap_anlist_all_attributes;
00372        op2.ors_attrsonly = 0;
00373 
00374        rc = op->o_bd->be_search( &op2, &rs2 );
00375        if ( rc != LDAP_SUCCESS ) {
00376               rc = rs->sr_err = btd.btd_rc;
00377               rs->sr_text = "subtree delete not possible";
00378               send_ldap_result( op, rs );
00379               goto clean;
00380        }
00381 
00382        for ( ; btd.btd_eid != NULL;
00383               btd.btd_eid = backsql_free_entryID( btd.btd_eid,
00384                      1, op->o_tmpmemctx ) )
00385        {
00386               Entry  *e = (void *)0xbad;
00387               rc = backsql_delete_int( op, rs, dbh, sthp, btd.btd_eid, &e );
00388               if ( rc != LDAP_SUCCESS ) {
00389                      break;
00390               }
00391        }
00392 
00393 clean:;
00394        for ( ; btd.btd_eid != NULL;
00395               btd.btd_eid = backsql_free_entryID( btd.btd_eid,
00396                      1, op->o_tmpmemctx ) )
00397               ;
00398 
00399        return rc;
00400 }
00401 
00402 int
00403 backsql_delete( Operation *op, SlapReply *rs )
00404 {
00405        SQLHDBC              dbh = SQL_NULL_HDBC;
00406        SQLHSTMT             sth = SQL_NULL_HSTMT;
00407        backsql_oc_map_rec   *oc = NULL;
00408        backsql_srch_info    bsi = { 0 };
00409        backsql_entryID             e_id = { 0 };
00410        Entry                d = { 0 }, p = { 0 }, *e = NULL;
00411        struct berval        pdn = BER_BVNULL;
00412        int                  manageDSAit = get_manageDSAit( op );
00413 
00414        Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
00415                      op->o_req_ndn.bv_val, 0, 0 );
00416 
00417        rs->sr_err = backsql_get_db_conn( op, &dbh );
00418        if ( rs->sr_err != LDAP_SUCCESS ) {
00419               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00420                      "could not get connection handle - exiting\n", 
00421                      0, 0, 0 );
00422               rs->sr_text = ( rs->sr_err == LDAP_OTHER )
00423                      ? "SQL-backend error" : NULL;
00424               e = NULL;
00425               goto done;
00426        }
00427 
00428        /*
00429         * Get the entry
00430         */
00431        bsi.bsi_e = &d;
00432        rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn,
00433                      LDAP_SCOPE_BASE, 
00434                      (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
00435                      ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) );
00436        switch ( rs->sr_err ) {
00437        case LDAP_SUCCESS:
00438               break;
00439 
00440        case LDAP_REFERRAL:
00441               if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) &&
00442                             dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) )
00443               {
00444                      rs->sr_err = LDAP_SUCCESS;
00445                      rs->sr_text = NULL;
00446                      rs->sr_matched = NULL;
00447                      if ( rs->sr_ref ) {
00448                             ber_bvarray_free( rs->sr_ref );
00449                             rs->sr_ref = NULL;
00450                      }
00451                      break;
00452               }
00453               e = &d;
00454               /* fallthru */
00455 
00456        default:
00457               Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
00458                      "could not retrieve deleteDN ID - no such entry\n", 
00459                      0, 0, 0 );
00460               if ( !BER_BVISNULL( &d.e_nname ) ) {
00461                      /* FIXME: should always be true! */
00462                      e = &d;
00463 
00464               } else {
00465                      e = NULL;
00466               }
00467               goto done;
00468        }
00469 
00470        if ( get_assert( op ) &&
00471                      ( test_filter( op, &d, get_assertion( op ) )
00472                        != LDAP_COMPARE_TRUE ) )
00473        {
00474               rs->sr_err = LDAP_ASSERTION_FAILED;
00475               e = &d;
00476               goto done;
00477        }
00478 
00479        if ( !access_allowed( op, &d, slap_schema.si_ad_entry, 
00480                      NULL, ACL_WDEL, NULL ) )
00481        {
00482               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00483                      "no write access to entry\n", 
00484                      0, 0, 0 );
00485               rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00486               e = &d;
00487               goto done;
00488        }
00489 
00490        rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn );
00491        switch ( rs->sr_err ) {
00492        case LDAP_COMPARE_FALSE:
00493               rs->sr_err = LDAP_SUCCESS;
00494               break;
00495 
00496        case LDAP_COMPARE_TRUE:
00497 #ifdef SLAP_CONTROL_X_TREE_DELETE
00498               if ( get_treeDelete( op ) ) {
00499                      rs->sr_err = LDAP_SUCCESS;
00500                      break;
00501               }
00502 #endif /* SLAP_CONTROL_X_TREE_DELETE */
00503 
00504               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00505                      "entry \"%s\" has children\n",
00506                      op->o_req_dn.bv_val, 0, 0 );
00507               rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
00508               rs->sr_text = "subordinate objects must be deleted first";
00509               /* fallthru */
00510 
00511        default:
00512               e = &d;
00513               goto done;
00514        }
00515 
00516        assert( bsi.bsi_base_id.eid_oc != NULL );
00517        oc = bsi.bsi_base_id.eid_oc;
00518        if ( oc->bom_delete_proc == NULL ) {
00519               Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00520                      "delete procedure is not defined "
00521                      "for this objectclass - aborting\n", 0, 0, 0 );
00522               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
00523               rs->sr_text = "operation not permitted within namingContext";
00524               e = NULL;
00525               goto done;
00526        }
00527 
00528        /*
00529         * Get the parent
00530         */
00531        e_id = bsi.bsi_base_id;
00532        memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) );
00533        if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
00534               dnParent( &op->o_req_ndn, &pdn );
00535               bsi.bsi_e = &p;
00536               rs->sr_err = backsql_init_search( &bsi, &pdn,
00537                             LDAP_SCOPE_BASE, 
00538                             (time_t)(-1), NULL, dbh, op, rs,
00539                             slap_anlist_no_attrs,
00540                             BACKSQL_ISF_GET_ENTRY );
00541               if ( rs->sr_err != LDAP_SUCCESS ) {
00542                      Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
00543                             "could not retrieve deleteDN ID "
00544                             "- no such entry\n", 
00545                             0, 0, 0 );
00546                      e = &p;
00547                      goto done;
00548               }
00549 
00550               (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
00551 
00552               /* check parent for "children" acl */
00553               if ( !access_allowed( op, &p, slap_schema.si_ad_children, 
00554                             NULL, ACL_WDEL, NULL ) )
00555               {
00556                      Debug( LDAP_DEBUG_TRACE, "   backsql_delete(): "
00557                             "no write access to parent\n", 
00558                             0, 0, 0 );
00559                      rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00560                      e = &p;
00561                      goto done;
00562 
00563               }
00564        }
00565 
00566        e = &d;
00567 #ifdef SLAP_CONTROL_X_TREE_DELETE
00568        if ( get_treeDelete( op ) ) {
00569               backsql_tree_delete( op, rs, dbh, &sth );
00570               if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS )
00571               {
00572                      e = NULL;
00573               }
00574 
00575        } else
00576 #endif /* SLAP_CONTROL_X_TREE_DELETE */
00577        {
00578               backsql_delete_int( op, rs, dbh, &sth, &e_id, &e );
00579        }
00580 
00581        /*
00582         * Commit only if all operations succeed
00583         */
00584        if ( sth != SQL_NULL_HSTMT ) {
00585               SQLUSMALLINT  CompletionType = SQL_ROLLBACK;
00586        
00587               if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
00588                      assert( e == NULL );
00589                      CompletionType = SQL_COMMIT;
00590               }
00591 
00592               SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
00593        }
00594 
00595 done:;
00596        if ( e != NULL ) {
00597               if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL,
00598                                    ACL_DISCLOSE, NULL ) )
00599               {
00600                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00601                      rs->sr_text = NULL;
00602                      rs->sr_matched = NULL;
00603                      if ( rs->sr_ref ) {
00604                             ber_bvarray_free( rs->sr_ref );
00605                             rs->sr_ref = NULL;
00606                      }
00607               }
00608        }
00609 
00610        if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
00611               rs->sr_err = LDAP_X_NO_OPERATION;
00612        }
00613 
00614        send_ldap_result( op, rs );
00615 
00616        Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
00617 
00618        if ( !BER_BVISNULL( &e_id.eid_ndn ) ) {
00619               (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx );
00620        }
00621 
00622        if ( !BER_BVISNULL( &d.e_nname ) ) {
00623               backsql_entry_clean( op, &d );
00624        }
00625 
00626        if ( !BER_BVISNULL( &p.e_nname ) ) {
00627               backsql_entry_clean( op, &p );
00628        }
00629 
00630        if ( rs->sr_ref ) {
00631               ber_bvarray_free( rs->sr_ref );
00632               rs->sr_ref = NULL;
00633        }
00634 
00635        return rs->sr_err;
00636 }
00637