2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2005 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by Dmitry Kovalev for inclusion
19 * by OpenLDAP Software. Additional significant contributors include
20 * Pierangelo Masarati.
26 #include <sys/types.h>
27 #include "ac/string.h"
30 #include "proto-sql.h"
32 typedef struct backsql_delete_attr_t {
36 backsql_entryID *e_id;
37 } backsql_delete_attr_t;
40 backsql_delete_attr_f( void *v_at, void *v_bda )
42 backsql_at_map_rec *at = (backsql_at_map_rec *)v_at;
43 backsql_delete_attr_t *bda = (backsql_delete_attr_t *)v_bda;
46 rc = backsql_modify_delete_all_values( bda->op,
47 bda->rs, bda->dbh, bda->e_id, at );
49 if ( rc != LDAP_SUCCESS ) {
50 return BACKSQL_AVL_STOP;
53 return BACKSQL_AVL_CONTINUE;
57 backsql_delete_all_attrs(
61 backsql_entryID *e_id,
62 backsql_oc_map_rec *oc )
64 backsql_delete_attr_t bda;
72 rc = avl_apply( oc->bom_attrs, backsql_delete_attr_f, &bda,
73 BACKSQL_AVL_STOP, AVL_INORDER );
74 if ( rc == BACKSQL_AVL_STOP ) {
82 backsql_delete( Operation *op, SlapReply *rs )
84 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
85 SQLHDBC dbh = SQL_NULL_HDBC;
86 SQLHSTMT sth = SQL_NULL_HSTMT;
88 int prc = LDAP_SUCCESS;
89 backsql_oc_map_rec *oc = NULL;
90 backsql_entryID e_id = BACKSQL_ENTRYID_INIT;
92 /* first parameter no */
94 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
96 Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n",
97 op->o_req_ndn.bv_val, 0, 0 );
99 dnParent( &op->o_req_dn, &e.e_name );
100 dnParent( &op->o_req_ndn, &e.e_nname );
103 /* check parent for "children" acl */
104 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
105 NULL, ACL_WRITE, NULL ) ) {
106 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
107 "no write access to parent\n",
109 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
114 rs->sr_err = backsql_get_db_conn( op, &dbh );
115 if ( rs->sr_err != LDAP_SUCCESS ) {
116 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
117 "could not get connection handle - exiting\n",
119 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
120 ? "SQL-backend error" : NULL;
124 rs->sr_err = backsql_dn2id( op, rs, &e_id, dbh, &op->o_req_ndn, 1 );
125 if ( rs->sr_err != LDAP_SUCCESS ) {
126 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
127 "could not lookup entry id\n", 0, 0, 0 );
131 rs->sr_err = backsql_has_children( bi, dbh, &op->o_req_ndn );
132 switch ( rs->sr_err ) {
133 case LDAP_COMPARE_FALSE:
134 rs->sr_err = LDAP_SUCCESS;
137 case LDAP_COMPARE_TRUE:
138 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
139 "entry \"%s\" has children\n",
140 op->o_req_dn.bv_val, 0, 0 );
141 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
142 rs->sr_text = "subtree delete not supported";
149 oc = backsql_id2oc( bi, e_id.eid_oc_id );
151 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
152 "cannot determine objectclass of entry -- aborting\n",
154 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
155 rs->sr_text = "operation not permitted within namingContext";
159 if ( oc->bom_delete_proc == NULL ) {
160 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
161 "delete procedure is not defined "
162 "for this objectclass - aborting\n", 0, 0, 0 );
163 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
164 rs->sr_text = "operation not permitted within namingContext";
169 rs->sr_err = backsql_delete_all_attrs( op, rs, dbh, &e_id, oc );
170 if ( rs->sr_err != LDAP_SUCCESS ) {
174 rc = backsql_Prepare( dbh, &sth, oc->bom_delete_proc, 0 );
175 if ( rc != SQL_SUCCESS ) {
176 Debug( LDAP_DEBUG_TRACE,
177 " backsql_delete(): "
178 "error preparing delete query\n",
180 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
182 rs->sr_err = LDAP_OTHER;
183 rs->sr_text = "SQL-backend error";
187 if ( BACKSQL_IS_DEL( oc->bom_expect_return ) ) {
189 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
190 if ( rc != SQL_SUCCESS ) {
191 Debug( LDAP_DEBUG_TRACE,
192 " backsql_delete(): "
193 "error binding output parameter for objectClass %s\n",
194 oc->bom_oc->soc_cname.bv_val, 0, 0 );
195 backsql_PrintErrors( bi->sql_db_env, dbh,
197 SQLFreeStmt( sth, SQL_DROP );
199 rs->sr_text = "SQL-backend error";
200 rs->sr_err = LDAP_OTHER;
208 rc = backsql_BindParamID( sth, pno + 1, SQL_PARAM_INPUT, &e_id.eid_keyval );
209 if ( rc != SQL_SUCCESS ) {
210 Debug( LDAP_DEBUG_TRACE,
211 " backsql_delete(): "
212 "error binding keyval parameter for objectClass %s\n",
213 oc->bom_oc->soc_cname.bv_val, 0, 0 );
214 backsql_PrintErrors( bi->sql_db_env, dbh,
216 SQLFreeStmt( sth, SQL_DROP );
218 rs->sr_text = "SQL-backend error";
219 rs->sr_err = LDAP_OTHER;
223 rc = SQLExecute( sth );
224 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
225 rs->sr_err = LDAP_SUCCESS;
228 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
229 "delete_proc execution failed (rc=%d, prc=%d)\n",
233 if ( prc != LDAP_SUCCESS ) {
234 /* SQL procedure executed fine
235 * but returned an error */
236 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
239 backsql_PrintErrors( bi->sql_db_env, dbh,
241 rs->sr_err = LDAP_OTHER;
243 SQLFreeStmt( sth, SQL_DROP );
246 SQLFreeStmt( sth, SQL_DROP );
248 /* delete "auxiliary" objectClasses, if any... */
249 rc = backsql_Prepare( dbh, &sth, bi->sql_delobjclasses_stmt, 0 );
250 if ( rc != SQL_SUCCESS ) {
251 Debug( LDAP_DEBUG_TRACE,
252 " backsql_delete(): "
253 "error preparing ldap_entry_objclasses delete query\n",
255 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
257 rs->sr_err = LDAP_OTHER;
258 rs->sr_text = "SQL-backend error";
262 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
263 if ( rc != SQL_SUCCESS ) {
264 Debug( LDAP_DEBUG_TRACE,
265 " backsql_delete(): "
266 "error binding auxiliary objectClasses "
267 "entry ID parameter for objectClass %s\n",
268 oc->bom_oc->soc_cname.bv_val, 0, 0 );
269 backsql_PrintErrors( bi->sql_db_env, dbh,
271 SQLFreeStmt( sth, SQL_DROP );
273 rs->sr_text = "SQL-backend error";
274 rs->sr_err = LDAP_OTHER;
278 rc = SQLExecute( sth );
281 /* apparently there were no "auxiliary" objectClasses
282 * for this entry... */
287 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
288 "failed to delete record from ldap_entry_objclasses\n",
290 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
291 SQLFreeStmt( sth, SQL_DROP );
292 rs->sr_err = LDAP_OTHER;
293 rs->sr_text = "SQL-backend error";
296 SQLFreeStmt( sth, SQL_DROP );
298 /* delete referrals, if any... */
299 rc = backsql_Prepare( dbh, &sth, bi->sql_delreferrals_stmt, 0 );
300 if ( rc != SQL_SUCCESS ) {
301 Debug( LDAP_DEBUG_TRACE,
302 " backsql_delete(): "
303 "error preparing ldap_referrals delete query\n",
305 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
307 rs->sr_err = LDAP_OTHER;
308 rs->sr_text = "SQL-backend error";
312 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
313 if ( rc != SQL_SUCCESS ) {
314 Debug( LDAP_DEBUG_TRACE,
315 " backsql_delete(): "
316 "error binding referrals entry ID parameter "
317 "for objectClass %s\n",
318 oc->bom_oc->soc_cname.bv_val, 0, 0 );
319 backsql_PrintErrors( bi->sql_db_env, dbh,
321 SQLFreeStmt( sth, SQL_DROP );
323 rs->sr_text = "SQL-backend error";
324 rs->sr_err = LDAP_OTHER;
328 rc = SQLExecute( sth );
331 /* apparently there were no referrals
332 * for this entry... */
337 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
338 "failed to delete record from ldap_referrals\n",
340 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
341 SQLFreeStmt( sth, SQL_DROP );
342 rs->sr_err = LDAP_OTHER;
343 rs->sr_text = "SQL-backend error";
346 SQLFreeStmt( sth, SQL_DROP );
348 /* delete entry... */
349 rc = backsql_Prepare( dbh, &sth, bi->sql_delentry_stmt, 0 );
350 if ( rc != SQL_SUCCESS ) {
351 Debug( LDAP_DEBUG_TRACE,
352 " backsql_delete(): "
353 "error preparing ldap_entries delete query\n",
355 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
357 rs->sr_err = LDAP_OTHER;
358 rs->sr_text = "SQL-backend error";
362 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &e_id.eid_id );
363 if ( rc != SQL_SUCCESS ) {
364 Debug( LDAP_DEBUG_TRACE,
365 " backsql_delete(): "
366 "error binding entry ID parameter "
367 "for objectClass %s\n",
368 oc->bom_oc->soc_cname.bv_val, 0, 0 );
369 backsql_PrintErrors( bi->sql_db_env, dbh,
371 SQLFreeStmt( sth, SQL_DROP );
373 rs->sr_text = "SQL-backend error";
374 rs->sr_err = LDAP_OTHER;
378 rc = SQLExecute( sth );
379 if ( rc != SQL_SUCCESS ) {
380 Debug( LDAP_DEBUG_TRACE, " backsql_delete(): "
381 "failed to delete record from ldap_entries\n",
383 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
384 SQLFreeStmt( sth, SQL_DROP );
385 rs->sr_err = LDAP_OTHER;
386 rs->sr_text = "SQL-backend error";
389 SQLFreeStmt( sth, SQL_DROP );
391 rs->sr_err = LDAP_SUCCESS;
396 * Commit only if all operations succeed
398 * FIXME: backsql_add() does not fail if add operations
399 * are not available for some attributes, or if
400 * a multiple value add actually results in a replace,
401 * or if a single operation on an attribute fails
404 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
405 CompletionType = SQL_COMMIT;
407 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
409 send_ldap_result( op, rs );
411 Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
413 return ( ( rs->sr_err == LDAP_SUCCESS ) ? op->o_noop : 1 );