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 build 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(
50 backsql_oc_map_rec *oc,
51 backsql_entryID *e_id,
52 Modifications *modlist )
54 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
59 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
60 "traversing modifications list\n", 0, 0, 0 );
62 #ifndef BACKSQL_REALLOC_STMT
63 SQLAllocStmt( dbh, &sth );
64 #endif /* BACKSQL_REALLOC_STMT */
66 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
67 AttributeDescription *ad;
68 backsql_at_map_rec *at = NULL;
69 struct berval *at_val;
72 /* first parameter no, parameter order */
74 /* procedure return code */
77 #ifdef BACKSQL_REALLOC_STMT
78 SQLAllocStmt( dbh, &sth );
79 #endif /* BACKSQL_REALLOC_STMT */
84 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
85 "modifying attribute '%s'\n",
86 ad->ad_cname.bv_val, 0, 0 );
88 if ( backsql_attr_skip( ad, c_mod->sm_bvalues ) ) {
92 at = backsql_ad2at( oc, ad );
94 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
95 "attribute provided is not registered "
96 "in objectClass '%s'\n",
97 ad->ad_cname.bv_val, 0, 0 );
99 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
100 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
101 rs->sr_text = "operation not permitted "
102 "within namingContext";
109 switch( c_mod->sm_op ) {
110 case LDAP_MOD_REPLACE: {
114 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
115 "replacing values for attribute '%s'\n",
116 at->ad->ad_cname.bv_val, 0, 0 );
118 if ( at->add_proc == NULL ) {
119 Debug( LDAP_DEBUG_TRACE,
120 "backsql_modify_internal(): "
121 "add procedure is not defined "
122 "for attribute '%s' "
123 "- unable to perform replacements\n",
124 at->ad->ad_cname.bv_val, 0, 0 );
126 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
127 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
128 rs->sr_text = "operation not permitted "
129 "within namingContext";
136 if ( at->delete_proc == NULL ) {
137 Debug( LDAP_DEBUG_TRACE,
138 "backsql_modify_internal(): "
139 "delete procedure is not defined "
140 "for attribute '%s' "
142 at->ad->ad_cname.bv_val, 0, 0 );
144 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
145 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
146 rs->sr_text = "operation not permitted "
147 "within namingContext";
155 rc = backsql_Prepare( dbh, &asth, at->query, 0 );
156 if ( rc != SQL_SUCCESS ) {
157 Debug( LDAP_DEBUG_TRACE,
158 "backsql_modify_internal(): "
159 "error preparing query\n", 0, 0, 0 );
160 backsql_PrintErrors( bi->db_env, dbh,
163 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
164 rs->sr_err = LDAP_OTHER;
165 rs->sr_text = "SQL-backend error";
172 rc = backsql_BindParamID( asth, 1, &e_id->keyval );
173 if ( rc != SQL_SUCCESS ) {
174 Debug( LDAP_DEBUG_TRACE,
175 "backsql_modify_internal(): "
176 "error binding key value parameter\n",
178 backsql_PrintErrors( bi->db_env, dbh,
180 SQLFreeStmt( asth, SQL_DROP );
182 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
183 rs->sr_err = LDAP_OTHER;
184 rs->sr_text = "SQL-backend error";
191 rc = SQLExecute( asth );
192 if ( !BACKSQL_SUCCESS( rc ) ) {
193 Debug( LDAP_DEBUG_TRACE,
194 "backsql_modify_internal(): "
195 "error executing attribute query\n",
197 backsql_PrintErrors( bi->db_env, dbh,
199 SQLFreeStmt( asth, SQL_DROP );
201 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
202 rs->sr_err = LDAP_OTHER;
203 rs->sr_text = "SQL-backend error";
210 backsql_BindRowAsStrings( asth, &row );
211 rc = SQLFetch( asth );
212 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
213 for ( i = 0; i < row.ncols; i++ ) {
214 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
216 SQLBindParameter(sth, 1,
224 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
225 SQLBindParameter( sth, pno + 1 + po,
227 SQL_C_ULONG, SQL_INTEGER,
228 0, 0, &e_id->keyval, 0, 0 );
231 * check for syntax needed here
232 * maybe need binary bind?
234 SQLBindParameter(sth, pno + 2 - po,
236 SQL_C_CHAR, SQL_CHAR,
238 strlen( row.cols[ i ] ), 0 );
240 Debug( LDAP_DEBUG_TRACE,
241 "backsql_modify_internal(): "
243 at->delete_proc, 0, 0 );
244 rc = SQLExecDirect( sth,
245 at->delete_proc, SQL_NTS );
246 if ( rc != SQL_SUCCESS ) {
247 Debug( LDAP_DEBUG_TRACE,
248 "backsql_modify_internal(): "
250 "execution failed\n",
252 backsql_PrintErrors( bi->db_env,
255 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
256 rs->sr_err = LDAP_OTHER;
257 rs->sr_text = "SQL-backend error";
261 #ifdef BACKSQL_REALLOC_STMT
262 SQLFreeStmt( sth, SQL_DROP );
263 SQLAllocStmt( dbh, &sth );
264 #endif /* BACKSQL_REALLOC_STMT */
267 backsql_FreeRow( &row );
268 SQLFreeStmt( asth, SQL_DROP );
272 * PASSTHROUGH - to add new attributes -- do NOT add break
275 case SLAP_MOD_SOFTADD:
277 if ( at->add_proc == NULL ) {
278 Debug( LDAP_DEBUG_TRACE,
279 "backsql_modify_internal(): "
280 "add procedure is not defined "
281 "for attribute '%s'\n",
282 at->ad->ad_cname.bv_val, 0, 0 );
284 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
285 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
286 rs->sr_text = "operation not permitted "
287 "within namingContext";
294 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
295 "adding new values for attribute '%s'\n",
296 at->ad->ad_cname.bv_val, 0, 0 );
297 for ( i = 0, at_val = c_mod->sm_bvalues;
298 at_val->bv_val != NULL;
300 if ( BACKSQL_IS_ADD( at->expect_return ) ) {
302 SQLBindParameter( sth, 1,
304 SQL_C_ULONG, SQL_INTEGER,
309 po = ( BACKSQL_IS_ADD( at->param_order ) ) > 0;
310 SQLBindParameter( sth, pno + 1 + po,
312 SQL_C_ULONG, SQL_INTEGER,
313 0, 0, &e_id->keyval, 0, 0 );
316 * check for syntax needed here
317 * maybe need binary bind?
319 SQLBindParameter( sth, pno + 2 - po,
321 SQL_C_CHAR, SQL_CHAR,
322 0, 0, at_val->bv_val,
325 Debug( LDAP_DEBUG_TRACE,
326 "backsql_modify_internal(): "
328 at->add_proc, 0, 0 );
329 rc = SQLExecDirect( sth, at->add_proc,
331 if ( rc != SQL_SUCCESS ) {
332 Debug( LDAP_DEBUG_TRACE,
333 "backsql_modify_internal(): "
334 "add_proc execution failed\n",
336 backsql_PrintErrors( bi->db_env,
339 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
340 rs->sr_err = LDAP_OTHER;
341 rs->sr_text = "SQL-backend error";
345 #ifdef BACKSQL_REALLOC_STMT
346 SQLFreeStmt( sth, SQL_DROP );
347 SQLAllocStmt( dbh, &sth );
348 #endif /* BACKSQL_REALLOC_STMT */
352 case LDAP_MOD_DELETE:
353 if ( at->delete_proc == NULL ) {
354 Debug( LDAP_DEBUG_TRACE,
355 "backsql_modify_internal(): "
356 "delete procedure is not defined "
357 "for attribute '%s'\n",
358 at->ad->ad_cname.bv_val, 0, 0 );
360 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
361 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
362 rs->sr_text = "operation not permitted "
363 "within namingContext";
370 if ( c_mod->sm_bvalues == NULL ) {
371 Debug( LDAP_DEBUG_TRACE,
372 "backsql_modify_internal(): "
373 "no values given to delete "
374 "for attribute '%s' "
375 "-- deleting all values\n",
376 at->ad->ad_cname.bv_val, 0, 0 );
380 Debug( LDAP_DEBUG_TRACE, "backsql_modify_internal(): "
381 "deleting values for attribute '%s'\n",
382 at->ad->ad_cname.bv_val, 0, 0 );
384 for ( i = 0, at_val = c_mod->sm_bvalues;
385 at_val->bv_val != NULL;
387 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
389 SQLBindParameter( sth, 1,
391 SQL_C_ULONG, SQL_INTEGER,
396 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
397 SQLBindParameter( sth, pno + 1 + po,
399 SQL_C_ULONG, SQL_INTEGER,
400 0, 0, &e_id->keyval, 0, 0 );
403 * check for syntax needed here
404 * maybe need binary bind?
406 SQLBindParameter( sth, pno + 2 - po,
407 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
408 0, 0, at_val->bv_val,
411 Debug( LDAP_DEBUG_TRACE,
412 "backsql_modify_internal(): "
414 at->delete_proc, 0, 0 );
415 rc = SQLExecDirect( sth, at->delete_proc,
417 if ( rc != SQL_SUCCESS ) {
418 Debug( LDAP_DEBUG_TRACE,
419 "backsql_modify_internal(): "
420 "delete_proc execution "
421 "failed\n", 0, 0, 0 );
422 backsql_PrintErrors( bi->db_env,
425 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
426 rs->sr_err = LDAP_OTHER;
427 rs->sr_text = "SQL-backend error";
431 #ifdef BACKSQL_REALLOC_STMT
432 SQLFreeStmt( sth, SQL_DROP );
433 SQLAllocStmt( dbh, &sth );
434 #endif /* BACKSQL_REALLOC_STMT */
438 #ifndef BACKSQL_REALLOC_STMT
439 SQLFreeStmt( sth, SQL_RESET_PARAMS );
440 #else /* BACKSQL_REALLOC_STMT */
441 SQLFreeStmt( sth, SQL_DROP );
442 #endif /* BACKSQL_REALLOC_STMT */
447 #ifndef BACKSQL_REALLOC_STMT
448 SQLFreeStmt( sth, SQL_DROP );
449 #endif /* BACKSQL_REALLOC_STMT */
452 * FIXME: should fail in case one change fails?
458 backsql_modify( Operation *op, SlapReply *rs )
460 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
462 backsql_oc_map_rec *oc = NULL;
463 backsql_entryID e_id;
467 * FIXME: in case part of the operation cannot be performed
468 * (missing mapping, SQL write fails or so) the entire operation
469 * should be rolled-back
471 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
472 op->o_req_ndn.bv_val, 0, 0 );
474 rs->sr_err = backsql_get_db_conn( op, &dbh );
475 if ( rs->sr_err != LDAP_SUCCESS ) {
476 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
477 "could not get connection handle - exiting\n",
480 * FIXME: we don't want to send back
481 * excessively detailed messages
483 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
484 ? "SQL-backend error" : NULL;
485 send_ldap_result( op, rs );
489 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn );
490 if ( rs->sr_err != LDAP_SUCCESS ) {
491 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
492 "could not lookup entry id\n", 0, 0, 0 );
493 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
494 ? "SQL-backend error" : NULL;
495 send_ldap_result( op, rs );
499 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
500 "modifying entry '%s' (id=%ld)\n",
501 e_id.dn.bv_val, e_id.id, 0 );
503 oc = backsql_id2oc( bi, e_id.oc_id );
505 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
506 "cannot determine objectclass of entry -- aborting\n",
509 * FIXME: should never occur, since the entry was built!!!
513 * FIXME: we don't want to send back
514 * excessively detailed messages
516 rs->sr_err = LDAP_OTHER;
517 rs->sr_text = "SQL-backend error";
518 send_ldap_result( op, rs );
523 e.e_name = op->o_req_dn;
524 e.e_nname = op->o_req_ndn;
525 if ( !acl_check_modlist( op, &e, op->oq_modify.rs_modlist ) ) {
526 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
529 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id,
530 op->oq_modify.rs_modlist );
533 if ( rs->sr_err == LDAP_SUCCESS ) {
535 * Commit only if all operations succeed
537 SQLTransact( SQL_NULL_HENV, dbh,
538 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
540 send_ldap_result( op, rs );
541 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
547 backsql_modrdn( Operation *op, SlapReply *rs )
549 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
553 backsql_entryID e_id, pe_id, new_pid;
554 backsql_oc_map_rec *oc = NULL;
555 struct berval p_dn, p_ndn,
556 *new_pdn = NULL, *new_npdn = NULL,
558 LDAPRDN *new_rdn = NULL;
559 LDAPRDN *old_rdn = NULL;
562 struct berval *newSuperior = op->oq_modrdn.rs_newSup;
564 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
565 "newrdn='%s', newSuperior='%s'\n",
566 op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val,
567 newSuperior ? newSuperior->bv_val : "(NULL)" );
568 rs->sr_err = backsql_get_db_conn( op, &dbh );
569 if ( rs->sr_err != LDAP_SUCCESS ) {
570 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
571 "could not get connection handle - exiting\n",
573 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
574 ? "SQL-backend error" : NULL;
575 send_ldap_result( op, rs );
579 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn );
580 if ( rs->sr_err != LDAP_SUCCESS ) {
581 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
582 "could not lookup entry id\n", 0, 0, 0 );
583 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
584 ? "SQL-backend error" : NULL;
585 send_ldap_result( op, rs );
589 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
592 if ( backsql_has_children( bi, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) {
593 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
594 "entry \"%s\" has children\n",
595 op->o_req_dn.bv_val, 0, 0 );
596 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
597 rs->sr_text = "subtree rename not supported";
598 send_ldap_result( op, rs );
602 dnParent( &op->o_req_dn, &p_dn );
603 dnParent( &op->o_req_ndn, &p_ndn );
606 * namingContext "" is not supported
608 if ( p_dn.bv_len == 0 ) {
609 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
610 "parent is \"\" - aborting\n", 0, 0, 0 );
611 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
612 rs->sr_text = "not allowed within namingContext";
613 send_ldap_result( op, rs );
618 * Check for children access to parent
623 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
624 NULL, ACL_WRITE, NULL ) ) {
625 Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
626 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
632 * namingContext "" is not supported
634 if ( newSuperior->bv_len == 0 ) {
635 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
636 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
637 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
638 rs->sr_text = "not allowed within namingContext";
639 send_ldap_result( op, rs );
643 new_pdn = newSuperior;
644 new_npdn = op->oq_modrdn.rs_nnewSup;
647 e.e_nname = *new_npdn;
650 * Check for children access to new parent
652 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
653 NULL, ACL_WRITE, NULL ) ) {
654 Debug( LDAP_DEBUG_TRACE, "no access to new parent\n",
656 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
665 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
666 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
667 "newSuperior is equal to old parent - ignored\n",
672 if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) {
673 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
674 "newSuperior is equal to entry being moved "
675 "- aborting\n", 0, 0, 0 );
676 rs->sr_err = LDAP_OTHER;
677 rs->sr_text = "newSuperior is equal to old DN";
678 send_ldap_result( op, rs );
682 build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn );
683 if ( dnNormalize2( NULL, &new_dn, &new_ndn ) != LDAP_SUCCESS ) {
684 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
685 "new dn is invalid ('%s') - aborting\n",
686 new_dn.bv_val, 0, 0 );
687 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
688 rs->sr_text = "new DN is invalid";
689 send_ldap_result( op, rs );
693 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): new entry dn is '%s'\n",
694 new_dn.bv_val, 0, 0 );
696 rs->sr_err = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
697 if ( rs->sr_err != LDAP_SUCCESS ) {
698 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
699 "could not lookup old parent entry id\n", 0, 0, 0 );
700 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
701 ? "SQL-backend error" : NULL;
702 send_ldap_result( op, rs );
706 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
707 "old parent entry id is %ld\n", pe_id.id, 0, 0 );
709 rs->sr_err = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
710 if ( rs->sr_err != LDAP_SUCCESS ) {
711 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
712 "could not lookup new parent entry id\n", 0, 0, 0 );
713 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
714 ? "SQL-backend error" : NULL;
715 send_ldap_result( op, rs );
719 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
720 "new parent entry id is %ld\n", new_pid.id, 0, 0 );
723 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
724 "executing delentry_query\n", 0, 0, 0 );
725 SQLAllocStmt( dbh, &sth );
726 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
727 0, 0, &e_id.id, 0, 0 );
728 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
729 if ( rc != SQL_SUCCESS ) {
730 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
731 "failed to delete record from ldap_entries\n",
733 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
734 rs->sr_err = LDAP_OTHER;
735 rs->sr_text = "SQL-backend error";
736 send_ldap_result( op, rs );
740 SQLFreeStmt( sth, SQL_RESET_PARAMS );
742 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
743 "executing insentry_query\n", 0, 0, 0 );
744 backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
745 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
746 0, 0, &e_id.oc_id, 0, 0 );
747 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
748 0, 0, &new_pid.id, 0, 0 );
749 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
750 0, 0, &e_id.keyval, 0, 0 );
751 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
752 if ( rc != SQL_SUCCESS ) {
753 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
754 "could not insert ldap_entries record\n", 0, 0, 0 );
755 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
756 rs->sr_err = LDAP_OTHER;
757 rs->sr_text = "SQL-backend error";
758 send_ldap_result( op, rs );
763 * Get attribute type and attribute value of our new rdn,
764 * we will need to add that to our new entry
766 if ( ldap_bv2rdn( &op->oq_modrdn.rs_newrdn, &new_rdn,
767 (char **)&rs->sr_text,
768 LDAP_DN_FORMAT_LDAP ) ) {
770 LDAP_LOG ( OPERATION, ERR,
771 "backsql_modrdn: can't figure out "
772 "type(s)/values(s) of newrdn\n",
775 Debug( LDAP_DEBUG_TRACE,
776 "backsql_modrdn: can't figure out "
777 "type(s)/values(s) of newrdn\n",
780 rs->sr_err = LDAP_INVALID_DN_SYNTAX;
785 LDAP_LOG ( OPERATION, RESULTS,
786 "backsql_modrdn: new_rdn_type=\"%s\", "
787 "new_rdn_val=\"%s\"\n",
788 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
789 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
791 Debug( LDAP_DEBUG_TRACE,
792 "backsql_modrdn: new_rdn_type=\"%s\", "
793 "new_rdn_val=\"%s\"\n",
794 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
795 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
798 if ( op->oq_modrdn.rs_deleteoldrdn ) {
799 if ( ldap_bv2rdn( &op->o_req_dn, &old_rdn,
800 (char **)&rs->sr_text,
801 LDAP_DN_FORMAT_LDAP ) ) {
803 LDAP_LOG ( OPERATION, ERR,
804 "backsql_modrdn: can't figure out "
805 "type(s)/values(s) of old_rdn\n",
808 Debug( LDAP_DEBUG_TRACE,
809 "backsql_modrdn: can't figure out "
810 "the old_rdn type(s)/value(s)\n",
813 rs->sr_err = LDAP_OTHER;
820 rs->sr_err = slap_modrdn2mods( op, rs, &e, old_rdn, new_rdn, &mod );
821 if ( rs->sr_err != LDAP_SUCCESS ) {
825 if ( !acl_check_modlist( op, &e, mod )) {
826 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
830 oc = backsql_id2oc( bi, e_id.oc_id );
831 rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, mod );
833 if ( rs->sr_err == LDAP_SUCCESS ) {
836 * Commit only if all operations succeed
838 SQLTransact( SQL_NULL_HENV, dbh,
839 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
843 SQLFreeStmt( sth, SQL_DROP );
845 if ( new_dn.bv_val ) {
846 ch_free( new_dn.bv_val );
849 if ( new_ndn.bv_val ) {
850 ch_free( new_ndn.bv_val );
853 /* LDAP v2 supporting correct attribute handling. */
854 if ( new_rdn != NULL ) {
855 ldap_rdnfree( new_rdn );
857 if ( old_rdn != NULL ) {
858 ldap_rdnfree( old_rdn );
862 for (; mod; mod=tmp ) {
868 send_ldap_result( op, rs );
870 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
875 backsql_add( Operation *op, SlapReply *rs )
877 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
880 unsigned long new_keyval = 0;
883 backsql_oc_map_rec *oc = NULL;
884 backsql_at_map_rec *at_rec = NULL;
885 backsql_entryID e_id, parent_id;
888 struct berval *at_val;
890 /* first parameter #, parameter order */
891 SQLUSMALLINT pno, po;
892 /* procedure return code */
895 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry '%s'\n",
896 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
899 if ( global_schemacheck ) {
900 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
902 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e,
904 &rs->sr_text, textbuf, sizeof( textbuf ) );
905 if ( rs->sr_err != LDAP_SUCCESS ) {
906 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
907 "entry failed schema check -- aborting\n",
909 send_ldap_result( op, rs );
914 /* search structural objectClass */
915 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
916 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
921 /* there must exist */
922 assert( at != NULL );
924 /* I guess we should play with sub/supertypes to find a suitable oc */
925 oc = backsql_name2oc( bi, &at->a_vals[0] );
928 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
929 "cannot determine objectclass of entry -- aborting\n",
931 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
932 rs->sr_text = "operation not permitted within namingContext";
933 send_ldap_result( op, rs );
937 if ( oc->create_proc == NULL ) {
938 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
939 "create procedure is not defined for this objectclass "
940 "- aborting\n", 0, 0, 0 );
941 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
942 rs->sr_text = "operation not permitted within namingContext";
943 send_ldap_result( op, rs );
946 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
947 && oc->create_keyval == NULL ) {
948 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
949 "create procedure needs select procedure, "
950 "but none is defined - aborting\n", 0, 0, 0 );
951 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
952 rs->sr_text = "operation not permitted within namingContext";
953 send_ldap_result( op, rs );
957 rs->sr_err = backsql_get_db_conn( op, &dbh );
958 if ( prc != LDAP_SUCCESS ) {
959 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
960 "could not get connection handle - exiting\n",
962 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
963 ? "SQL-backend error" : NULL,
964 send_ldap_result( op, rs );
969 * Check if entry exists
971 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->oq_add.rs_e->e_name );
972 if ( rs->sr_err == LDAP_SUCCESS ) {
973 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
974 "entry '%s' exists\n",
975 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
976 rs->sr_err = LDAP_ALREADY_EXISTS;
977 send_ldap_result( op, rs );
982 * Check if parent exists
984 dnParent( &op->oq_add.rs_e->e_name, &pdn );
985 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &pdn );
986 if ( rs->sr_err != LDAP_SUCCESS ) {
987 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
988 "could not lookup parent entry for new record '%s'\n",
991 if ( rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
992 send_ldap_result( op, rs );
1001 char *matched = NULL;
1004 dnParent( &dn, &pdn );
1007 * Empty DN ("") defaults to LDAP_SUCCESS
1009 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &pdn );
1010 switch ( rs->sr_err ) {
1011 case LDAP_NO_SUCH_OBJECT:
1012 if ( pdn.bv_len > 0 ) {
1015 /* fail over to next case */
1018 matched = pdn.bv_val;
1019 /* fail over to next case */
1022 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1023 rs->sr_matched = matched;
1024 send_ldap_result( op, rs );
1031 * create_proc is executed; if expect_return is set, then
1032 * an output parameter is bound, which should contain
1033 * the id of the added row; otherwise the procedure
1034 * is expected to return the id as the first column of a select
1039 dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
1040 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1041 NULL, ACL_WRITE, NULL ) ) {
1042 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1043 send_ldap_result( op, rs );
1047 rc = SQLAllocStmt( dbh, &sth );
1048 if ( rc != SQL_SUCCESS ) {
1049 rs->sr_err = LDAP_OTHER;
1050 rs->sr_text = "SQL-backend error";
1051 send_ldap_result( op, rs );
1055 if ( BACKSQL_IS_ADD( oc->expect_return ) ) {
1056 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1057 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1060 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s'\n",
1061 oc->create_proc, 0, 0 );
1062 rc = SQLExecDirect( sth, oc->create_proc, SQL_NTS );
1063 if ( rc != SQL_SUCCESS ) {
1064 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1065 "create_proc execution failed\n", 0, 0, 0 );
1066 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1067 SQLFreeStmt( sth, SQL_DROP );
1068 rs->sr_err = LDAP_OTHER;
1069 rs->sr_text = "SQL-backend error";
1070 send_ldap_result( op, rs );
1074 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1077 if ( !BACKSQL_IS_ADD( oc->expect_return ) ) {
1079 SQLINTEGER value_len;
1081 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1082 #ifndef BACKSQL_REALLOC_STMT
1083 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1084 #else /* BACKSQL_REALLOC_STMT */
1085 SQLFreeStmt( sth, SQL_DROP );
1086 rc = SQLAllocStmt( dbh, &sth );
1087 if ( rc != SQL_SUCCESS ) {
1088 rs->sr_err = LDAP_OTHER;
1089 rs->sr_text = "SQL-backend error";
1090 send_ldap_result( op, rs );
1093 #endif /* BACKSQL_REALLOC_STMT */
1095 rc = SQLExecDirect( sth, oc->create_keyval, SQL_NTS );
1096 if ( rc != SQL_SUCCESS ) {
1097 rs->sr_err = LDAP_OTHER;
1098 rs->sr_text = "SQL-backend error";
1099 send_ldap_result( op, rs );
1105 * the query to know the id of the inserted entry
1106 * must be embedded in the create procedure
1108 rc = SQLNumResultCols( sth, &ncols );
1109 if ( rc != SQL_SUCCESS ) {
1110 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1111 "create_proc result evaluation failed\n",
1113 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1114 SQLFreeStmt( sth, SQL_DROP );
1115 rs->sr_err = LDAP_OTHER;
1116 rs->sr_text = "SQL-backend error";
1117 send_ldap_result( op, rs );
1120 } else if ( ncols != 1 ) {
1121 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1122 "create_proc result is bogus (ncols=%d)\n",
1124 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1125 SQLFreeStmt( sth, SQL_DROP );
1126 rs->sr_err = LDAP_OTHER;
1127 rs->sr_text = "SQL-backend error";
1128 send_ldap_result( op, rs );
1134 SQLCHAR colname[ 64 ];
1135 SQLSMALLINT name_len, col_type, col_scale, col_null;
1139 * FIXME: check whether col_type is compatible,
1140 * if it can be null and so on ...
1142 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1144 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1145 &name_len, &col_type,
1146 &col_prec, &col_scale, &col_null );
1150 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1151 (SQLPOINTER)&new_keyval,
1152 (SQLINTEGER)sizeof( new_keyval ),
1155 rc = SQLFetch( sth );
1157 if ( value_len <= 0 ) {
1158 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1159 "create_proc result is empty?\n",
1161 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1162 SQLFreeStmt( sth, SQL_DROP );
1163 rs->sr_err = LDAP_OTHER;
1164 rs->sr_text = "SQL-backend error";
1165 send_ldap_result( op, rs );
1170 #ifndef BACKSQL_REALLOC_STMT
1171 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1172 #else /* BACKSQL_REALLOC_STMT */
1173 SQLFreeStmt( sth, SQL_DROP );
1174 #endif /* BACKSQL_REALLOC_STMT */
1176 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1177 "create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
1179 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
1180 SQLUSMALLINT currpos;
1182 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1183 "adding attribute '%s'\n",
1184 at->a_desc->ad_cname.bv_val, 0, 0 );
1188 * - the first occurrence of objectClass, which is used
1189 * to determine how to bulid the SQL entry (FIXME ?!?)
1190 * - operational attributes
1191 * empty attributes (FIXME ?!?)
1193 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1197 at_rec = backsql_ad2at( oc, at->a_desc );
1199 if ( at_rec == NULL ) {
1200 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1201 "attribute '%s' is not registered "
1202 "in objectclass '%s'\n",
1203 at->a_desc->ad_cname.bv_val,
1204 BACKSQL_OC_NAME( oc ), 0 );
1206 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1207 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1208 rs->sr_text = "operation not permitted "
1209 "within namingContext";
1210 send_ldap_result( op, rs );
1217 if ( at_rec->add_proc == NULL ) {
1218 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1219 "add procedure is not defined "
1220 "for attribute '%s'\n",
1221 at->a_desc->ad_cname.bv_val, 0, 0 );
1223 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1224 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1225 rs->sr_text = "operation not permitted "
1226 "within namingContext";
1227 send_ldap_result( op, rs );
1234 #ifdef BACKSQL_REALLOC_STMT
1235 rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
1236 if ( rc != SQL_SUCCESS ) {
1238 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1239 rs->sr_err = LDAP_OTHER;
1240 rs->sr_text = "SQL-backend error";
1241 send_ldap_result( op, rs );
1247 #endif /* BACKSQL_REALLOC_STMT */
1249 if ( BACKSQL_IS_ADD( at_rec->expect_return ) ) {
1251 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
1252 SQL_C_ULONG, SQL_INTEGER,
1258 po = ( BACKSQL_IS_ADD( at_rec->param_order ) ) > 0;
1259 currpos = pno + 1 + po;
1260 SQLBindParameter( sth, currpos,
1261 SQL_PARAM_INPUT, SQL_C_ULONG,
1262 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1263 currpos = pno + 2 - po;
1265 for ( i = 0, at_val = &at->a_vals[ i ];
1266 at_val->bv_val != NULL;
1267 i++, at_val = &at->a_vals[ i ] ) {
1270 * Do not deal with the objectClass that is used
1271 * to build the entry
1273 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1274 if ( bvmatch( at_val, &oc->oc->soc_cname ) ) {
1280 * check for syntax needed here
1281 * maybe need binary bind?
1284 backsql_BindParamStr( sth, currpos,
1285 at_val->bv_val, at_val->bv_len + 1 );
1286 #ifdef SECURITY_PARANOID
1287 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1288 "executing '%s', id=%ld\n",
1289 at_rec->add_proc, new_keyval, 0 );
1291 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1292 "executing '%s' with val='%s', id=%ld\n",
1293 at_rec->add_proc, at_val->bv_val, new_keyval );
1295 #ifndef BACKSQL_REALLOC_STMT
1296 rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
1297 #else /* BACKSQL_REALLOC_STMT */
1298 rc = SQLExecute( sth );
1299 #endif /* BACKSQL_REALLOC_STMT */
1300 if ( rc != SQL_SUCCESS ) {
1301 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1302 "add_proc execution failed\n",
1304 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1306 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
1307 rs->sr_err = LDAP_OTHER;
1308 rs->sr_text = "SQL-backend error";
1309 send_ldap_result( op, rs );
1314 #ifndef BACKSQL_REALLOC_STMT
1315 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1316 #else /* BACKSQL_REALLOC_STMT */
1317 SQLFreeStmt( sth, SQL_DROP );
1318 #endif /* BACKSQL_REALLOC_STMT */
1321 #ifdef BACKSQL_REALLOC_STMT
1322 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1323 if ( rc != SQL_SUCCESS ) {
1324 rs->sr_err = LDAP_OTHER;
1325 rs->sr_text = "SQL-backend error";
1326 send_ldap_result( op, rs );
1329 #endif /* BACKSQL_REALLOC_STMT */
1331 backsql_BindParamStr( sth, 1, op->oq_add.rs_e->e_name.bv_val,
1332 BACKSQL_MAX_DN_LEN );
1333 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1334 0, 0, &oc->id, 0, 0 );
1335 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1336 0, 0, &parent_id.id, 0, 0 );
1337 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1338 0, 0, &new_keyval, 0, 0 );
1340 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s' for dn '%s'\n",
1341 bi->insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 );
1342 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, parent_id=%ld, "
1343 "keyval=%ld\n", oc->id, parent_id.id, new_keyval );
1344 #ifndef BACKSQL_REALLOC_STMT
1345 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
1346 #else /* BACKSQL_REALLOC_STMT */
1347 rc = SQLExecute( sth );
1348 #endif /* BACKSQL_REALLOC_STMT */
1349 if ( rc != SQL_SUCCESS ) {
1350 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1351 "could not insert ldap_entries record\n", 0, 0, 0 );
1352 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1355 * execute delete_proc to delete data added !!!
1357 SQLFreeStmt( sth, SQL_DROP );
1358 rs->sr_err = LDAP_OTHER;
1359 rs->sr_text = "SQL-backend error";
1360 send_ldap_result( op, rs );
1364 SQLFreeStmt( sth, SQL_DROP );
1367 * Commit only if all operations succeed
1369 SQLTransact( SQL_NULL_HENV, dbh,
1370 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1373 * FIXME: NOOP does not work for add -- it works for all
1374 * the other operations, and I don't get the reason :(
1377 send_ldap_result( op, rs );
1383 backsql_delete( Operation *op, SlapReply *rs )
1385 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
1389 backsql_oc_map_rec *oc = NULL;
1390 backsql_entryID e_id;
1392 /* first parameter no */
1395 Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
1396 op->o_req_ndn.bv_val, 0, 0 );
1398 dnParent( &op->o_req_dn, &e.e_name );
1399 dnParent( &op->o_req_ndn, &e.e_nname );
1402 /* check parent for "children" acl */
1403 if ( !access_allowed( op, &e, slap_schema.si_ad_children,
1404 NULL, ACL_WRITE, NULL ) ) {
1405 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1406 "no write access to parent\n",
1408 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1409 send_ldap_result( op, rs );
1414 rs->sr_err = backsql_get_db_conn( op, &dbh );
1415 if ( rs->sr_err != LDAP_SUCCESS ) {
1416 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1417 "could not get connection handle - exiting\n",
1419 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1420 ? "SQL-backend error" : NULL,
1421 send_ldap_result( op, rs );
1425 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn );
1426 if ( rs->sr_err != LDAP_SUCCESS ) {
1427 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1428 "could not lookup entry id\n", 0, 0, 0 );
1429 send_ldap_result( op, rs );
1433 rs->sr_err = backsql_has_children( bi, dbh, &op->o_req_ndn );
1434 switch ( rs->sr_err ) {
1435 case LDAP_COMPARE_TRUE:
1436 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1437 "entry \"%s\" has children\n",
1438 op->o_req_dn.bv_val, 0, 0 );
1439 rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
1440 rs->sr_text = "subtree delete not supported";
1441 send_ldap_result( op, rs );
1444 case LDAP_COMPARE_FALSE:
1448 send_ldap_result( op, rs );
1452 oc = backsql_id2oc( bi, e_id.oc_id );
1454 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1455 "cannot determine objectclass of entry -- aborting\n",
1457 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1458 rs->sr_text = "operation not permitted within namingContext";
1459 send_ldap_result( op, rs );
1463 if ( oc->delete_proc == NULL ) {
1464 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1465 "delete procedure is not defined "
1466 "for this objectclass - aborting\n", 0, 0, 0 );
1467 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1468 rs->sr_text = "operation not permitted within namingContext";
1469 send_ldap_result( op, rs );
1473 SQLAllocStmt( dbh, &sth );
1474 if ( BACKSQL_IS_DEL( oc->expect_return ) ) {
1476 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1477 SQL_INTEGER, 0, 0, &rc, 0, 0 );
1482 SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT,
1483 SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
1485 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
1486 oc->delete_proc, 0, 0 );
1487 rc = SQLExecDirect( sth, oc->delete_proc, SQL_NTS );
1488 if ( rc != SQL_SUCCESS ) {
1489 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1490 "delete_proc execution failed\n", 0, 0, 0 );
1491 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1492 SQLFreeStmt( sth, SQL_DROP );
1493 rs->sr_err = LDAP_OTHER;
1494 rs->sr_text = "SQL-backend error";
1495 send_ldap_result( op, rs );
1498 #ifndef BACKSQL_REALLOC_STMT
1499 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1500 #else /* BACKSQL_REALLOC_STMT */
1501 SQLFreeStmt( sth, SQL_DROP );
1502 SQLAllocStmt( dbh, &sth );
1503 #endif /* BACKSQL_REALLOC_STMT */
1505 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
1506 0, 0, &e_id.id, 0, 0 );
1507 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
1508 if ( rc != SQL_SUCCESS ) {
1509 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1510 "failed to delete record from ldap_entries\n",
1512 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1513 SQLFreeStmt( sth, SQL_DROP );
1514 rs->sr_err = LDAP_OTHER;
1515 rs->sr_text = "SQL-backend error";
1516 send_ldap_result( op, rs );
1520 SQLFreeStmt( sth, SQL_DROP );
1523 * Commit only if all operations succeed
1525 * FIXME: backsql_add() does not fail if add operations
1526 * are not available for some attributes, or if
1527 * a multiple value add actually results in a replace,
1528 * or if a single operation on an attribute fails
1531 SQLTransact( SQL_NULL_HENV, dbh,
1532 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
1534 send_ldap_result( op, rs );
1535 Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
1539 #endif /* SLAPD_SQL */