2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2010 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * Portions Copyright 2004 Mark Adamson.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by Dmitry Kovalev for inclusion
20 * by OpenLDAP Software. Additional significant contributors include
21 * Pierangelo Masarati and Mark Adamson.
28 #include <sys/types.h>
29 #include "ac/string.h"
32 #include "proto-sql.h"
34 #ifdef BACKSQL_SYNCPROV
36 #endif /* BACKSQL_SYNCPROV */
40 * - null values (e.g. delete modification)
41 * - single occurrence of objectClass, because it is already used
42 * to determine how to build the SQL entry
43 * - operational attributes
46 #define backsql_opattr_skip(ad) \
47 (is_at_operational( (ad)->ad_type ) && (ad) != slap_schema.si_ad_ref )
48 #define backsql_attr_skip(ad, vals) \
50 ( (ad) == slap_schema.si_ad_objectClass \
51 && (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
52 || backsql_opattr_skip( (ad) ) \
53 || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
57 backsql_modify_delete_all_values(
61 backsql_entryID *e_id,
62 backsql_at_map_rec *at )
64 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
66 SQLHSTMT asth = SQL_NULL_HSTMT;
70 if ( at->bam_delete_proc == NULL ) {
71 Debug( LDAP_DEBUG_TRACE,
72 " backsql_modify_delete_all_values(): "
73 "missing attribute value delete procedure "
75 at->bam_ad->ad_cname.bv_val, 0, 0 );
76 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
77 rs->sr_text = "SQL-backend error";
78 return rs->sr_err = LDAP_OTHER;
84 rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
85 if ( rc != SQL_SUCCESS ) {
86 Debug( LDAP_DEBUG_TRACE,
87 " backsql_modify_delete_all_values(): "
88 "error preparing attribute value select query "
90 at->bam_query, 0, 0 );
91 backsql_PrintErrors( bi->sql_db_env, dbh,
94 rs->sr_text = "SQL-backend error";
95 return rs->sr_err = LDAP_OTHER;
98 rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
99 if ( rc != SQL_SUCCESS ) {
100 Debug( LDAP_DEBUG_TRACE,
101 " backsql_modify_delete_all_values(): "
102 "error binding key value parameter "
103 "to attribute value select query\n",
105 backsql_PrintErrors( bi->sql_db_env, dbh,
107 SQLFreeStmt( asth, SQL_DROP );
109 rs->sr_text = "SQL-backend error";
110 return rs->sr_err = LDAP_OTHER;
113 rc = SQLExecute( asth );
114 if ( !BACKSQL_SUCCESS( rc ) ) {
115 Debug( LDAP_DEBUG_TRACE,
116 " backsql_modify_delete_all_values(): "
117 "error executing attribute value select query\n",
119 backsql_PrintErrors( bi->sql_db_env, dbh,
121 SQLFreeStmt( asth, SQL_DROP );
123 rs->sr_text = "SQL-backend error";
124 return rs->sr_err = LDAP_OTHER;
127 backsql_BindRowAsStrings_x( asth, &row, op->o_tmpmemctx );
128 for ( rc = SQLFetch( asth );
129 BACKSQL_SUCCESS( rc );
130 rc = SQLFetch( asth ) )
133 /* first parameter no, parameter order */
134 SQLUSMALLINT pno = 0,
136 /* procedure return code */
137 int prc = LDAP_SUCCESS;
139 for ( i = 0; i < row.ncols; i++ ) {
140 SQLHSTMT sth = SQL_NULL_HSTMT;
143 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
144 if ( rc != SQL_SUCCESS ) {
145 Debug( LDAP_DEBUG_TRACE,
146 " backsql_modify_delete_all_values(): "
147 "error preparing attribute value "
150 at->bam_delete_proc, 0, 0 );
151 backsql_PrintErrors( bi->sql_db_env, dbh,
154 rs->sr_text = "SQL-backend error";
155 rs->sr_err = LDAP_OTHER;
159 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
161 rc = backsql_BindParamInt( sth, 1,
162 SQL_PARAM_OUTPUT, &prc );
163 if ( rc != SQL_SUCCESS ) {
164 Debug( LDAP_DEBUG_TRACE,
165 " backsql_modify_delete_all_values(): "
166 "error binding output parameter for %s[%d]\n",
167 at->bam_ad->ad_cname.bv_val, i, 0 );
168 backsql_PrintErrors( bi->sql_db_env, dbh,
170 SQLFreeStmt( sth, SQL_DROP );
172 rs->sr_text = "SQL-backend error";
173 rs->sr_err = LDAP_OTHER;
177 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
178 rc = backsql_BindParamID( sth, pno + 1 + po,
179 SQL_PARAM_INPUT, &e_id->eid_keyval );
180 if ( rc != SQL_SUCCESS ) {
181 Debug( LDAP_DEBUG_TRACE,
182 " backsql_modify_delete_all_values(): "
183 "error binding keyval parameter for %s[%d]\n",
184 at->bam_ad->ad_cname.bv_val, i, 0 );
185 backsql_PrintErrors( bi->sql_db_env, dbh,
187 SQLFreeStmt( sth, SQL_DROP );
189 rs->sr_text = "SQL-backend error";
190 rs->sr_err = LDAP_OTHER;
194 Debug( LDAP_DEBUG_TRACE,
195 " backsql_modify_delete_all_values() "
196 "arg(%d)=" BACKSQL_IDFMT "\n",
198 BACKSQL_IDARG(e_id->eid_keyval), 0 );
201 * check for syntax needed here
202 * maybe need binary bind?
204 col_len = strlen( row.cols[ i ] );
205 rc = backsql_BindParamStr( sth, pno + 2 - po,
206 SQL_PARAM_INPUT, row.cols[ i ], col_len );
207 if ( rc != SQL_SUCCESS ) {
208 Debug( LDAP_DEBUG_TRACE,
209 " backsql_modify_delete_all_values(): "
210 "error binding value parameter for %s[%d]\n",
211 at->bam_ad->ad_cname.bv_val, i, 0 );
212 backsql_PrintErrors( bi->sql_db_env, dbh,
214 SQLFreeStmt( sth, SQL_DROP );
216 rs->sr_text = "SQL-backend error";
217 rs->sr_err = LDAP_OTHER;
221 Debug( LDAP_DEBUG_TRACE,
222 " backsql_modify_delete_all_values(): "
223 "arg(%d)=%s; executing \"%s\"\n",
224 pno + 2 - po, row.cols[ i ],
225 at->bam_delete_proc );
226 rc = SQLExecute( sth );
227 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
228 rs->sr_err = LDAP_SUCCESS;
231 Debug( LDAP_DEBUG_TRACE,
232 " backsql_modify_delete_all_values(): "
234 "execution failed (rc=%d, prc=%d)\n",
236 if ( prc != LDAP_SUCCESS ) {
237 /* SQL procedure executed fine
238 * but returned an error */
239 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
242 backsql_PrintErrors( bi->sql_db_env, dbh,
244 rs->sr_err = LDAP_OTHER;
246 rs->sr_text = op->o_req_dn.bv_val;
247 SQLFreeStmt( sth, SQL_DROP );
250 SQLFreeStmt( sth, SQL_DROP );
254 rs->sr_err = LDAP_SUCCESS;
257 backsql_FreeRow_x( &row, op->o_tmpmemctx );
258 SQLFreeStmt( asth, SQL_DROP );
264 backsql_modify_internal(
268 backsql_oc_map_rec *oc,
269 backsql_entryID *e_id,
270 Modifications *modlist )
272 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
276 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
277 "traversing modifications list\n", 0, 0, 0 );
279 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
280 AttributeDescription *ad;
282 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
286 /* NOTE: some day we'll have to pass
287 * the normalized values as well */
288 BerVarray sm_nvalues;
290 backsql_at_map_rec *at = NULL;
291 struct berval *at_val;
294 ad = ml->sml_mod.sm_desc;
295 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
296 sm_values = ml->sml_mod.sm_values;
298 sm_nvalues = ml->sml_mod.sm_nvalues;
301 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
302 "modifying attribute \"%s\" (%s) according to "
303 "mappings for objectClass \"%s\"\n",
304 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
306 if ( backsql_attr_skip( ad, sm_values ) ) {
310 at = backsql_ad2at( oc, ad );
312 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
313 "attribute \"%s\" is not registered "
314 "in objectClass \"%s\"\n",
315 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
317 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
318 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
319 rs->sr_text = "operation not permitted "
320 "within namingContext";
328 case LDAP_MOD_REPLACE: {
329 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
330 "replacing values for attribute \"%s\"\n",
331 at->bam_ad->ad_cname.bv_val, 0, 0 );
333 if ( at->bam_add_proc == NULL ) {
334 Debug( LDAP_DEBUG_TRACE,
335 " backsql_modify_internal(): "
336 "add procedure is not defined "
337 "for attribute \"%s\" "
338 "- unable to perform replacements\n",
339 at->bam_ad->ad_cname.bv_val, 0, 0 );
341 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
342 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
343 rs->sr_text = "operation not permitted "
344 "within namingContext";
351 if ( at->bam_delete_proc == NULL ) {
352 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
353 Debug( LDAP_DEBUG_TRACE,
354 " backsql_modify_internal(): "
355 "delete procedure is not defined "
356 "for attribute \"%s\"\n",
357 at->bam_ad->ad_cname.bv_val, 0, 0 );
359 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
360 rs->sr_text = "operation not permitted "
361 "within namingContext";
365 Debug( LDAP_DEBUG_TRACE,
366 " backsql_modify_internal(): "
367 "delete procedure is not defined "
368 "for attribute \"%s\" "
370 at->bam_ad->ad_cname.bv_val, 0, 0 );
376 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
377 if ( rs->sr_err != LDAP_SUCCESS ) {
381 /* LDAP_MOD_DELETE gets here if all values must be deleted */
382 if ( sm_op == LDAP_MOD_DELETE ) {
388 * PASSTHROUGH - to add new attributes -- do NOT add break
391 /* case SLAP_MOD_SOFTADD: */
393 if ( at->bam_add_proc == NULL ) {
394 Debug( LDAP_DEBUG_TRACE,
395 " backsql_modify_internal(): "
396 "add procedure is not defined "
397 "for attribute \"%s\"\n",
398 at->bam_ad->ad_cname.bv_val, 0, 0 );
400 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
401 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
402 rs->sr_text = "operation not permitted "
403 "within namingContext";
410 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
411 "adding new values for attribute \"%s\"\n",
412 at->bam_ad->ad_cname.bv_val, 0, 0 );
414 /* can't add a NULL val array */
415 assert( sm_values != NULL );
417 for ( i = 0, at_val = sm_values;
418 !BER_BVISNULL( at_val );
421 SQLHSTMT sth = SQL_NULL_HSTMT;
422 /* first parameter position, parameter order */
423 SQLUSMALLINT pno = 0,
425 /* procedure return code */
426 int prc = LDAP_SUCCESS;
428 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
429 if ( rc != SQL_SUCCESS ) {
430 Debug( LDAP_DEBUG_TRACE,
431 " backsql_modify_internal(): "
432 "error preparing add query\n",
434 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
436 rs->sr_err = LDAP_OTHER;
437 rs->sr_text = "SQL-backend error";
441 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
443 rc = backsql_BindParamInt( sth, 1,
444 SQL_PARAM_OUTPUT, &prc );
445 if ( rc != SQL_SUCCESS ) {
446 Debug( LDAP_DEBUG_TRACE,
447 " backsql_modify_internal(): "
448 "error binding output parameter for %s[%d]\n",
449 at->bam_ad->ad_cname.bv_val, i, 0 );
450 backsql_PrintErrors( bi->sql_db_env, dbh,
452 SQLFreeStmt( sth, SQL_DROP );
454 rs->sr_text = "SQL-backend error";
455 rs->sr_err = LDAP_OTHER;
459 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
460 rc = backsql_BindParamID( sth, pno + 1 + po,
461 SQL_PARAM_INPUT, &e_id->eid_keyval );
462 if ( rc != SQL_SUCCESS ) {
463 Debug( LDAP_DEBUG_TRACE,
464 " backsql_modify_internal(): "
465 "error binding keyval parameter for %s[%d]\n",
466 at->bam_ad->ad_cname.bv_val, i, 0 );
467 backsql_PrintErrors( bi->sql_db_env, dbh,
469 SQLFreeStmt( sth, SQL_DROP );
471 rs->sr_text = "SQL-backend error";
472 rs->sr_err = LDAP_OTHER;
476 Debug( LDAP_DEBUG_TRACE,
477 " backsql_modify_internal(): "
478 "arg(%d)=" BACKSQL_IDFMT "\n",
480 BACKSQL_IDARG(e_id->eid_keyval), 0 );
483 * check for syntax needed here
484 * maybe need binary bind?
486 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
487 SQL_PARAM_INPUT, at_val );
488 if ( rc != SQL_SUCCESS ) {
489 Debug( LDAP_DEBUG_TRACE,
490 " backsql_modify_internal(): "
491 "error binding value parameter for %s[%d]\n",
492 at->bam_ad->ad_cname.bv_val, i, 0 );
493 backsql_PrintErrors( bi->sql_db_env, dbh,
495 SQLFreeStmt( sth, SQL_DROP );
497 rs->sr_text = "SQL-backend error";
498 rs->sr_err = LDAP_OTHER;
501 Debug( LDAP_DEBUG_TRACE,
502 " backsql_modify_internal(): "
503 "arg(%d)=\"%s\"; executing \"%s\"\n",
504 pno + 2 - po, at_val->bv_val,
507 rc = SQLExecute( sth );
508 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
509 rs->sr_err = LDAP_SUCCESS;
512 Debug( LDAP_DEBUG_TRACE,
513 " backsql_modify_internal(): "
514 "add_proc execution failed "
517 if ( prc != LDAP_SUCCESS ) {
518 /* SQL procedure executed fine
519 * but returned an error */
520 SQLFreeStmt( sth, SQL_DROP );
522 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
523 rs->sr_text = at->bam_ad->ad_cname.bv_val;
527 backsql_PrintErrors( bi->sql_db_env, dbh,
529 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
531 SQLFreeStmt( sth, SQL_DROP );
533 rs->sr_err = LDAP_OTHER;
534 rs->sr_text = "SQL-backend error";
539 SQLFreeStmt( sth, SQL_DROP );
543 case LDAP_MOD_DELETE:
544 if ( at->bam_delete_proc == NULL ) {
545 Debug( LDAP_DEBUG_TRACE,
546 " backsql_modify_internal(): "
547 "delete procedure is not defined "
548 "for attribute \"%s\"\n",
549 at->bam_ad->ad_cname.bv_val, 0, 0 );
551 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
552 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
553 rs->sr_text = "operation not permitted "
554 "within namingContext";
561 if ( sm_values == NULL ) {
562 Debug( LDAP_DEBUG_TRACE,
563 " backsql_modify_internal(): "
564 "no values given to delete "
565 "for attribute \"%s\" "
566 "-- deleting all values\n",
567 at->bam_ad->ad_cname.bv_val, 0, 0 );
571 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
572 "deleting values for attribute \"%s\"\n",
573 at->bam_ad->ad_cname.bv_val, 0, 0 );
575 for ( i = 0, at_val = sm_values;
576 !BER_BVISNULL( at_val );
579 SQLHSTMT sth = SQL_NULL_HSTMT;
580 /* first parameter position, parameter order */
581 SQLUSMALLINT pno = 0,
583 /* procedure return code */
584 int prc = LDAP_SUCCESS;
586 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
587 if ( rc != SQL_SUCCESS ) {
588 Debug( LDAP_DEBUG_TRACE,
589 " backsql_modify_internal(): "
590 "error preparing delete query\n",
592 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
594 rs->sr_err = LDAP_OTHER;
595 rs->sr_text = "SQL-backend error";
599 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
601 rc = backsql_BindParamInt( sth, 1,
602 SQL_PARAM_OUTPUT, &prc );
603 if ( rc != SQL_SUCCESS ) {
604 Debug( LDAP_DEBUG_TRACE,
605 " backsql_modify_internal(): "
606 "error binding output parameter for %s[%d]\n",
607 at->bam_ad->ad_cname.bv_val, i, 0 );
608 backsql_PrintErrors( bi->sql_db_env, dbh,
610 SQLFreeStmt( sth, SQL_DROP );
612 rs->sr_text = "SQL-backend error";
613 rs->sr_err = LDAP_OTHER;
617 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
618 rc = backsql_BindParamID( sth, pno + 1 + po,
619 SQL_PARAM_INPUT, &e_id->eid_keyval );
620 if ( rc != SQL_SUCCESS ) {
621 Debug( LDAP_DEBUG_TRACE,
622 " backsql_modify_internal(): "
623 "error binding keyval parameter for %s[%d]\n",
624 at->bam_ad->ad_cname.bv_val, i, 0 );
625 backsql_PrintErrors( bi->sql_db_env, dbh,
627 SQLFreeStmt( sth, SQL_DROP );
629 rs->sr_text = "SQL-backend error";
630 rs->sr_err = LDAP_OTHER;
634 Debug( LDAP_DEBUG_TRACE,
635 " backsql_modify_internal(): "
636 "arg(%d)=" BACKSQL_IDFMT "\n",
638 BACKSQL_IDARG(e_id->eid_keyval), 0 );
641 * check for syntax needed here
642 * maybe need binary bind?
644 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
645 SQL_PARAM_INPUT, at_val );
646 if ( rc != SQL_SUCCESS ) {
647 Debug( LDAP_DEBUG_TRACE,
648 " backsql_modify_internal(): "
649 "error binding value parameter for %s[%d]\n",
650 at->bam_ad->ad_cname.bv_val, i, 0 );
651 backsql_PrintErrors( bi->sql_db_env, dbh,
653 SQLFreeStmt( sth, SQL_DROP );
655 rs->sr_text = "SQL-backend error";
656 rs->sr_err = LDAP_OTHER;
660 Debug( LDAP_DEBUG_TRACE,
661 " backsql_modify_internal(): "
662 "executing \"%s\"\n",
663 at->bam_delete_proc, 0, 0 );
664 rc = SQLExecute( sth );
665 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS )
667 rs->sr_err = LDAP_SUCCESS;
670 Debug( LDAP_DEBUG_TRACE,
671 " backsql_modify_internal(): "
672 "delete_proc execution "
673 "failed (rc=%d, prc=%d)\n",
676 if ( prc != LDAP_SUCCESS ) {
677 /* SQL procedure executed fine
678 * but returned an error */
679 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
680 rs->sr_text = at->bam_ad->ad_cname.bv_val;
684 backsql_PrintErrors( bi->sql_db_env,
686 SQLFreeStmt( sth, SQL_DROP );
687 rs->sr_err = LDAP_OTHER;
688 rs->sr_text = at->bam_ad->ad_cname.bv_val;
692 SQLFreeStmt( sth, SQL_DROP );
696 case LDAP_MOD_INCREMENT:
697 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
698 "increment not supported yet\n", 0, 0, 0 );
699 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
700 rs->sr_err = LDAP_OTHER;
701 rs->sr_text = "SQL-backend error";
709 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
711 rs->sr_text ? ": " : "",
712 rs->sr_text ? rs->sr_text : "" );
715 * FIXME: should fail in case one change fails?
725 backsql_oc_map_rec *oc,
727 backsql_key_t new_keyval )
729 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
730 backsql_at_map_rec *at_rec = NULL;
731 struct berval *at_val;
734 SQLUSMALLINT currpos;
735 SQLHSTMT sth = SQL_NULL_HSTMT;
737 at_rec = backsql_ad2at( oc, at->a_desc );
739 if ( at_rec == NULL ) {
740 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
741 "attribute \"%s\" is not registered "
742 "in objectclass \"%s\"\n",
743 op->ora_e->e_name.bv_val,
744 at->a_desc->ad_cname.bv_val,
745 BACKSQL_OC_NAME( oc ) );
747 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
748 rs->sr_text = "operation not permitted "
749 "within namingContext";
750 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
756 if ( at_rec->bam_add_proc == NULL ) {
757 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
758 "add procedure is not defined "
759 "for attribute \"%s\" "
760 "of structuralObjectClass \"%s\"\n",
761 op->ora_e->e_name.bv_val,
762 at->a_desc->ad_cname.bv_val,
763 BACKSQL_OC_NAME( oc ) );
765 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
766 rs->sr_text = "operation not permitted "
767 "within namingContext";
768 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
774 for ( i = 0, at_val = &at->a_vals[ i ];
775 !BER_BVISNULL( at_val );
776 i++, at_val = &at->a_vals[ i ] )
778 /* procedure return code */
779 int prc = LDAP_SUCCESS;
780 /* first parameter #, parameter order */
781 SQLUSMALLINT pno, po;
782 char logbuf[ STRLENOF("val[], id=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long)];
785 * Do not deal with the objectClass that is used
788 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
789 if ( dn_match( at_val, &oc->bom_oc->soc_cname ) )
795 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
796 if ( rc != SQL_SUCCESS ) {
797 rs->sr_text = "SQL-backend error";
798 return rs->sr_err = LDAP_OTHER;
801 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
803 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
804 if ( rc != SQL_SUCCESS ) {
805 Debug( LDAP_DEBUG_TRACE,
806 " backsql_add_attr(): "
807 "error binding output parameter for %s[%lu]\n",
808 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
809 backsql_PrintErrors( bi->sql_db_env, dbh,
811 SQLFreeStmt( sth, SQL_DROP );
813 rs->sr_text = "SQL-backend error";
814 return rs->sr_err = LDAP_OTHER;
821 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
822 currpos = pno + 1 + po;
823 rc = backsql_BindParamNumID( sth, currpos,
824 SQL_PARAM_INPUT, &new_keyval );
825 if ( rc != SQL_SUCCESS ) {
826 Debug( LDAP_DEBUG_TRACE,
827 " backsql_add_attr(): "
828 "error binding keyval parameter for %s[%lu]\n",
829 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
830 backsql_PrintErrors( bi->sql_db_env, dbh,
832 SQLFreeStmt( sth, SQL_DROP );
834 rs->sr_text = "SQL-backend error";
835 return rs->sr_err = LDAP_OTHER;
838 currpos = pno + 2 - po;
841 * check for syntax needed here
842 * maybe need binary bind?
845 rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
846 if ( rc != SQL_SUCCESS ) {
847 Debug( LDAP_DEBUG_TRACE,
848 " backsql_add_attr(): "
849 "error binding value parameter for %s[%lu]\n",
850 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
851 backsql_PrintErrors( bi->sql_db_env, dbh,
853 SQLFreeStmt( sth, SQL_DROP );
855 rs->sr_text = "SQL-backend error";
856 return rs->sr_err = LDAP_OTHER;
860 if ( LogTest( LDAP_DEBUG_TRACE ) ) {
861 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=" BACKSQL_IDNUMFMT,
863 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
864 "executing \"%s\" %s\n",
865 op->ora_e->e_name.bv_val,
866 at_rec->bam_add_proc, logbuf );
869 rc = SQLExecute( sth );
870 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
871 rs->sr_err = LDAP_SUCCESS;
874 Debug( LDAP_DEBUG_TRACE,
875 " backsql_add_attr(\"%s\"): "
876 "add_proc execution failed (rc=%d, prc=%d)\n",
877 op->ora_e->e_name.bv_val, rc, prc );
878 if ( prc != LDAP_SUCCESS ) {
879 /* SQL procedure executed fine
880 * but returned an error */
881 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
882 rs->sr_text = op->ora_e->e_name.bv_val;
883 SQLFreeStmt( sth, SQL_DROP );
887 backsql_PrintErrors( bi->sql_db_env, dbh,
889 rs->sr_err = LDAP_OTHER;
890 rs->sr_text = op->ora_e->e_name.bv_val;
891 SQLFreeStmt( sth, SQL_DROP );
895 SQLFreeStmt( sth, SQL_DROP );
902 backsql_add( Operation *op, SlapReply *rs )
904 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
905 SQLHDBC dbh = SQL_NULL_HDBC;
906 SQLHSTMT sth = SQL_NULL_HSTMT;
907 backsql_key_t new_keyval = 0;
909 backsql_oc_map_rec *oc = NULL;
910 backsql_srch_info bsi = { 0 };
911 Entry p = { 0 }, *e = NULL;
913 *at_objectClass = NULL;
914 ObjectClass *soc = NULL;
915 struct berval scname = BER_BVNULL;
917 struct berval realdn = BER_BVNULL;
921 char textbuf[ SLAP_TEXT_BUFLEN ];
922 size_t textlen = sizeof( textbuf );
924 #ifdef BACKSQL_SYNCPROV
926 * NOTE: fake successful result to force contextCSN to be bumped up
929 char buf[ LDAP_PVT_CSNSTR_BUFSIZE ];
933 csn.bv_len = sizeof( buf );
934 slap_get_csn( op, &csn, 1 );
936 rs->sr_err = LDAP_SUCCESS;
937 send_ldap_result( op, rs );
939 slap_graduate_commit_csn( op );
943 #endif /* BACKSQL_SYNCPROV */
945 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
946 op->ora_e->e_name.bv_val, 0, 0 );
949 if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
950 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
952 rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, NULL,
953 &rs->sr_text, textbuf, sizeof( textbuf ) );
954 if ( rs->sr_err != LDAP_SUCCESS ) {
955 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
956 "entry failed schema check -- aborting\n",
957 op->ora_e->e_name.bv_val, 0, 0 );
963 slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
965 if ( get_assert( op ) &&
966 ( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
968 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
969 "assertion control failed -- aborting\n",
970 op->ora_e->e_name.bv_val, 0, 0 );
972 rs->sr_err = LDAP_ASSERTION_FAILED;
976 /* search structuralObjectClass */
977 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
978 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
983 /* there must exist */
985 char buf[ SLAP_TEXT_BUFLEN ];
988 /* search structuralObjectClass */
989 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
990 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
996 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
998 op->ora_e->e_name.bv_val, 0, 0 );
999 rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
1004 rs->sr_err = structural_class( at->a_vals, &soc, NULL,
1005 &text, buf, sizeof( buf ), op->o_tmpmemctx );
1006 if ( rs->sr_err != LDAP_SUCCESS ) {
1007 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1009 op->ora_e->e_name.bv_val, text, rs->sr_err );
1013 scname = soc->soc_cname;
1016 scname = at->a_vals[0];
1019 /* I guess we should play with sub/supertypes to find a suitable oc */
1020 oc = backsql_name2oc( bi, &scname );
1023 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1024 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1025 op->ora_e->e_name.bv_val,
1027 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1028 rs->sr_text = "operation not permitted within namingContext";
1033 if ( oc->bom_create_proc == NULL ) {
1034 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1035 "create procedure is not defined "
1036 "for structuralObjectClass \"%s\" - aborting\n",
1037 op->ora_e->e_name.bv_val,
1039 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1040 rs->sr_text = "operation not permitted within namingContext";
1044 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
1045 && oc->bom_create_keyval == NULL ) {
1046 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1047 "create procedure needs select procedure, "
1048 "but none is defined for structuralObjectClass \"%s\" "
1050 op->ora_e->e_name.bv_val,
1052 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1053 rs->sr_text = "operation not permitted within namingContext";
1058 /* check write access */
1059 if ( !access_allowed_mask( op, op->ora_e,
1060 slap_schema.si_ad_entry,
1061 NULL, ACL_WADD, NULL, &mask ) )
1063 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1068 rs->sr_err = backsql_get_db_conn( op, &dbh );
1069 if ( rs->sr_err != LDAP_SUCCESS ) {
1070 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1071 "could not get connection handle - exiting\n",
1072 op->ora_e->e_name.bv_val, 0, 0 );
1073 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1074 ? "SQL-backend error" : NULL;
1080 * Check if entry exists
1082 * NOTE: backsql_api_dn2odbc() is called explicitly because
1083 * we need the mucked DN to pass it to the create procedure.
1085 realdn = op->ora_e->e_name;
1086 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
1087 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1088 "backsql_api_dn2odbc(\"%s\") failed\n",
1089 op->ora_e->e_name.bv_val, realdn.bv_val, 0 );
1090 rs->sr_err = LDAP_OTHER;
1091 rs->sr_text = "SQL-backend error";
1096 rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1097 if ( rs->sr_err == LDAP_SUCCESS ) {
1098 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1100 op->ora_e->e_name.bv_val, 0, 0 );
1101 rs->sr_err = LDAP_ALREADY_EXISTS;
1107 * Get the parent dn and see if the corresponding entry exists.
1109 if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
1110 pdn = slap_empty_bv;
1113 dnParent( &op->ora_e->e_nname, &pdn );
1119 rs->sr_err = backsql_init_search( &bsi, &pdn,
1121 (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
1122 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
1123 if ( rs->sr_err != LDAP_SUCCESS ) {
1124 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1125 "could not retrieve addDN parent "
1126 "\"%s\" ID - %s matched=\"%s\"\n",
1128 rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
1129 rs->sr_matched ? rs->sr_matched : "(null)" );
1134 /* check "children" pseudo-attribute access to parent */
1135 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1136 NULL, ACL_WADD, NULL ) )
1138 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1145 * create_proc is executed; if expect_return is set, then
1146 * an output parameter is bound, which should contain
1147 * the id of the added row; otherwise the procedure
1148 * is expected to return the id as the first column of a select
1150 rc = backsql_Prepare( dbh, &sth, oc->bom_create_proc, 0 );
1151 if ( rc != SQL_SUCCESS ) {
1152 rs->sr_err = LDAP_OTHER;
1153 rs->sr_text = "SQL-backend error";
1159 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1160 rc = backsql_BindParamNumID( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1161 if ( rc != SQL_SUCCESS ) {
1162 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1163 "error binding keyval parameter "
1164 "for objectClass %s\n",
1165 op->ora_e->e_name.bv_val,
1166 oc->bom_oc->soc_cname.bv_val, 0 );
1167 backsql_PrintErrors( bi->sql_db_env, dbh,
1169 SQLFreeStmt( sth, SQL_DROP );
1171 rs->sr_text = "SQL-backend error";
1172 rs->sr_err = LDAP_OTHER;
1179 if ( oc->bom_create_hint ) {
1180 at = attr_find( op->ora_e->e_attrs, oc->bom_create_hint );
1181 if ( at && at->a_vals ) {
1182 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1183 at->a_vals[0].bv_val,
1184 at->a_vals[0].bv_len );
1185 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1186 "create_proc hint: param = '%s'\n",
1187 at->a_vals[0].bv_val, 0, 0 );
1190 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1192 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1193 "create_proc hint (%s) not avalable\n",
1194 oc->bom_create_hint->ad_cname.bv_val,
1200 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1201 op->ora_e->e_name.bv_val, oc->bom_create_proc, 0 );
1202 rc = SQLExecute( sth );
1203 if ( rc != SQL_SUCCESS ) {
1204 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1205 "create_proc execution failed\n",
1206 op->ora_e->e_name.bv_val, 0, 0 );
1207 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1208 SQLFreeStmt( sth, SQL_DROP );
1209 rs->sr_err = LDAP_OTHER;
1210 rs->sr_text = "SQL-backend error";
1215 /* FIXME: after SQLExecute(), the row is already inserted
1216 * (at least with PostgreSQL and unixODBC); needs investigation */
1218 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1220 SQLINTEGER value_len;
1222 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1223 SQLFreeStmt( sth, SQL_DROP );
1225 rc = backsql_Prepare( dbh, &sth, oc->bom_create_keyval, 0 );
1226 if ( rc != SQL_SUCCESS ) {
1227 rs->sr_err = LDAP_OTHER;
1228 rs->sr_text = "SQL-backend error";
1233 rc = SQLExecute( sth );
1234 if ( rc != SQL_SUCCESS ) {
1235 rs->sr_err = LDAP_OTHER;
1236 rs->sr_text = "SQL-backend error";
1243 * the query to know the id of the inserted entry
1244 * must be embedded in the create procedure
1246 rc = SQLNumResultCols( sth, &ncols );
1247 if ( rc != SQL_SUCCESS ) {
1248 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1249 "create_proc result evaluation failed\n",
1250 op->ora_e->e_name.bv_val, 0, 0 );
1251 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1252 SQLFreeStmt( sth, SQL_DROP );
1253 rs->sr_err = LDAP_OTHER;
1254 rs->sr_text = "SQL-backend error";
1258 } else if ( ncols != 1 ) {
1259 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1260 "create_proc result is bogus (ncols=%d)\n",
1261 op->ora_e->e_name.bv_val, ncols, 0 );
1262 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1263 SQLFreeStmt( sth, SQL_DROP );
1264 rs->sr_err = LDAP_OTHER;
1265 rs->sr_text = "SQL-backend error";
1272 SQLCHAR colname[ 64 ];
1273 SQLSMALLINT name_len, col_type, col_scale, col_null;
1277 * FIXME: check whether col_type is compatible,
1278 * if it can be null and so on ...
1280 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1282 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1283 &name_len, &col_type,
1284 &col_prec, &col_scale, &col_null );
1288 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1289 (SQLPOINTER)&new_keyval,
1290 (SQLINTEGER)sizeof( new_keyval ),
1293 rc = SQLFetch( sth );
1295 if ( value_len <= 0 ) {
1296 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1297 "create_proc result is empty?\n",
1298 op->ora_e->e_name.bv_val, 0, 0 );
1299 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1300 SQLFreeStmt( sth, SQL_DROP );
1301 rs->sr_err = LDAP_OTHER;
1302 rs->sr_text = "SQL-backend error";
1308 SQLFreeStmt( sth, SQL_DROP );
1310 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1311 "create_proc returned keyval=" BACKSQL_IDNUMFMT "\n",
1312 op->ora_e->e_name.bv_val, new_keyval, 0 );
1314 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
1315 if ( rc != SQL_SUCCESS ) {
1316 rs->sr_err = LDAP_OTHER;
1317 rs->sr_text = "SQL-backend error";
1322 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1323 if ( rc != SQL_SUCCESS ) {
1324 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1325 "error binding DN parameter for objectClass %s\n",
1326 op->ora_e->e_name.bv_val,
1327 oc->bom_oc->soc_cname.bv_val, 0 );
1328 backsql_PrintErrors( bi->sql_db_env, dbh,
1330 SQLFreeStmt( sth, SQL_DROP );
1332 rs->sr_text = "SQL-backend error";
1333 rs->sr_err = LDAP_OTHER;
1338 rc = backsql_BindParamNumID( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1339 if ( rc != SQL_SUCCESS ) {
1340 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1341 "error binding objectClass ID parameter "
1342 "for objectClass %s\n",
1343 op->ora_e->e_name.bv_val,
1344 oc->bom_oc->soc_cname.bv_val, 0 );
1345 backsql_PrintErrors( bi->sql_db_env, dbh,
1347 SQLFreeStmt( sth, SQL_DROP );
1349 rs->sr_text = "SQL-backend error";
1350 rs->sr_err = LDAP_OTHER;
1355 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &bsi.bsi_base_id.eid_id );
1356 if ( rc != SQL_SUCCESS ) {
1357 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1358 "error binding parent ID parameter "
1359 "for objectClass %s\n",
1360 op->ora_e->e_name.bv_val,
1361 oc->bom_oc->soc_cname.bv_val, 0 );
1362 backsql_PrintErrors( bi->sql_db_env, dbh,
1364 SQLFreeStmt( sth, SQL_DROP );
1366 rs->sr_text = "SQL-backend error";
1367 rs->sr_err = LDAP_OTHER;
1372 rc = backsql_BindParamNumID( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1373 if ( rc != SQL_SUCCESS ) {
1374 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1375 "error binding entry ID parameter "
1376 "for objectClass %s\n",
1377 op->ora_e->e_name.bv_val,
1378 oc->bom_oc->soc_cname.bv_val, 0 );
1379 backsql_PrintErrors( bi->sql_db_env, dbh,
1381 SQLFreeStmt( sth, SQL_DROP );
1383 rs->sr_text = "SQL-backend error";
1384 rs->sr_err = LDAP_OTHER;
1389 if ( LogTest( LDAP_DEBUG_TRACE ) ) {
1390 char buf[ SLAP_TEXT_BUFLEN ];
1392 snprintf( buf, sizeof(buf),
1393 "executing \"%s\" for dn=\"%s\" oc_map_id=" BACKSQL_IDNUMFMT " p_id=" BACKSQL_IDFMT " keyval=" BACKSQL_IDNUMFMT,
1394 bi->sql_insentry_stmt, op->ora_e->e_name.bv_val,
1395 oc->bom_id, BACKSQL_IDARG(bsi.bsi_base_id.eid_id),
1397 Debug( LDAP_DEBUG_TRACE, " backsql_add(): %s\n", buf, 0, 0 );
1400 rc = SQLExecute( sth );
1401 if ( rc != SQL_SUCCESS ) {
1402 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1403 "could not insert ldap_entries record\n",
1404 op->ora_e->e_name.bv_val, 0, 0 );
1405 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
1408 * execute delete_proc to delete data added !!!
1410 SQLFreeStmt( sth, SQL_DROP );
1411 rs->sr_err = LDAP_OTHER;
1412 rs->sr_text = "SQL-backend error";
1417 SQLFreeStmt( sth, SQL_DROP );
1419 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1420 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1421 "adding attribute \"%s\"\n",
1422 at->a_desc->ad_cname.bv_val, 0, 0 );
1426 * - the first occurrence of objectClass, which is used
1427 * to determine how to build the SQL entry (FIXME ?!?)
1428 * - operational attributes
1429 * - empty attributes (FIXME ?!?)
1431 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1435 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1436 at_objectClass = at;
1440 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1441 if ( rs->sr_err != LDAP_SUCCESS ) {
1447 if ( at_objectClass ) {
1448 rs->sr_err = backsql_add_attr( op, rs, dbh, oc,
1449 at_objectClass, new_keyval );
1450 if ( rs->sr_err != LDAP_SUCCESS ) {
1458 * Commit only if all operations succeed
1460 if ( sth != SQL_NULL_HSTMT ) {
1461 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
1463 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1464 assert( e == NULL );
1465 CompletionType = SQL_COMMIT;
1468 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
1472 * FIXME: NOOP does not work for add -- it works for all
1473 * the other operations, and I don't get the reason :(
1475 * hint: there might be some autocommit in Postgres
1476 * so that when the unique id of the key table is
1477 * automatically increased, there's no rollback.
1478 * We might implement a "rollback" procedure consisting
1479 * in deleting that row.
1485 if ( e == op->ora_e && !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
1486 /* mask already collected */
1489 } else if ( e == &p && !access_allowed( op, &p,
1490 slap_schema.si_ad_entry, NULL,
1491 ACL_DISCLOSE, NULL ) )
1496 if ( disclose == 0 ) {
1497 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1499 rs->sr_matched = NULL;
1501 ber_bvarray_free( rs->sr_ref );
1507 if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
1508 rs->sr_err = LDAP_X_NO_OPERATION;
1511 send_ldap_result( op, rs );
1512 slap_graduate_commit_csn( op );
1514 if ( !BER_BVISNULL( &realdn )
1515 && realdn.bv_val != op->ora_e->e_name.bv_val )
1517 ch_free( realdn.bv_val );
1520 if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
1521 (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
1524 if ( !BER_BVISNULL( &p.e_nname ) ) {
1525 backsql_entry_clean( op, &p );
1528 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1529 op->ora_e->e_name.bv_val,
1531 rs->sr_text ? rs->sr_text : "" );
1534 rs->sr_matched = NULL;
1536 ber_bvarray_free( rs->sr_ref );