2 * Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
4 * Redistribution and use in source and binary forms are permitted only
5 * as authorized by the OpenLDAP Public License. A copy of this
6 * license is available at http://www.OpenLDAP.org/license.html or
7 * in file LICENSE in the top-level directory of the distribution.
15 #include <sys/types.h>
16 #include "ac/string.h"
21 #include "schema-map.h"
26 * PostgreSQL 7.0 doesn't work without :(
28 #define BACKSQL_REALLOC_STMT
32 * - the first occurrence of objectClass, which is used
33 * to determine how to bulid the SQL entry (FIXME ?!?)
34 * - operational attributes
35 * empty attributes (FIXME ?!?)
37 #define backsql_attr_skip(ad,vals) \
39 ( (ad) == slap_schema.si_ad_objectClass \
40 && (vals)[ 1 ].bv_val == NULL ) \
41 || is_at_operational( (ad)->ad_type ) \
42 || ( (vals)[ 0 ].bv_val == NULL ) \
46 backsql_modify_internal(
51 backsql_oc_map_rec *oc,
52 backsql_entryID *e_id,
53 Modifications *modlist,
56 backsql_info *bi = (backsql_info*)be->be_private;
60 int res = LDAP_SUCCESS;
62 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
63 "traversing modifications list\n", 0, 0, 0 );
67 #ifndef BACKSQL_REALLOC_STMT
68 SQLAllocStmt( dbh, &sth );
69 #endif /* BACKSQL_REALLOC_STMT */
71 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
72 AttributeDescription *ad;
73 backsql_at_map_rec *at = NULL;
74 struct berval *at_val;
77 /* first parameter no, parameter order */
79 /* procedure return code */
82 #ifdef BACKSQL_REALLOC_STMT
83 SQLAllocStmt( dbh, &sth );
84 #endif /* BACKSQL_REALLOC_STMT */
89 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
90 "modifying attribute '%s'\n",
91 ad->ad_cname.bv_val, 0, 0 );
93 if ( backsql_attr_skip( ad, c_mod->sm_bvalues ) ) {
97 at = backsql_ad2at( oc, ad );
99 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
100 "attribute provided is not registered "
101 "in objectClass '%s'\n",
102 ad->ad_cname.bv_val, 0, 0 );
104 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
105 res = LDAP_UNWILLING_TO_PERFORM;
106 *text = "operation not permitted "
107 "within namingContext";
114 switch( c_mod->sm_op ) {
115 case LDAP_MOD_REPLACE: {
119 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
120 "replacing values for attribute '%s'\n",
121 at->ad->ad_cname.bv_val, 0, 0 );
123 if ( at->add_proc == NULL ) {
124 Debug( LDAP_DEBUG_TRACE,
125 "backsql_modify_internal(): "
126 "add procedure is not defined "
127 "for attribute '%s' "
128 "- unable to perform replacements\n",
129 at->ad->ad_cname.bv_val, 0, 0 );
131 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
132 res = LDAP_UNWILLING_TO_PERFORM;
133 *text = "operation not permitted "
134 "within namingContext";
141 if ( at->delete_proc == NULL ) {
142 Debug( LDAP_DEBUG_TRACE,
143 "backsql_modify_internal(): "
144 "delete procedure is not defined "
145 "for attribute '%s' "
147 at->ad->ad_cname.bv_val, 0, 0 );
149 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
150 res = LDAP_UNWILLING_TO_PERFORM;
151 *text = "operation not permitted "
152 "within namingContext";
160 rc = backsql_Prepare( dbh, &asth, at->query, 0 );
161 if ( rc != SQL_SUCCESS ) {
162 Debug( LDAP_DEBUG_TRACE,
163 "backsql_modify_internal(): "
164 "error preparing query\n", 0, 0, 0 );
165 backsql_PrintErrors( bi->db_env, dbh,
168 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
170 *text = "SQL-backend error";
177 rc = backsql_BindParamID( asth, 1, &e_id->keyval );
178 if ( rc != SQL_SUCCESS ) {
179 Debug( LDAP_DEBUG_TRACE,
180 "backsql_modify_internal(): "
181 "error binding key value parameter\n",
183 backsql_PrintErrors( bi->db_env, dbh,
185 SQLFreeStmt( asth, SQL_DROP );
187 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
189 *text = "SQL-backend error";
196 rc = SQLExecute( asth );
197 if ( !BACKSQL_SUCCESS( rc ) ) {
198 Debug( LDAP_DEBUG_TRACE,
199 "backsql_modify_internal(): "
200 "error executing attribute query\n",
202 backsql_PrintErrors( bi->db_env, dbh,
204 SQLFreeStmt( asth, SQL_DROP );
206 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
208 *text = "SQL-backend error";
215 backsql_BindRowAsStrings( asth, &row );
216 rc = SQLFetch( asth );
217 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
218 for ( i = 0; i < row.ncols; i++ ) {
219 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
221 SQLBindParameter(sth, 1,
229 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
230 SQLBindParameter( sth, pno + 1 + po,
232 SQL_C_ULONG, SQL_INTEGER,
233 0, 0, &e_id->keyval, 0, 0 );
236 * check for syntax needed here
237 * maybe need binary bind?
239 SQLBindParameter(sth, pno + 2 - po,
241 SQL_C_CHAR, SQL_CHAR,
243 strlen( row.cols[ i ] ), 0 );
245 Debug( LDAP_DEBUG_TRACE,
246 "backsql_modify_internal(): "
248 at->delete_proc, 0, 0 );
249 rc = SQLExecDirect( sth,
250 at->delete_proc, SQL_NTS );
251 if ( rc != SQL_SUCCESS ) {
252 Debug( LDAP_DEBUG_TRACE,
253 "backsql_modify_internal(): "
255 "execution failed\n",
257 backsql_PrintErrors( bi->db_env,
260 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
262 *text = "SQL-backend error";
266 #ifdef BACKSQL_REALLOC_STMT
267 SQLFreeStmt( sth, SQL_DROP );
268 SQLAllocStmt( dbh, &sth );
269 #endif /* BACKSQL_REALLOC_STMT */
272 backsql_FreeRow( &row );
273 SQLFreeStmt( asth, SQL_DROP );
277 * PASSTHROUGH - to add new attributes -- do NOT add break
280 case SLAP_MOD_SOFTADD:
282 if ( at->add_proc == NULL ) {
283 Debug( LDAP_DEBUG_TRACE,
284 "backsql_modify_internal(): "
285 "add procedure is not defined "
286 "for attribute '%s'\n",
287 at->ad->ad_cname.bv_val, 0, 0 );
289 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
290 res = LDAP_UNWILLING_TO_PERFORM;
291 *text = "operation not permitted "
292 "within namingContext";
299 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
300 "adding new values for attribute '%s'\n",
301 at->ad->ad_cname.bv_val, 0, 0 );
302 for ( i = 0, at_val = c_mod->sm_bvalues;
303 at_val->bv_val != NULL;
305 if ( BACKSQL_IS_ADD( at->expect_return ) ) {
307 SQLBindParameter( sth, 1,
309 SQL_C_ULONG, SQL_INTEGER,
314 po = ( BACKSQL_IS_ADD( at->param_order ) ) > 0;
315 SQLBindParameter( sth, pno + 1 + po,
317 SQL_C_ULONG, SQL_INTEGER,
318 0, 0, &e_id->keyval, 0, 0 );
321 * check for syntax needed here
322 * maybe need binary bind?
324 SQLBindParameter( sth, pno + 2 - po,
326 SQL_C_CHAR, SQL_CHAR,
327 0, 0, at_val->bv_val,
330 Debug( LDAP_DEBUG_TRACE,
331 "backsql_modify_internal(): "
333 at->add_proc, 0, 0 );
334 rc = SQLExecDirect( sth, at->add_proc,
336 if ( rc != SQL_SUCCESS ) {
337 Debug( LDAP_DEBUG_TRACE,
338 "backsql_modify_internal(): "
339 "add_proc execution failed\n",
341 backsql_PrintErrors( bi->db_env,
344 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
346 *text = "SQL-backend error";
350 #ifdef BACKSQL_REALLOC_STMT
351 SQLFreeStmt( sth, SQL_DROP );
352 SQLAllocStmt( dbh, &sth );
353 #endif /* BACKSQL_REALLOC_STMT */
357 case LDAP_MOD_DELETE:
358 if ( at->delete_proc == NULL ) {
359 Debug( LDAP_DEBUG_TRACE,
360 "backsql_modify_internal(): "
361 "delete procedure is not defined "
362 "for attribute '%s'\n",
363 at->ad->ad_cname.bv_val, 0, 0 );
365 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
366 res = LDAP_UNWILLING_TO_PERFORM;
367 *text = "operation not permitted "
368 "within namingContext";
375 if ( c_mod->sm_bvalues == NULL ) {
376 Debug( LDAP_DEBUG_TRACE,
377 "backsql_modify_internal(): "
378 "no values given to delete "
379 "for attribute '%s' "
380 "-- deleting all values\n",
381 at->ad->ad_cname.bv_val, 0, 0 );
385 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
386 "deleting values for attribute '%s'\n",
387 at->ad->ad_cname.bv_val, 0, 0 );
389 for ( i = 0, at_val = c_mod->sm_bvalues;
390 at_val->bv_val != NULL;
392 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
394 SQLBindParameter( sth, 1,
396 SQL_C_ULONG, SQL_INTEGER,
401 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
402 SQLBindParameter( sth, pno + 1 + po,
404 SQL_C_ULONG, SQL_INTEGER,
405 0, 0, &e_id->keyval, 0, 0 );
408 * check for syntax needed here
409 * maybe need binary bind?
411 SQLBindParameter( sth, pno + 2 - po,
412 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
413 0, 0, at_val->bv_val,
416 Debug( LDAP_DEBUG_TRACE,
417 "backsql_modify_internal(): "
419 at->delete_proc, 0, 0 );
420 rc = SQLExecDirect( sth, at->delete_proc,
422 if ( rc != SQL_SUCCESS ) {
423 Debug( LDAP_DEBUG_TRACE,
424 "backsql_modify_internal(): "
425 "delete_proc execution "
426 "failed\n", 0, 0, 0 );
427 backsql_PrintErrors( bi->db_env,
430 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
432 *text = "SQL-backend error";
436 #ifdef BACKSQL_REALLOC_STMT
437 SQLFreeStmt( sth, SQL_DROP );
438 SQLAllocStmt( dbh, &sth );
439 #endif /* BACKSQL_REALLOC_STMT */
443 #ifndef BACKSQL_REALLOC_STMT
444 SQLFreeStmt( sth, SQL_RESET_PARAMS );
445 #else /* BACKSQL_REALLOC_STMT */
446 SQLFreeStmt( sth, SQL_DROP );
447 #endif /* BACKSQL_REALLOC_STMT */
452 #ifndef BACKSQL_REALLOC_STMT
453 SQLFreeStmt( sth, SQL_DROP );
454 #endif /* BACKSQL_REALLOC_STMT */
457 * FIXME: should fail in case one change fails?
469 Modifications *modlist )
471 backsql_info *bi = (backsql_info*)be->be_private;
473 backsql_oc_map_rec *oc = NULL;
474 backsql_entryID e_id;
477 const char *text = NULL;
480 * FIXME: in case part of the operation cannot be performed
481 * (missing mapping, SQL write fails or so) the entire operation
482 * should be rolled-back
485 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
487 res = backsql_get_db_conn( be, conn, &dbh );
488 if ( res != LDAP_SUCCESS ) {
489 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
490 "could not get connection handle - exiting\n",
493 * FIXME: we don't want to send back
494 * excessively detailed messages
496 send_ldap_result( conn, op, res, NULL,
497 res == LDAP_OTHER ? "SQL-backend error" : "",
502 res = backsql_dn2id( bi, &e_id, dbh, ndn );
503 if ( res != LDAP_SUCCESS ) {
504 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
505 "could not lookup entry id\n", 0, 0, 0 );
506 send_ldap_result( conn, op, res , NULL,
507 res == LDAP_OTHER ? "SQL-backend error" : "",
512 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
513 "modifying entry '%s' (id=%ld)\n",
514 e_id.dn.bv_val, e_id.id, 0 );
516 oc = backsql_id2oc( bi, e_id.oc_id );
518 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
519 "cannot determine objectclass of entry -- aborting\n",
522 * FIXME: should never occur, since the entry was built!!!
526 * FIXME: we don't want to send back
527 * excessively detailed messages
529 send_ldap_result( conn, op, LDAP_OTHER, NULL,
530 "SQL-backend error", NULL, NULL );
537 if ( !acl_check_modlist( be, conn, op, &e, modlist )) {
538 res = LDAP_INSUFFICIENT_ACCESS;
541 res = backsql_modify_internal( be, conn, op,
542 dbh, oc, &e_id, modlist, &text );
545 if ( res == LDAP_SUCCESS ) {
547 * Commit only if all operations succeed
549 SQLTransact( SQL_NULL_HENV, dbh,
550 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
552 send_ldap_result( conn, op, res, NULL, text, NULL, NULL );
553 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
565 struct berval *newrdn,
566 struct berval *nnewrdn,
568 struct berval *newSuperior,
569 struct berval *nnewSuperior )
571 backsql_info *bi = (backsql_info*)be->be_private;
575 backsql_entryID e_id, pe_id, new_pid;
576 backsql_oc_map_rec *oc = NULL;
578 struct berval p_dn, p_ndn,
579 *new_pdn = NULL, *new_npdn = NULL,
581 const char *text = NULL;
582 LDAPRDN *new_rdn = NULL;
583 LDAPRDN *old_rdn = NULL;
587 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
588 "newrdn='%s', newSuperior='%s'\n",
589 dn->bv_val, newrdn->bv_val,
590 newSuperior ? newSuperior->bv_val : "(NULL)" );
591 res = backsql_get_db_conn( be, conn, &dbh );
592 if ( res != LDAP_SUCCESS ) {
593 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
594 "could not get connection handle - exiting\n",
596 send_ldap_result( conn, op, res, NULL,
597 res == LDAP_OTHER ? "SQL-backend error" : "",
602 res = backsql_dn2id( bi, &e_id, dbh, ndn );
603 if ( res != LDAP_SUCCESS ) {
604 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
605 "could not lookup entry id\n", 0, 0, 0 );
606 send_ldap_result( conn, op, res, NULL,
607 res == LDAP_OTHER ? "SQL-backend error" : "",
613 * FIXME: check whether entry has children
616 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
619 if ( backsql_has_children( bi, dbh, ndn ) == LDAP_COMPARE_TRUE ) {
620 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
621 "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
622 send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
623 NULL, "subtree delete not supported",
628 dnParent( dn, &p_dn );
629 dnParent( ndn, &p_ndn );
632 * namingContext "" is not supported
634 if ( p_dn.bv_len == 0 ) {
635 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
636 "parent is \"\" - aborting\n", 0, 0, 0 );
637 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
638 NULL, "not allowed within namingContext",
644 * Check for children access to parent
649 if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
650 NULL, ACL_WRITE, NULL ) ) {
651 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
652 res = LDAP_INSUFFICIENT_ACCESS;
658 * namingContext "" is not supported
660 if ( newSuperior->bv_len == 0 ) {
661 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
662 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
663 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
665 "not allowed within namingContext",
670 new_pdn = newSuperior;
671 new_npdn = nnewSuperior;
674 e.e_nname = *new_npdn;
677 * Check for children access to new parent
679 if ( !access_allowed( be, conn, op, &e,
680 slap_schema.si_ad_children,
681 NULL, ACL_WRITE, NULL ) ) {
682 Debug( LDAP_DEBUG_TRACE, "no access to new parent\n",
684 res = LDAP_INSUFFICIENT_ACCESS;
693 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
694 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
695 "newSuperior is equal to old parent - ignored\n",
700 if ( newSuperior && dn_match( ndn, new_npdn ) ) {
701 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
702 "newSuperior is equal to entry being moved "
703 "- aborting\n", 0, 0, 0 );
704 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
705 NULL, "newSuperior is equal to old DN",
710 build_new_dn( &new_dn, new_pdn, newrdn );
711 if ( dnNormalize2( NULL, &new_dn, &new_ndn ) != LDAP_SUCCESS ) {
712 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
713 "new dn is invalid ('%s') - aborting\n",
714 new_dn.bv_val, 0, 0 );
715 send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX,
716 NULL, "new DN is invalid", NULL, NULL );
720 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): new entry dn is '%s'\n",
721 new_dn.bv_val, 0, 0 );
723 res = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
724 if ( res != LDAP_SUCCESS ) {
725 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
726 "could not lookup old parent entry id\n", 0, 0, 0 );
727 send_ldap_result( conn, op, res, NULL,
728 res == LDAP_OTHER ? "SQL-backend error" : "",
733 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
734 "old parent entry id is %ld\n", pe_id.id, 0, 0 );
736 res = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
737 if ( res != LDAP_SUCCESS ) {
738 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
739 "could not lookup new parent entry id\n", 0, 0, 0 );
740 send_ldap_result( conn, op, res, NULL,
741 res == LDAP_OTHER ? "SQL-backend error" : "",
746 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
747 "new parent entry id is %ld\n", new_pid.id, 0, 0 );
750 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
751 "executing delentry_query\n", 0, 0, 0 );
752 SQLAllocStmt( dbh, &sth );
753 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
754 0, 0, &e_id.id, 0, 0 );
755 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
756 if ( rc != SQL_SUCCESS ) {
757 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
758 "failed to delete record from ldap_entries\n",
760 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
761 send_ldap_result( conn, op, LDAP_OTHER,
762 NULL, "SQL-backend error", NULL, NULL );
766 SQLFreeStmt( sth, SQL_RESET_PARAMS );
768 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
769 "executing insentry_query\n", 0, 0, 0 );
770 backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
771 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
772 0, 0, &e_id.oc_id, 0, 0 );
773 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
774 0, 0, &new_pid.id, 0, 0 );
775 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
776 0, 0, &e_id.keyval, 0, 0 );
777 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
778 if ( rc != SQL_SUCCESS ) {
779 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
780 "could not insert ldap_entries record\n", 0, 0, 0 );
781 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
782 send_ldap_result( conn, op, LDAP_OTHER,
783 NULL, "SQL-backend error", NULL, NULL );
788 * Get attribute type and attribute value of our new rdn,
789 * we will need to add that to our new entry
791 if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
792 LDAP_DN_FORMAT_LDAP ) ) {
794 LDAP_LOG ( OPERATION, ERR,
795 "backsql_modrdn: can't figure out "
796 "type(s)/values(s) of newrdn\n",
799 Debug( LDAP_DEBUG_TRACE,
800 "backsql_modrdn: can't figure out "
801 "type(s)/values(s) of newrdn\n",
804 rc = LDAP_INVALID_DN_SYNTAX;
809 LDAP_LOG ( OPERATION, RESULTS,
810 "backsql_modrdn: new_rdn_type=\"%s\", "
811 "new_rdn_val=\"%s\"\n",
812 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
813 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
815 Debug( LDAP_DEBUG_TRACE,
816 "backsql_modrdn: new_rdn_type=\"%s\", "
817 "new_rdn_val=\"%s\"\n",
818 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
819 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
822 if ( deleteoldrdn ) {
823 if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
824 LDAP_DN_FORMAT_LDAP ) ) {
826 LDAP_LOG ( OPERATION, ERR,
827 "backsql_modrdn: can't figure out "
828 "type(s)/values(s) of old_rdn\n",
831 Debug( LDAP_DEBUG_TRACE,
832 "backsql_modrdn: can't figure out "
833 "the old_rdn type(s)/value(s)\n",
843 res = slap_modrdn2mods( be, conn, op, &e, old_rdn, new_rdn,
844 deleteoldrdn, &mod );
845 if ( res != LDAP_SUCCESS ) {
849 if ( !acl_check_modlist( be, conn, op, &e, mod )) {
850 res = LDAP_INSUFFICIENT_ACCESS;
854 oc = backsql_id2oc( bi, e_id.oc_id );
855 res = backsql_modify_internal( be, conn, op,
856 dbh, oc, &e_id, mod, &text );
858 if ( res == LDAP_SUCCESS ) {
861 * Commit only if all operations succeed
863 SQLTransact( SQL_NULL_HENV, dbh,
864 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
868 SQLFreeStmt( sth, SQL_DROP );
870 if ( new_dn.bv_val ) {
871 ch_free( new_dn.bv_val );
874 if ( new_ndn.bv_val ) {
875 ch_free( new_ndn.bv_val );
878 /* LDAP v2 supporting correct attribute handling. */
879 if ( new_rdn != NULL ) {
880 ldap_rdnfree( new_rdn );
882 if ( old_rdn != NULL ) {
883 ldap_rdnfree( old_rdn );
887 for (; mod; mod=tmp ) {
893 send_ldap_result( conn, op, res, NULL, text, NULL, NULL );
895 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
906 backsql_info *bi = (backsql_info*)be->be_private;
909 unsigned long new_keyval = 0;
912 backsql_oc_map_rec *oc = NULL;
913 backsql_at_map_rec *at_rec = NULL;
914 backsql_entryID e_id, parent_id;
918 struct berval *at_val;
920 /* first parameter #, parameter order */
921 SQLUSMALLINT pno, po;
922 /* procedure return code */
925 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry '%s'\n",
926 e->e_name.bv_val, 0, 0 );
929 if ( global_schemacheck ) {
930 const char *text = NULL;
931 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
933 rc = entry_schema_check( be, e, NULL,
934 &text, textbuf, sizeof( textbuf ) );
935 if ( rc != LDAP_SUCCESS ) {
937 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
938 "entry failed schema check -- aborting\n",
940 send_ldap_result( conn, op, rc, NULL,
941 "operation not permitted "
942 "within namingContext",
948 /* search structural objectClass */
949 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
950 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
955 /* there must exist */
956 assert( at != NULL );
958 /* I guess we should play with sub/supertypes to find a suitable oc */
959 oc = backsql_name2oc( bi, &at->a_vals[0] );
962 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
963 "cannot determine objectclass of entry -- aborting\n",
965 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
966 "operation not permitted within namingContext",
971 if ( oc->create_proc == NULL ) {
972 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
973 "create procedure is not defined for this objectclass "
974 "- aborting\n", 0, 0, 0 );
975 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
976 "operation not permitted within namingContext",
980 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
981 && oc->create_keyval == NULL ) {
982 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
983 "create procedure needs select procedure, "
984 "but none is defined - aborting\n", 0, 0, 0 );
985 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
986 "operation not permitted within namingContext",
991 prc = backsql_get_db_conn( be, conn, &dbh );
992 if ( prc != LDAP_SUCCESS ) {
993 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
994 "could not get connection handle - exiting\n",
996 send_ldap_result( conn, op, prc, NULL,
997 prc == LDAP_OTHER ? "SQL-backend error" : "",
1003 * Check if entry exists
1005 res = backsql_dn2id( bi, &e_id, dbh, &e->e_name );
1006 if ( res == LDAP_SUCCESS ) {
1007 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1008 "entry '%s' exists\n",
1009 e->e_name.bv_val, 0, 0 );
1010 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
1011 NULL, NULL, NULL, NULL );
1016 * Check if parent exists
1018 dnParent( &e->e_name, &pdn );
1019 res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
1020 if ( res != LDAP_SUCCESS ) {
1023 * NO SUCH OBJECT seems more appropriate
1025 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1026 "could not lookup parent entry for new record '%s'\n",
1029 if ( res != LDAP_NO_SUCH_OBJECT ) {
1030 send_ldap_result( conn, op, res,
1031 NULL, NULL, NULL, NULL );
1040 char *matched = NULL;
1043 dnParent( &dn, &pdn );
1046 * Empty DN ("") defaults to LDAP_SUCCESS
1048 res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
1050 case LDAP_NO_SUCH_OBJECT:
1051 if ( pdn.bv_len > 0 ) {
1054 /* fail over to next case */
1057 matched = pdn.bv_val;
1058 /* fail over to next case */
1061 send_ldap_result( conn, op, res,
1062 matched, NULL, NULL, NULL );
1069 * create_proc is executed; if expect_return is set, then
1070 * an output parameter is bound, which should contain
1071 * the id of the added row; otherwise the procedure
1072 * is expected to return the id as the first column of a select
1077 dnParent( &e->e_nname, &p.e_nname );
1078 if ( !access_allowed( be, conn, op, &p, slap_schema.si_ad_children,
1079 NULL, ACL_WRITE, NULL ) ) {
1080 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
1081 NULL, NULL, NULL, NULL );
1085 rc = SQLAllocStmt( dbh, &sth );
1086 if ( rc != SQL_SUCCESS ) {
1087 send_ldap_result( conn, op, LDAP_OTHER,
1088 NULL, "SQL-backend error", NULL, NULL );
1092 if ( BACKSQL_IS_ADD( oc->expect_return ) ) {
1093 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1094 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1097 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s'\n",
1098 oc->create_proc, 0, 0 );
1099 rc = SQLExecDirect( sth, oc->create_proc, SQL_NTS );
1100 if ( rc != SQL_SUCCESS ) {
1101 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1102 "create_proc execution failed\n", 0, 0, 0 );
1103 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1104 SQLFreeStmt( sth, SQL_DROP );
1105 send_ldap_result( conn, op, LDAP_OTHER,
1106 NULL, "SQL-backend error", NULL, NULL );
1110 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1113 if ( !BACKSQL_IS_ADD( oc->expect_return ) ) {
1115 SQLINTEGER value_len;
1117 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1118 #ifndef BACKSQL_REALLOC_STMT
1119 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1120 #else /* BACKSQL_REALLOC_STMT */
1121 SQLFreeStmt( sth, SQL_DROP );
1122 rc = SQLAllocStmt( dbh, &sth );
1123 if ( rc != SQL_SUCCESS ) {
1124 send_ldap_result( conn, op, LDAP_OTHER,
1125 NULL, "SQL-backend error",
1129 #endif /* BACKSQL_REALLOC_STMT */
1131 rc = SQLExecDirect( sth, oc->create_keyval, SQL_NTS );
1132 if ( rc != SQL_SUCCESS ) {
1133 send_ldap_result( conn, op, LDAP_OTHER,
1134 NULL, "SQL-backend error",
1141 * the query to know the id of the inserted entry
1142 * must be embedded in the create procedure
1144 rc = SQLNumResultCols( sth, &ncols );
1145 if ( rc != SQL_SUCCESS ) {
1146 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1147 "create_proc result evaluation failed\n",
1149 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1150 SQLFreeStmt( sth, SQL_DROP );
1151 send_ldap_result( conn, op, LDAP_OTHER,
1152 NULL, "SQL-backend error", NULL, NULL );
1155 } else if ( ncols != 1 ) {
1156 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1157 "create_proc result is bogus (ncols=%d)\n",
1159 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1160 SQLFreeStmt( sth, SQL_DROP );
1161 send_ldap_result( conn, op, LDAP_OTHER,
1162 NULL, "SQL-backend error", NULL, NULL );
1168 SQLCHAR colname[ 64 ];
1169 SQLSMALLINT name_len, col_type, col_scale, col_null;
1173 * FIXME: check whether col_type is compatible,
1174 * if it can be null and so on ...
1176 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1178 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1179 &name_len, &col_type,
1180 &col_prec, &col_scale, &col_null );
1184 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1185 (SQLPOINTER)&new_keyval,
1186 (SQLINTEGER)sizeof( new_keyval ),
1189 rc = SQLFetch( sth );
1191 if ( value_len <= 0 ) {
1192 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1193 "create_proc result is empty?\n",
1195 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1196 SQLFreeStmt( sth, SQL_DROP );
1197 send_ldap_result( conn, op, LDAP_OTHER,
1198 NULL, "SQL-backend error", NULL, NULL );
1203 #ifndef BACKSQL_REALLOC_STMT
1204 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1205 #else /* BACKSQL_REALLOC_STMT */
1206 SQLFreeStmt( sth, SQL_DROP );
1207 #endif /* BACKSQL_REALLOC_STMT */
1209 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1210 "create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
1212 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
1213 SQLUSMALLINT currpos;
1215 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1216 "adding attribute '%s'\n",
1217 at->a_desc->ad_cname.bv_val, 0, 0 );
1221 * - the first occurrence of objectClass, which is used
1222 * to determine how to bulid the SQL entry (FIXME ?!?)
1223 * - operational attributes
1224 * empty attributes (FIXME ?!?)
1226 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1230 at_rec = backsql_ad2at( oc, at->a_desc );
1232 if ( at_rec == NULL ) {
1233 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1234 "attribute '%s' is not registered "
1235 "in objectclass '%s'\n",
1236 at->a_desc->ad_cname.bv_val,
1237 BACKSQL_OC_NAME( oc ), 0 );
1239 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1240 send_ldap_result( conn, op,
1241 LDAP_UNWILLING_TO_PERFORM, NULL,
1242 "operation not permitted "
1243 "within namingContext",
1251 if ( at_rec->add_proc == NULL ) {
1252 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1253 "add procedure is not defined "
1254 "for attribute '%s'\n",
1255 at->a_desc->ad_cname.bv_val, 0, 0 );
1257 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1258 send_ldap_result( conn, op,
1259 LDAP_UNWILLING_TO_PERFORM, NULL,
1260 "operation not permitted "
1261 "within namingContext",
1269 #ifdef BACKSQL_REALLOC_STMT
1270 rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
1271 if ( rc != SQL_SUCCESS ) {
1273 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1274 send_ldap_result( conn, op, LDAP_OTHER,
1275 NULL, "SQL-backend error",
1282 #endif /* BACKSQL_REALLOC_STMT */
1284 if ( BACKSQL_IS_ADD( at_rec->expect_return ) ) {
1286 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
1287 SQL_C_ULONG, SQL_INTEGER,
1293 po = ( BACKSQL_IS_ADD( at_rec->param_order ) ) > 0;
1294 currpos = pno + 1 + po;
1295 SQLBindParameter( sth, currpos,
1296 SQL_PARAM_INPUT, SQL_C_ULONG,
1297 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1298 currpos = pno + 2 - po;
1300 for ( i = 0, at_val = &at->a_vals[ i ];
1301 at_val->bv_val != NULL;
1302 i++, at_val = &at->a_vals[ i ] ) {
1305 * Do not deal with the objectClass that is used
1306 * to build the entry
1308 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1309 if ( bvmatch( at_val, &oc->oc->soc_cname ) ) {
1315 * check for syntax needed here
1316 * maybe need binary bind?
1319 backsql_BindParamStr( sth, currpos,
1320 at_val->bv_val, at_val->bv_len + 1 );
1321 #ifdef SECURITY_PARANOID
1322 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1323 "executing '%s', id=%ld\n",
1324 at_rec->add_proc, new_keyval, 0 );
1326 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1327 "executing '%s' with val='%s', id=%ld\n",
1328 at_rec->add_proc, at_val->bv_val, new_keyval );
1330 #ifndef BACKSQL_REALLOC_STMT
1331 rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
1332 #else /* BACKSQL_REALLOC_STMT */
1333 rc = SQLExecute( sth );
1334 #endif /* BACKSQL_REALLOC_STMT */
1335 if ( rc != SQL_SUCCESS ) {
1336 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1337 "add_proc execution failed\n",
1339 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1341 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1342 send_ldap_result( conn, op, LDAP_OTHER,
1344 "SQL-backend error",
1350 #ifndef BACKSQL_REALLOC_STMT
1351 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1352 #else /* BACKSQL_REALLOC_STMT */
1353 SQLFreeStmt( sth, SQL_DROP );
1354 #endif /* BACKSQL_REALLOC_STMT */
1357 #ifdef BACKSQL_REALLOC_STMT
1358 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1359 if ( rc != SQL_SUCCESS ) {
1360 send_ldap_result( conn, op, LDAP_OTHER,
1361 NULL, "SQL-backend error", NULL, NULL );
1364 #endif /* BACKSQL_REALLOC_STMT */
1366 backsql_BindParamStr( sth, 1, e->e_name.bv_val, BACKSQL_MAX_DN_LEN );
1367 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1368 0, 0, &oc->id, 0, 0 );
1369 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1370 0, 0, &parent_id.id, 0, 0 );
1371 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1372 0, 0, &new_keyval, 0, 0 );
1374 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s' for dn '%s'\n",
1375 bi->insentry_query, e->e_name.bv_val, 0 );
1376 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, parent_id=%ld, "
1377 "keyval=%ld\n", oc->id, parent_id.id, new_keyval );
1378 #ifndef BACKSQL_REALLOC_STMT
1379 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
1380 #else /* BACKSQL_REALLOC_STMT */
1381 rc = SQLExecute( sth );
1382 #endif /* BACKSQL_REALLOC_STMT */
1383 if ( rc != SQL_SUCCESS ) {
1384 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1385 "could not insert ldap_entries record\n", 0, 0, 0 );
1386 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1389 * execute delete_proc to delete data added !!!
1391 SQLFreeStmt( sth, SQL_DROP );
1392 send_ldap_result( conn, op, LDAP_OTHER,
1393 NULL, "SQL-backend error", NULL, NULL );
1397 SQLFreeStmt( sth, SQL_DROP );
1400 * Commit only if all operations succeed
1402 SQLTransact( SQL_NULL_HENV, dbh,
1403 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1406 * FIXME: NOOP does not work for add -- it works for all
1407 * the other operations, and I don't get the reason :(
1410 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL );
1421 struct berval *ndn )
1423 backsql_info *bi = (backsql_info*)be->be_private;
1427 backsql_oc_map_rec *oc = NULL;
1428 backsql_entryID e_id;
1431 /* first parameter no */
1434 Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
1435 ndn->bv_val, 0, 0 );
1437 dnParent( dn, &e.e_name );
1438 dnParent( ndn, &e.e_nname );
1441 /* check parent for "children" acl */
1442 if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
1443 NULL, ACL_WRITE, NULL ) ) {
1444 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1445 "no write access to parent\n",
1447 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
1448 NULL, NULL, NULL, NULL );
1453 res = backsql_get_db_conn( be, conn, &dbh );
1454 if ( res != LDAP_SUCCESS ) {
1455 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1456 "could not get connection handle - exiting\n",
1458 send_ldap_result( conn, op, res, NULL,
1459 res == LDAP_OTHER ? "SQL-backend error" : "",
1464 res = backsql_dn2id( bi, &e_id, dbh, ndn );
1465 if ( res != LDAP_SUCCESS ) {
1466 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1467 "could not lookup entry id\n", 0, 0, 0 );
1468 send_ldap_result( conn, op, res, NULL, NULL, NULL, NULL );
1472 res = backsql_has_children( bi, dbh, ndn );
1474 case LDAP_COMPARE_TRUE:
1475 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1476 "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
1477 send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
1478 NULL, "subtree delete not supported",
1482 case LDAP_COMPARE_FALSE:
1486 send_ldap_result( conn, op, res, NULL, NULL, NULL, NULL );
1490 oc = backsql_id2oc( bi, e_id.oc_id );
1492 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1493 "cannot determine objectclass of entry -- aborting\n",
1495 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
1496 "operation not permitted within namingContext",
1501 if ( oc->delete_proc == NULL ) {
1502 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1503 "delete procedure is not defined "
1504 "for this objectclass - aborting\n", 0, 0, 0 );
1505 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
1506 "operation not permitted within namingContext",
1511 SQLAllocStmt( dbh, &sth );
1512 if ( BACKSQL_IS_DEL( oc->expect_return ) ) {
1514 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1515 SQL_INTEGER, 0, 0, &rc, 0, 0 );
1520 SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT,
1521 SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
1523 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
1524 oc->delete_proc, 0, 0 );
1525 rc = SQLExecDirect( sth, oc->delete_proc, SQL_NTS );
1526 if ( rc != SQL_SUCCESS ) {
1527 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1528 "delete_proc execution failed\n", 0, 0, 0 );
1529 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1530 SQLFreeStmt( sth, SQL_DROP );
1531 send_ldap_result( conn, op, LDAP_OTHER,
1532 NULL, "SQL-backend error", NULL, NULL );
1535 #ifndef BACKSQL_REALLOC_STMT
1536 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1537 #else /* BACKSQL_REALLOC_STMT */
1538 SQLFreeStmt( sth, SQL_DROP );
1539 SQLAllocStmt( dbh, &sth );
1540 #endif /* BACKSQL_REALLOC_STMT */
1542 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
1543 0, 0, &e_id.id, 0, 0 );
1544 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
1545 if ( rc != SQL_SUCCESS ) {
1546 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1547 "failed to delete record from ldap_entries\n",
1549 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1550 SQLFreeStmt( sth, SQL_DROP );
1551 send_ldap_result( conn, op, LDAP_OTHER,
1552 NULL, "SQL-backend error", NULL, NULL );
1556 SQLFreeStmt( sth, SQL_DROP );
1559 * Commit only if all operations succeed
1561 * FIXME: backsql_add() does not fail if add operations
1562 * are not available for some attributes, or if
1563 * a multiple value add actually results in a replace,
1564 * or if a single operation on an attribute fails
1567 SQLTransact( SQL_NULL_HENV, dbh,
1568 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1570 send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, NULL );
1571 Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
1575 #endif /* SLAPD_SQL */