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>
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(
49 backsql_oc_map_rec *oc,
50 backsql_entryID *e_id,
51 Modifications *modlist,
57 int res = LDAP_SUCCESS;
59 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
60 "traversing modifications list\n", 0, 0, 0 );
64 #ifndef BACKSQL_REALLOC_STMT
65 SQLAllocStmt( dbh, &sth );
66 #endif /* BACKSQL_REALLOC_STMT */
68 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
69 AttributeDescription *ad;
70 backsql_at_map_rec *at = NULL;
71 struct berval *at_val;
74 /* first parameter no, parameter order */
76 /* procedure return code */
79 #ifdef BACKSQL_REALLOC_STMT
80 SQLAllocStmt( dbh, &sth );
81 #endif /* BACKSQL_REALLOC_STMT */
86 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
87 "modifying attribute '%s'\n",
88 ad->ad_cname.bv_val, 0, 0 );
90 if ( backsql_attr_skip( ad, c_mod->sm_bvalues ) ) {
94 at = backsql_ad2at( oc, ad );
96 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
97 "attribute provided is not registered "
98 "in objectClass '%s'\n",
99 ad->ad_cname.bv_val, 0, 0 );
101 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
102 res = LDAP_UNWILLING_TO_PERFORM;
103 *text = "operation not permitted "
104 "within namingContext";
111 switch( c_mod->sm_op ) {
112 case LDAP_MOD_REPLACE: {
116 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
117 "replacing values for attribute '%s'\n",
118 at->ad->ad_cname.bv_val, 0, 0 );
120 if ( at->add_proc == NULL ) {
121 Debug( LDAP_DEBUG_TRACE,
122 "backsql_modify_internal(): "
123 "add procedure is not defined "
124 "for attribute '%s' "
125 "- unable to perform replacements\n",
126 at->ad->ad_cname.bv_val, 0, 0 );
128 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
129 res = LDAP_UNWILLING_TO_PERFORM;
130 *text = "operation not permitted "
131 "within namingContext";
138 if ( at->delete_proc == NULL ) {
139 Debug( LDAP_DEBUG_TRACE,
140 "backsql_modify_internal(): "
141 "delete procedure is not defined "
142 "for attribute '%s' "
144 at->ad->ad_cname.bv_val, 0, 0 );
146 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
147 res = LDAP_UNWILLING_TO_PERFORM;
148 *text = "operation not permitted "
149 "within namingContext";
157 rc = backsql_Prepare( dbh, &asth, at->query, 0 );
158 if ( rc != SQL_SUCCESS ) {
159 Debug( LDAP_DEBUG_TRACE,
160 "backsql_modify_internal(): "
161 "error preparing query\n", 0, 0, 0 );
162 backsql_PrintErrors( bi->db_env, dbh,
165 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
167 *text = "SQL-backend error";
174 rc = backsql_BindParamID( asth, 1, &e_id->keyval );
175 if ( rc != SQL_SUCCESS ) {
176 Debug( LDAP_DEBUG_TRACE,
177 "backsql_modify_internal(): "
178 "error binding key value parameter\n",
180 backsql_PrintErrors( bi->db_env, dbh,
182 SQLFreeStmt( asth, SQL_DROP );
184 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
186 *text = "SQL-backend error";
193 rc = SQLExecute( asth );
194 if ( !BACKSQL_SUCCESS( rc ) ) {
195 Debug( LDAP_DEBUG_TRACE,
196 "backsql_modify_internal(): "
197 "error executing attribute query\n",
199 backsql_PrintErrors( bi->db_env, dbh,
201 SQLFreeStmt( asth, SQL_DROP );
203 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
205 *text = "SQL-backend error";
212 backsql_BindRowAsStrings( asth, &row );
213 rc = SQLFetch( asth );
214 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
215 for ( i = 0; i < row.ncols; i++ ) {
216 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
218 SQLBindParameter(sth, 1,
226 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
227 SQLBindParameter( sth, pno + 1 + po,
229 SQL_C_ULONG, SQL_INTEGER,
230 0, 0, &e_id->keyval, 0, 0 );
233 * check for syntax needed here
234 * maybe need binary bind?
236 SQLBindParameter(sth, pno + 2 - po,
238 SQL_C_CHAR, SQL_CHAR,
240 strlen( row.cols[ i ] ), 0 );
242 Debug( LDAP_DEBUG_TRACE,
243 "backsql_modify_internal(): "
245 at->delete_proc, 0, 0 );
246 rc = SQLExecDirect( sth,
247 at->delete_proc, SQL_NTS );
248 if ( rc != SQL_SUCCESS ) {
249 Debug( LDAP_DEBUG_TRACE,
250 "backsql_modify_internal(): "
252 "execution failed\n",
254 backsql_PrintErrors( bi->db_env,
257 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
259 *text = "SQL-backend error";
263 #ifdef BACKSQL_REALLOC_STMT
264 SQLFreeStmt( sth, SQL_DROP );
265 SQLAllocStmt( dbh, &sth );
266 #endif /* BACKSQL_REALLOC_STMT */
269 backsql_FreeRow( &row );
270 SQLFreeStmt( asth, SQL_DROP );
274 * PASSTHROUGH - to add new attributes -- do NOT add break
277 case SLAP_MOD_SOFTADD:
279 if ( at->add_proc == NULL ) {
280 Debug( LDAP_DEBUG_TRACE,
281 "backsql_modify_internal(): "
282 "add procedure is not defined "
283 "for attribute '%s'\n",
284 at->ad->ad_cname.bv_val, 0, 0 );
286 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
287 res = LDAP_UNWILLING_TO_PERFORM;
288 *text = "operation not permitted "
289 "within namingContext";
296 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
297 "adding new values for attribute '%s'\n",
298 at->ad->ad_cname.bv_val, 0, 0 );
299 for ( i = 0, at_val = c_mod->sm_bvalues;
300 at_val->bv_val != NULL;
302 if ( BACKSQL_IS_ADD( at->expect_return ) ) {
304 SQLBindParameter( sth, 1,
306 SQL_C_ULONG, SQL_INTEGER,
311 po = ( BACKSQL_IS_ADD( at->param_order ) ) > 0;
312 SQLBindParameter( sth, pno + 1 + po,
314 SQL_C_ULONG, SQL_INTEGER,
315 0, 0, &e_id->keyval, 0, 0 );
318 * check for syntax needed here
319 * maybe need binary bind?
321 SQLBindParameter( sth, pno + 2 - po,
323 SQL_C_CHAR, SQL_CHAR,
324 0, 0, at_val->bv_val,
327 Debug( LDAP_DEBUG_TRACE,
328 "backsql_modify_internal(): "
330 at->add_proc, 0, 0 );
331 rc = SQLExecDirect( sth, at->add_proc,
333 if ( rc != SQL_SUCCESS ) {
334 Debug( LDAP_DEBUG_TRACE,
335 "backsql_modify_internal(): "
336 "add_proc execution failed\n",
338 backsql_PrintErrors( bi->db_env,
341 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
343 *text = "SQL-backend error";
347 #ifdef BACKSQL_REALLOC_STMT
348 SQLFreeStmt( sth, SQL_DROP );
349 SQLAllocStmt( dbh, &sth );
350 #endif /* BACKSQL_REALLOC_STMT */
354 case LDAP_MOD_DELETE:
355 if ( at->delete_proc == NULL ) {
356 Debug( LDAP_DEBUG_TRACE,
357 "backsql_modify_internal(): "
358 "delete procedure is not defined "
359 "for attribute '%s'\n",
360 at->ad->ad_cname.bv_val, 0, 0 );
362 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
363 res = LDAP_UNWILLING_TO_PERFORM;
364 *text = "operation not permitted "
365 "within namingContext";
372 if ( c_mod->sm_bvalues == NULL ) {
373 Debug( LDAP_DEBUG_TRACE,
374 "backsql_modify_internal(): "
375 "no values given to delete "
376 "for attribute '%s' "
377 "-- deleting all values\n",
378 at->ad->ad_cname.bv_val, 0, 0 );
382 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
383 "deleting values for attribute '%s'\n",
384 at->ad->ad_cname.bv_val, 0, 0 );
386 for ( i = 0, at_val = c_mod->sm_bvalues;
387 at_val->bv_val != NULL;
389 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
391 SQLBindParameter( sth, 1,
393 SQL_C_ULONG, SQL_INTEGER,
398 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
399 SQLBindParameter( sth, pno + 1 + po,
401 SQL_C_ULONG, SQL_INTEGER,
402 0, 0, &e_id->keyval, 0, 0 );
405 * check for syntax needed here
406 * maybe need binary bind?
408 SQLBindParameter( sth, pno + 2 - po,
409 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
410 0, 0, at_val->bv_val,
413 Debug( LDAP_DEBUG_TRACE,
414 "backsql_modify_internal(): "
416 at->delete_proc, 0, 0 );
417 rc = SQLExecDirect( sth, at->delete_proc,
419 if ( rc != SQL_SUCCESS ) {
420 Debug( LDAP_DEBUG_TRACE,
421 "backsql_modify_internal(): "
422 "delete_proc execution "
423 "failed\n", 0, 0, 0 );
424 backsql_PrintErrors( bi->db_env,
427 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
429 *text = "SQL-backend error";
433 #ifdef BACKSQL_REALLOC_STMT
434 SQLFreeStmt( sth, SQL_DROP );
435 SQLAllocStmt( dbh, &sth );
436 #endif /* BACKSQL_REALLOC_STMT */
440 #ifndef BACKSQL_REALLOC_STMT
441 SQLFreeStmt( sth, SQL_RESET_PARAMS );
442 #else /* BACKSQL_REALLOC_STMT */
443 SQLFreeStmt( sth, SQL_DROP );
444 #endif /* BACKSQL_REALLOC_STMT */
449 #ifndef BACKSQL_REALLOC_STMT
450 SQLFreeStmt( sth, SQL_DROP );
451 #endif /* BACKSQL_REALLOC_STMT */
454 * FIXME: should fail in case one change fails?
466 Modifications *modlist )
468 backsql_info *bi = (backsql_info*)be->be_private;
470 backsql_oc_map_rec *oc = NULL;
471 backsql_entryID e_id;
474 const char *text = NULL;
477 * FIXME: in case part of the operation cannot be performed
478 * (missing mapping, SQL write fails or so) the entire operation
479 * should be rolled-back
482 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
484 res = backsql_get_db_conn( be, conn, &dbh );
485 if ( res != LDAP_SUCCESS ) {
486 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
487 "could not get connection handle - exiting\n",
490 * FIXME: we don't want to send back
491 * excessively detailed messages
493 send_ldap_result( conn, op, res, "",
494 res == LDAP_OTHER ? "SQL-backend error" : "",
499 res = backsql_dn2id( bi, &e_id, dbh, ndn );
500 if ( res != LDAP_SUCCESS ) {
501 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
502 "could not lookup entry id\n", 0, 0, 0 );
503 send_ldap_result( conn, op, res , "",
504 res == LDAP_OTHER ? "SQL-backend error" : "",
509 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
510 "modifying entry '%s' (id=%ld)\n",
511 e_id.dn.bv_val, e_id.id, 0 );
513 oc = backsql_id2oc( bi, e_id.oc_id );
515 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
516 "cannot determine objectclass of entry -- aborting\n",
519 * FIXME: should never occur, since the entry was built!!!
523 * FIXME: we don't want to send back
524 * excessively detailed messages
526 send_ldap_result( conn, op, LDAP_OTHER, "",
527 "SQL-backend error", NULL, NULL );
534 if ( !acl_check_modlist( be, conn, op, &e, modlist )) {
535 res = LDAP_INSUFFICIENT_ACCESS;
538 res = backsql_modify_internal( bi, dbh, oc, &e_id,
542 if ( res == LDAP_SUCCESS ) {
544 * Commit only if all operations succeed
546 * FIXME: backsql_modify_internal() does not fail
547 * if add/delete operations are not available, or
548 * if a multiple value add actually results in a replace,
549 * or if a single operation on an attribute fails
552 SQLTransact( SQL_NULL_HENV, dbh,
553 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
555 send_ldap_result( conn, op, res, NULL, text, NULL, NULL );
556 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
568 struct berval *newrdn,
569 struct berval *nnewrdn,
571 struct berval *newSuperior,
572 struct berval *nnewSuperior )
574 backsql_info *bi = (backsql_info*)be->be_private;
578 backsql_entryID e_id, pe_id, new_pid;
579 backsql_oc_map_rec *oc = NULL;
581 struct berval p_dn, p_ndn,
582 *new_pdn = NULL, *new_npdn = NULL,
584 const char *text = NULL;
585 LDAPRDN *new_rdn = NULL;
586 LDAPRDN *old_rdn = NULL;
590 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
591 "newrdn='%s', newSuperior='%s'\n",
592 dn->bv_val, newrdn->bv_val,
593 newSuperior ? newSuperior->bv_val : "(NULL)" );
594 res = backsql_get_db_conn( be, conn, &dbh );
595 if ( res != LDAP_SUCCESS ) {
596 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
597 "could not get connection handle - exiting\n",
599 send_ldap_result( conn, op, res, "",
600 res == LDAP_OTHER ? "SQL-backend error" : "",
605 res = backsql_dn2id( bi, &e_id, dbh, ndn );
606 if ( res != LDAP_SUCCESS ) {
607 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
608 "could not lookup entry id\n", 0, 0, 0 );
609 send_ldap_result( conn, op, res, "",
610 res == LDAP_OTHER ? "SQL-backend error" : "",
616 * FIXME: check whether entry has children
619 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
622 if ( backsql_has_children( bi, dbh, ndn ) == LDAP_COMPARE_TRUE ) {
623 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
624 "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
625 send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
626 NULL, "subtree delete not supported",
631 dnParent( dn, &p_dn );
632 dnParent( ndn, &p_ndn );
635 * namingContext "" is not supported
637 if ( p_dn.bv_len == 0 ) {
638 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
639 "parent is \"\" - aborting\n", 0, 0, 0 );
640 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
641 "", "not allowed within namingContext",
647 * Check for children access to parent
652 if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
653 NULL, ACL_WRITE, NULL ) ) {
654 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
655 res = LDAP_INSUFFICIENT_ACCESS;
661 * namingContext "" is not supported
663 if ( newSuperior->bv_len == 0 ) {
664 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
665 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
666 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
667 "", "not allowed within namingContext",
672 new_pdn = newSuperior;
673 new_npdn = nnewSuperior;
676 e.e_nname = *new_npdn;
679 * Check for children access to new parent
681 if ( !access_allowed( be, conn, op, &e,
682 slap_schema.si_ad_children,
683 NULL, ACL_WRITE, NULL ) ) {
684 Debug( LDAP_DEBUG_TRACE, "no access to new parent\n",
686 res = LDAP_INSUFFICIENT_ACCESS;
695 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
696 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
697 "newSuperior is equal to old parent - ignored\n",
702 if ( newSuperior && dn_match( ndn, new_npdn ) ) {
703 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
704 "newSuperior is equal to entry being moved "
705 "- aborting\n", 0, 0, 0 );
706 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
711 build_new_dn( &new_dn, new_pdn, newrdn );
712 if ( dnNormalize2( NULL, &new_dn, &new_ndn ) != LDAP_SUCCESS ) {
713 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
714 "new dn is invalid ('%s') - aborting\n",
715 new_dn.bv_val, 0, 0 );
716 send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, "",
721 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): new entry dn is '%s'\n",
722 new_dn.bv_val, 0, 0 );
724 res = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
725 if ( res != LDAP_SUCCESS ) {
726 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
727 "could not lookup old parent entry id\n", 0, 0, 0 );
728 send_ldap_result( conn, op, res, "",
729 res == LDAP_OTHER ? "SQL-backend error" : "",
734 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
735 "old parent entry id is %ld\n", pe_id.id, 0, 0 );
737 res = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
738 if ( res != LDAP_SUCCESS ) {
739 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
740 "could not lookup new parent entry id\n", 0, 0, 0 );
741 send_ldap_result( conn, op, res, "",
742 res == LDAP_OTHER ? "SQL-backend error" : "",
747 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
748 "new parent entry id is %ld\n", new_pid.id, 0, 0 );
751 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
752 "executing delentry_query\n", 0, 0, 0 );
753 SQLAllocStmt( dbh, &sth );
754 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
755 0, 0, &e_id.id, 0, 0 );
756 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
757 if ( rc != SQL_SUCCESS ) {
758 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
759 "failed to delete record from ldap_entries\n",
761 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
762 send_ldap_result( conn, op, LDAP_OTHER, "",
763 "SQL-backend error", NULL, NULL );
767 SQLFreeStmt( sth, SQL_RESET_PARAMS );
769 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
770 "executing insentry_query\n", 0, 0, 0 );
771 backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
772 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
773 0, 0, &e_id.oc_id, 0, 0 );
774 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
775 0, 0, &new_pid.id, 0, 0 );
776 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
777 0, 0, &e_id.keyval, 0, 0 );
778 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
779 if ( rc != SQL_SUCCESS ) {
780 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
781 "could not insert ldap_entries record\n", 0, 0, 0 );
782 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
783 send_ldap_result( conn, op, LDAP_OTHER, "",
784 "SQL-backend error", NULL, NULL );
789 * Get attribute type and attribute value of our new rdn,
790 * we will need to add that to our new entry
792 if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
793 LDAP_DN_FORMAT_LDAP ) ) {
795 LDAP_LOG ( OPERATION, ERR,
796 "backsql_modrdn: can't figure out "
797 "type(s)/values(s) of newrdn\n",
800 Debug( LDAP_DEBUG_TRACE,
801 "backsql_modrdn: can't figure out "
802 "type(s)/values(s) of newrdn\n",
805 rc = LDAP_INVALID_DN_SYNTAX;
810 LDAP_LOG ( OPERATION, RESULTS,
811 "backsql_modrdn: new_rdn_type=\"%s\", "
812 "new_rdn_val=\"%s\"\n",
813 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
814 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
816 Debug( LDAP_DEBUG_TRACE,
817 "backsql_modrdn: new_rdn_type=\"%s\", "
818 "new_rdn_val=\"%s\"\n",
819 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
820 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
823 if ( deleteoldrdn ) {
824 if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
825 LDAP_DN_FORMAT_LDAP ) ) {
827 LDAP_LOG ( OPERATION, ERR,
828 "backsql_modrdn: can't figure out "
829 "type(s)/values(s) of old_rdn\n",
832 Debug( LDAP_DEBUG_TRACE,
833 "backsql_modrdn: can't figure out "
834 "the old_rdn type(s)/value(s)\n",
844 res = slap_modrdn2mods( be, conn, op, &e, old_rdn, new_rdn,
845 deleteoldrdn, &mod );
846 if ( res != LDAP_SUCCESS ) {
850 if ( !acl_check_modlist( be, conn, op, &e, mod )) {
851 res = LDAP_INSUFFICIENT_ACCESS;
855 oc = backsql_id2oc( bi, e_id.oc_id );
856 res = backsql_modify_internal( bi, dbh, oc, &e_id, mod, &text );
858 if ( res == LDAP_SUCCESS ) {
861 * Commit only if all operations succeed
863 * FIXME: backsql_modify_internal() does not fail
864 * if add/delete operations are not available, or
865 * if a multiple value add actually results in a replace,
866 * or if a single operation on an attribute fails for any
869 SQLTransact( SQL_NULL_HENV, dbh,
870 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
874 SQLFreeStmt( sth, SQL_DROP );
876 if ( new_dn.bv_val ) {
877 ch_free( new_dn.bv_val );
880 if ( new_ndn.bv_val ) {
881 ch_free( new_ndn.bv_val );
884 /* LDAP v2 supporting correct attribute handling. */
885 if ( new_rdn != NULL ) {
886 ldap_rdnfree( new_rdn );
888 if ( old_rdn != NULL ) {
889 ldap_rdnfree( old_rdn );
893 for (; mod; mod=tmp ) {
899 send_ldap_result( conn, op, res, "", text, NULL, NULL );
901 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
912 backsql_info *bi = (backsql_info*)be->be_private;
915 unsigned long new_keyval = 0;
918 backsql_oc_map_rec *oc = NULL;
919 backsql_at_map_rec *at_rec = NULL;
920 backsql_entryID e_id, parent_id;
924 struct berval *at_val;
926 /* first parameter #, parameter order */
927 SQLUSMALLINT pno, po;
928 /* procedure return code */
931 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry '%s'\n",
932 e->e_name.bv_val, 0, 0 );
934 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
935 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
936 if ( global_schemacheck ) {
937 const char *text = NULL;
938 char textbuf[ 1024 ];
939 size_t textlen = sizeof( textbuf );
942 int rc = structural_class( at->a_vals, &soc,
943 NULL, &text, textbuf, textlen );
944 if ( rc != LDAP_SUCCESS ) {
947 oc = backsql_name2oc( bi, &soc );
952 * FIXME: only the objectClass provided first
953 * is considered when creating a new entry
955 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, "",
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, "",
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, but none is defined"
984 "- aborting\n", 0, 0, 0 );
985 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
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, "",
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, "",
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, "", NULL, NULL, NULL );
1042 dnParent( &dn, &pdn );
1045 * Empty DN ("") defaults to LDAP_SUCCESS
1047 res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
1049 case LDAP_NO_SUCH_OBJECT:
1050 if ( pdn.bv_len > 0 ) {
1053 /* fail over to next case */
1056 matched = pdn.bv_val;
1057 /* fail over to next case */
1060 send_ldap_result( conn, op, res, matched,
1068 * create_proc is executed; if expect_return is set, then
1069 * an output parameter is bound, which should contain
1070 * the id of the added row; otherwise the procedure
1071 * is expected to return the id as the first column of a select
1076 dnParent( &e->e_nname, &p.e_nname );
1077 if ( !access_allowed( be, conn, op, &p, slap_schema.si_ad_children,
1078 NULL, ACL_WRITE, NULL ) ) {
1079 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
1080 NULL, NULL, NULL, NULL );
1084 #ifndef BACKSQL_REALLOC_STMT
1085 rc = SQLAllocStmt( dbh, &sth );
1086 #else /* BACKSQL_REALLOC_STMT */
1087 rc = backsql_Prepare( dbh, &sth, oc->create_proc, 0 );
1088 #endif /* BACKSQL_REALLOC_STMT */
1089 if ( rc != SQL_SUCCESS ) {
1090 send_ldap_result( conn, op, LDAP_OTHER, "",
1091 "SQL-backend error", NULL, NULL );
1095 if ( BACKSQL_IS_ADD( oc->expect_return ) ) {
1096 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1097 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1100 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s'\n",
1101 oc->create_proc, 0, 0 );
1102 #ifndef BACKSQL_REALLOC_STMT
1103 rc = SQLExecDirect( sth, oc->create_proc, SQL_NTS );
1104 #else /* BACKSQL_REALLOC_STMT */
1105 rc = SQLExecute( sth );
1106 #endif /* BACKSQL_REALLOC_STMT */
1107 if ( rc != SQL_SUCCESS ) {
1108 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1109 "create_proc execution failed\n", 0, 0, 0 );
1110 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1111 SQLFreeStmt( sth, SQL_DROP );
1112 send_ldap_result( conn, op, LDAP_OTHER, "",
1113 "SQL-backend error", NULL, NULL );
1117 if ( !BACKSQL_IS_ADD( oc->expect_return ) ) {
1121 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1122 #ifndef BACKSQL_REALLOC_STMT
1123 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1124 #else /* BACKSQL_REALLOC_STMT */
1125 SQLFreeStmt( sth, SQL_DROP );
1126 rc = SQLAllocStmt( dbh, &sth );
1127 if ( rc != SQL_SUCCESS ) {
1128 send_ldap_result( conn, op, LDAP_OTHER, "",
1129 "SQL-backend error", NULL, NULL );
1132 #endif /* BACKSQL_REALLOC_STMT */
1134 rc = SQLExecDirect( sth, oc->create_keyval, SQL_NTS );
1135 if ( rc != SQL_SUCCESS ) {
1136 send_ldap_result( conn, op, LDAP_OTHER, "",
1137 "SQL-backend error", NULL, NULL );
1143 * the query to know the id of the inserted entry
1144 * must be embedded in the create procedure
1146 rc = SQLNumResultCols( sth, &ncols );
1147 if ( rc != SQL_SUCCESS ) {
1148 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1149 "create_proc result evaluation failed\n",
1151 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1152 SQLFreeStmt( sth, SQL_DROP );
1153 send_ldap_result( conn, op, LDAP_OTHER, "",
1154 "SQL-backend error", NULL, NULL );
1157 } else if ( ncols != 1 ) {
1158 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1159 "create_proc result is bogus (ncols=%d)\n",
1161 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1162 SQLFreeStmt( sth, SQL_DROP );
1163 send_ldap_result( conn, op, LDAP_OTHER, "",
1164 "SQL-backend error", NULL, NULL );
1170 SQLCHAR colname[ 64 ];
1171 SQLSMALLINT name_len, col_type, col_scale, col_null;
1175 * FIXME: check whether col_type is compatible,
1176 * if it can be null and so on ...
1178 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1180 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1181 &name_len, &col_type,
1182 &col_prec, &col_scale, &col_null );
1186 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1187 (SQLPOINTER)&new_keyval,
1188 (SQLINTEGER)sizeof( new_keyval ),
1191 rc = SQLFetch( sth );
1195 * FIXME: what does is_null mean?
1198 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1199 "create_proc result is null\n",
1201 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1202 SQLFreeStmt( sth, SQL_DROP );
1203 send_ldap_result( conn, op, LDAP_OTHER, "",
1204 "SQL-backend error", NULL, NULL );
1210 #ifndef BACKSQL_REALLOC_STMT
1211 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1212 #else /* BACKSQL_REALLOC_STMT */
1213 SQLFreeStmt( sth, SQL_DROP );
1214 #endif /* BACKSQL_REALLOC_STMT */
1216 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1217 "create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
1219 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
1220 SQLUSMALLINT currpos;
1222 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1223 "adding attribute '%s'\n",
1224 at->a_desc->ad_cname.bv_val, 0, 0 );
1228 * - the first occurrence of objectClass, which is used
1229 * to determine how to bulid the SQL entry (FIXME ?!?)
1230 * - operational attributes
1231 * empty attributes (FIXME ?!?)
1233 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1237 at_rec = backsql_ad2at( oc, at->a_desc );
1239 if ( at_rec == NULL ) {
1240 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1241 "attribute '%s' is not registered "
1242 "in objectclass '%s'\n",
1243 at->a_desc->ad_cname.bv_val,
1244 BACKSQL_OC_NAME( oc ), 0 );
1246 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1247 send_ldap_result( conn, op,
1248 LDAP_UNWILLING_TO_PERFORM, "",
1249 "operation not permitted "
1250 "within namingContext",
1258 if ( at_rec->add_proc == NULL ) {
1259 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1260 "add procedure is not defined "
1261 "for attribute '%s'\n",
1262 at->a_desc->ad_cname.bv_val, 0, 0 );
1264 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1265 send_ldap_result( conn, op,
1266 LDAP_UNWILLING_TO_PERFORM, "",
1267 "operation not permitted "
1268 "within namingContext",
1276 #ifdef BACKSQL_REALLOC_STMT
1277 rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
1278 if ( rc != SQL_SUCCESS ) {
1280 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1281 send_ldap_result( conn, op,
1283 "SQL-backend error",
1290 #endif /* BACKSQL_REALLOC_STMT */
1292 if ( BACKSQL_IS_ADD( at_rec->expect_return ) ) {
1294 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
1295 SQL_C_ULONG, SQL_INTEGER,
1301 po = ( BACKSQL_IS_ADD( at_rec->param_order ) ) > 0;
1302 currpos = pno + 1 + po;
1303 SQLBindParameter( sth, currpos,
1304 SQL_PARAM_INPUT, SQL_C_ULONG,
1305 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1306 currpos = pno + 2 - po;
1308 for ( i = 0, at_val = &at->a_vals[ i ];
1309 at_val->bv_val != NULL;
1310 i++, at_val = &at->a_vals[ i ] ) {
1313 * Do not deal with the objectClass that is used
1314 * to build the entry
1316 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1317 if ( bvmatch( at_val, &oc->oc->soc_cname ) ) {
1323 * check for syntax needed here
1324 * maybe need binary bind?
1327 backsql_BindParamStr( sth, currpos,
1328 at_val->bv_val, at_val->bv_len + 1 );
1329 #ifdef SECURITY_PARANOID
1330 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1331 "executing '%s', id=%ld\n",
1332 at_rec->add_proc, new_keyval, 0 );
1334 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1335 "executing '%s' with val='%s', id=%ld\n",
1336 at_rec->add_proc, at_val->bv_val, new_keyval );
1338 #ifndef BACKSQL_REALLOC_STMT
1339 rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
1340 #else /* BACKSQL_REALLOC_STMT */
1341 rc = SQLExecute( sth );
1342 #endif /* BACKSQL_REALLOC_STMT */
1343 if ( rc != SQL_SUCCESS ) {
1344 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1345 "add_proc execution failed\n",
1347 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1349 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1350 send_ldap_result( conn, op,
1352 "SQL-backend error",
1358 #ifndef BACKSQL_REALLOC_STMT
1359 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1360 #else /* BACKSQL_REALLOC_STMT */
1361 SQLFreeStmt( sth, SQL_DROP );
1362 #endif /* BACKSQL_REALLOC_STMT */
1365 #ifdef BACKSQL_REALLOC_STMT
1366 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1367 if ( rc != SQL_SUCCESS ) {
1368 send_ldap_result( conn, op, LDAP_OTHER, "",
1369 "SQL-backend error", NULL, NULL );
1372 #endif /* BACKSQL_REALLOC_STMT */
1374 backsql_BindParamStr( sth, 1, e->e_name.bv_val, BACKSQL_MAX_DN_LEN );
1375 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1376 0, 0, &oc->id, 0, 0 );
1377 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1378 0, 0, &parent_id.id, 0, 0 );
1379 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1380 0, 0, &new_keyval, 0, 0 );
1382 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s' for dn '%s'\n",
1383 bi->insentry_query, e->e_name.bv_val, 0 );
1384 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, parent_id=%ld, "
1385 "keyval=%ld\n", oc->id, parent_id.id, new_keyval );
1386 #ifndef BACKSQL_REALLOC_STMT
1387 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
1388 #else /* BACKSQL_REALLOC_STMT */
1389 rc = SQLExecute( sth );
1390 #endif /* BACKSQL_REALLOC_STMT */
1391 if ( rc != SQL_SUCCESS ) {
1392 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1393 "could not insert ldap_entries record\n", 0, 0, 0 );
1394 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1397 * execute delete_proc to delete data added !!!
1399 SQLFreeStmt( sth, SQL_DROP );
1400 send_ldap_result( conn, op, LDAP_OTHER, "",
1401 "SQL-backend error", NULL, NULL );
1405 SQLFreeStmt( sth, SQL_DROP );
1408 * Commit only if all operations succeed
1410 * FIXME: backsql_add() does not fail if add operations
1411 * are not available for some attributes, or if
1412 * a multiple value add actually results in a replace,
1413 * or if a single operation on an attribute fails
1416 SQLTransact( SQL_NULL_HENV, dbh,
1417 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1419 send_ldap_result( conn, op, LDAP_SUCCESS, "",
1430 struct berval *ndn )
1432 backsql_info *bi = (backsql_info*)be->be_private;
1436 backsql_oc_map_rec *oc = NULL;
1437 backsql_entryID e_id;
1440 /* first parameter no */
1443 Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
1444 ndn->bv_val, 0, 0 );
1446 dnParent( dn, &e.e_name );
1447 dnParent( ndn, &e.e_nname );
1450 /* check parent for "children" acl */
1451 if ( !access_allowed( be, conn, op, &e, slap_schema.si_ad_children,
1452 NULL, ACL_WRITE, NULL ) ) {
1453 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1454 "no write access to parent\n",
1456 send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
1457 "", NULL, NULL, NULL );
1462 res = backsql_get_db_conn( be, conn, &dbh );
1463 if ( res != LDAP_SUCCESS ) {
1464 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1465 "could not get connection handle - exiting\n",
1467 send_ldap_result( conn, op, res, "",
1468 res == LDAP_OTHER ? "SQL-backend error" : "",
1473 res = backsql_dn2id( bi, &e_id, dbh, ndn );
1474 if ( res != LDAP_SUCCESS ) {
1475 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1476 "could not lookup entry id\n", 0, 0, 0 );
1477 send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
1481 res = backsql_has_children( bi, dbh, ndn );
1483 case LDAP_COMPARE_TRUE:
1484 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1485 "entry \"%s\" has children\n", dn->bv_val, 0, 0 );
1486 send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
1487 NULL, "subtree delete not supported",
1491 case LDAP_COMPARE_FALSE:
1495 send_ldap_result( conn, op, res, NULL, NULL, NULL, NULL );
1499 oc = backsql_id2oc( bi, e_id.oc_id );
1501 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1502 "cannot determine objectclass of entry "
1503 "-- aborting\n", 0, 0, 0 );
1504 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
1505 "operation not permitted within namingContext",
1510 if ( oc->delete_proc == NULL ) {
1511 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1512 "delete procedure is not defined "
1513 "for this objectclass - aborting\n", 0, 0, 0 );
1514 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
1515 "operation not permitted within namingContext",
1520 SQLAllocStmt( dbh, &sth );
1521 if ( BACKSQL_IS_DEL( oc->expect_return ) ) {
1523 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1524 SQL_INTEGER, 0, 0, &rc, 0, 0 );
1529 SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT,
1530 SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
1532 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
1533 oc->delete_proc, 0, 0 );
1534 rc = SQLExecDirect( sth, oc->delete_proc, SQL_NTS );
1535 if ( rc != SQL_SUCCESS ) {
1536 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1537 "delete_proc execution failed\n", 0, 0, 0 );
1538 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1539 SQLFreeStmt( sth, SQL_DROP );
1540 send_ldap_result( conn, op, LDAP_OTHER, "",
1541 "SQL-backend error", NULL, NULL );
1544 #ifndef BACKSQL_REALLOC_STMT
1545 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1546 #else /* BACKSQL_REALLOC_STMT */
1547 SQLFreeStmt( sth, SQL_DROP );
1548 SQLAllocStmt( dbh, &sth );
1549 #endif /* BACKSQL_REALLOC_STMT */
1551 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
1552 0, 0, &e_id.id, 0, 0 );
1553 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
1554 if ( rc != SQL_SUCCESS ) {
1555 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1556 "failed to delete record from ldap_entries\n",
1558 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1559 SQLFreeStmt( sth, SQL_DROP );
1560 send_ldap_result( conn, op, LDAP_OTHER, "",
1561 "SQL-backend error", NULL, NULL );
1565 SQLFreeStmt( sth, SQL_DROP );
1568 * Commit only if all operations succeed
1570 * FIXME: backsql_add() does not fail if add operations
1571 * are not available for some attributes, or if
1572 * a multiple value add actually results in a replace,
1573 * or if a single operation on an attribute fails
1576 SQLTransact( SQL_NULL_HENV, dbh,
1577 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1579 send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
1580 Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
1584 #endif /* SLAPD_SQL */