2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2005 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
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 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
95 rs->sr_text = "SQL-backend error";
96 return rs->sr_err = LDAP_OTHER;
101 rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
102 if ( rc != SQL_SUCCESS ) {
103 Debug( LDAP_DEBUG_TRACE,
104 " backsql_modify_delete_all_values(): "
105 "error binding key value parameter "
106 "to attribute value select query\n",
108 backsql_PrintErrors( bi->sql_db_env, dbh,
110 SQLFreeStmt( asth, SQL_DROP );
112 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
113 rs->sr_text = "SQL-backend error";
114 return rs->sr_err = LDAP_OTHER;
120 rc = SQLExecute( asth );
121 if ( !BACKSQL_SUCCESS( rc ) ) {
122 Debug( LDAP_DEBUG_TRACE,
123 " backsql_modify_delete_all_values(): "
124 "error executing attribute value select query\n",
126 backsql_PrintErrors( bi->sql_db_env, dbh,
128 SQLFreeStmt( asth, SQL_DROP );
130 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
131 rs->sr_text = "SQL-backend error";
132 return rs->sr_err = LDAP_OTHER;
138 backsql_BindRowAsStrings( asth, &row );
139 for ( rc = SQLFetch( asth );
140 BACKSQL_SUCCESS( rc );
141 rc = SQLFetch( asth ) )
144 /* first parameter no, parameter order */
145 SQLUSMALLINT pno, po;
146 /* procedure return code */
147 int prc = LDAP_SUCCESS;
149 for ( i = 0; i < row.ncols; i++ ) {
150 SQLHSTMT sth = SQL_NULL_HSTMT;
153 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
154 if ( rc != SQL_SUCCESS ) {
155 Debug( LDAP_DEBUG_TRACE,
156 " backsql_modify_delete_all_values(): "
157 "error preparing attribute value "
160 at->bam_delete_proc, 0, 0 );
161 backsql_PrintErrors( bi->sql_db_env, dbh,
164 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
165 rs->sr_text = "SQL-backend error";
166 return rs->sr_err = LDAP_OTHER;
172 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
174 rc = backsql_BindParamInt( sth, 1,
175 SQL_PARAM_OUTPUT, &prc );
176 if ( rc != SQL_SUCCESS ) {
177 Debug( LDAP_DEBUG_TRACE,
178 " backsql_modify_delete_all_values(): "
179 "error binding output parameter for %s[%d]\n",
180 at->bam_ad->ad_cname.bv_val, i, 0 );
181 backsql_PrintErrors( bi->sql_db_env, dbh,
183 SQLFreeStmt( sth, SQL_DROP );
185 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
186 rs->sr_text = "SQL-backend error";
187 return rs->sr_err = LDAP_OTHER;
196 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
197 rc = backsql_BindParamID( sth, pno + 1 + po,
198 SQL_PARAM_INPUT, &e_id->eid_keyval );
199 if ( rc != SQL_SUCCESS ) {
200 Debug( LDAP_DEBUG_TRACE,
201 " backsql_modify_delete_all_values(): "
202 "error binding keyval parameter for %s[%d]\n",
203 at->bam_ad->ad_cname.bv_val, i, 0 );
204 backsql_PrintErrors( bi->sql_db_env, dbh,
206 SQLFreeStmt( sth, SQL_DROP );
208 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
209 rs->sr_text = "SQL-backend error";
210 return rs->sr_err = LDAP_OTHER;
215 #ifdef BACKSQL_ARBITRARY_KEY
216 Debug( LDAP_DEBUG_TRACE,
217 " backsql_modify_delete_all_values() "
219 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
220 #else /* ! BACKSQL_ARBITRARY_KEY */
221 Debug( LDAP_DEBUG_TRACE,
222 " backsql_modify_delete_all_values() "
224 pno + 1 + po, e_id->eid_keyval, 0 );
225 #endif /* ! BACKSQL_ARBITRARY_KEY */
228 * check for syntax needed here
229 * maybe need binary bind?
231 col_len = strlen( row.cols[ i ] );
232 rc = backsql_BindParamStr( sth, pno + 2 - po,
233 SQL_PARAM_INPUT, row.cols[ i ], col_len );
234 if ( rc != SQL_SUCCESS ) {
235 Debug( LDAP_DEBUG_TRACE,
236 " backsql_modify_delete_all_values(): "
237 "error binding value parameter for %s[%d]\n",
238 at->bam_ad->ad_cname.bv_val, i, 0 );
239 backsql_PrintErrors( bi->sql_db_env, dbh,
241 SQLFreeStmt( sth, SQL_DROP );
243 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
244 rs->sr_text = "SQL-backend error";
245 return rs->sr_err = LDAP_OTHER;
251 Debug( LDAP_DEBUG_TRACE,
252 " backsql_modify_delete_all_values(): "
253 "arg%d=%s; executing \"%s\"\n",
254 pno + 2 - po, row.cols[ i ],
255 at->bam_delete_proc );
256 rc = SQLExecute( sth );
257 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
258 rs->sr_err = LDAP_SUCCESS;
261 Debug( LDAP_DEBUG_TRACE,
262 " backsql_modify_delete_all_values(): "
264 "execution failed (rc=%d, prc=%d)\n",
266 if ( prc != LDAP_SUCCESS ) {
267 /* SQL procedure executed fine
268 * but returned an error */
269 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
270 rs->sr_text = op->ora_e->e_name.bv_val;
271 SQLFreeStmt( sth, SQL_DROP );
275 backsql_PrintErrors( bi->sql_db_env, dbh,
277 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
279 rs->sr_err = LDAP_OTHER;
280 rs->sr_text = op->ora_e->e_name.bv_val;
281 SQLFreeStmt( sth, SQL_DROP );
286 SQLFreeStmt( sth, SQL_DROP );
289 backsql_FreeRow( &row );
290 SQLFreeStmt( asth, SQL_DROP );
296 backsql_modify_internal(
300 backsql_oc_map_rec *oc,
301 backsql_entryID *e_id,
302 Modifications *modlist )
304 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
306 SQLHSTMT sth = SQL_NULL_HSTMT;
309 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
310 "traversing modifications list\n", 0, 0, 0 );
312 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
313 AttributeDescription *ad;
315 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
319 /* NOTE: some day we'll have to pass
320 * the normalized values as well */
321 BerVarray sm_nvalues;
323 backsql_at_map_rec *at = NULL;
324 struct berval *at_val;
326 /* first parameter position, parameter order */
327 SQLUSMALLINT pno, po;
328 /* procedure return code */
329 int prc = LDAP_SUCCESS;
331 ad = ml->sml_mod.sm_desc;
332 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
333 sm_values = ml->sml_mod.sm_values;
335 sm_nvalues = ml->sml_mod.sm_nvalues;
338 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
339 "modifying attribute \"%s\" (%s) according to "
340 "mappings for objectClass \"%s\"\n",
341 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
343 if ( backsql_attr_skip( ad, sm_values ) ) {
347 at = backsql_ad2at( oc, ad );
349 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
350 "attribute \"%s\" is not registered "
351 "in objectClass \"%s\"\n",
352 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
354 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
355 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
356 rs->sr_text = "operation not permitted "
357 "within namingContext";
365 case LDAP_MOD_REPLACE: {
366 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
367 "replacing values for attribute \"%s\"\n",
368 at->bam_ad->ad_cname.bv_val, 0, 0 );
370 if ( at->bam_add_proc == NULL ) {
371 Debug( LDAP_DEBUG_TRACE,
372 " backsql_modify_internal(): "
373 "add procedure is not defined "
374 "for attribute \"%s\" "
375 "- unable to perform replacements\n",
376 at->bam_ad->ad_cname.bv_val, 0, 0 );
378 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
379 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
380 rs->sr_text = "operation not permitted "
381 "within namingContext";
388 if ( at->bam_delete_proc == NULL ) {
389 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
390 Debug( LDAP_DEBUG_TRACE,
391 " backsql_modify_internal(): "
392 "delete procedure is not defined "
393 "for attribute \"%s\"\n",
394 at->bam_ad->ad_cname.bv_val, 0, 0 );
396 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
397 rs->sr_text = "operation not permitted "
398 "within namingContext";
402 Debug( LDAP_DEBUG_TRACE,
403 " backsql_modify_internal(): "
404 "delete procedure is not defined "
405 "for attribute \"%s\" "
407 at->bam_ad->ad_cname.bv_val, 0, 0 );
413 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
414 if ( rs->sr_err != LDAP_SUCCESS ) {
418 /* LDAP_MOD_DELETE gets here if all values must be deleted */
419 if ( sm_op == LDAP_MOD_DELETE ) {
425 * PASSTHROUGH - to add new attributes -- do NOT add break
428 /* case SLAP_MOD_SOFTADD: */
430 if ( at->bam_add_proc == NULL ) {
431 Debug( LDAP_DEBUG_TRACE,
432 " backsql_modify_internal(): "
433 "add procedure is not defined "
434 "for attribute \"%s\"\n",
435 at->bam_ad->ad_cname.bv_val, 0, 0 );
437 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
438 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
439 rs->sr_text = "operation not permitted "
440 "within namingContext";
447 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
448 "adding new values for attribute \"%s\"\n",
449 at->bam_ad->ad_cname.bv_val, 0, 0 );
451 /* can't add a NULL val array */
452 assert( sm_values != NULL );
454 for ( i = 0, at_val = sm_values;
455 !BER_BVISNULL( at_val );
458 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
459 if ( rc != SQL_SUCCESS ) {
460 Debug( LDAP_DEBUG_TRACE,
461 " backsql_modify_internal(): "
462 "error preparing add query\n",
464 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
466 rs->sr_err = LDAP_OTHER;
467 rs->sr_text = "SQL-backend error";
471 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
473 rc = backsql_BindParamInt( sth, 1,
474 SQL_PARAM_OUTPUT, &prc );
475 if ( rc != SQL_SUCCESS ) {
476 Debug( LDAP_DEBUG_TRACE,
477 " backsql_modify_internal(): "
478 "error binding output parameter for %s[%d]\n",
479 at->bam_ad->ad_cname.bv_val, i, 0 );
480 backsql_PrintErrors( bi->sql_db_env, dbh,
482 SQLFreeStmt( sth, SQL_DROP );
484 rs->sr_text = "SQL-backend error";
485 rs->sr_err = LDAP_OTHER;
492 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
493 rc = backsql_BindParamID( sth, pno + 1 + po,
494 SQL_PARAM_INPUT, &e_id->eid_keyval );
495 if ( rc != SQL_SUCCESS ) {
496 Debug( LDAP_DEBUG_TRACE,
497 " backsql_modify_internal(): "
498 "error binding keyval parameter for %s[%d]\n",
499 at->bam_ad->ad_cname.bv_val, i, 0 );
500 backsql_PrintErrors( bi->sql_db_env, dbh,
502 SQLFreeStmt( sth, SQL_DROP );
504 rs->sr_text = "SQL-backend error";
505 rs->sr_err = LDAP_OTHER;
508 #ifdef BACKSQL_ARBITRARY_KEY
509 Debug( LDAP_DEBUG_TRACE,
510 " backsql_modify_internal(): "
512 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
513 #else /* ! BACKSQL_ARBITRARY_KEY */
514 Debug( LDAP_DEBUG_TRACE,
515 " backsql_modify_internal(): "
517 pno + 1 + po, e_id->eid_keyval, 0 );
518 #endif /* ! BACKSQL_ARBITRARY_KEY */
521 * check for syntax needed here
522 * maybe need binary bind?
524 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
525 SQL_PARAM_INPUT, at_val );
526 if ( rc != SQL_SUCCESS ) {
527 Debug( LDAP_DEBUG_TRACE,
528 " backsql_modify_internal(): "
529 "error binding value parameter for %s[%d]\n",
530 at->bam_ad->ad_cname.bv_val, i, 0 );
531 backsql_PrintErrors( bi->sql_db_env, dbh,
533 SQLFreeStmt( sth, SQL_DROP );
535 rs->sr_text = "SQL-backend error";
536 rs->sr_err = LDAP_OTHER;
539 Debug( LDAP_DEBUG_TRACE,
540 " backsql_modify_internal(): "
541 "arg%d=\"%s\"; executing \"%s\"\n",
542 pno + 2 - po, at_val->bv_val,
545 rc = SQLExecute( sth );
546 if ( rc != SQL_SUCCESS ) {
547 Debug( LDAP_DEBUG_TRACE,
548 " backsql_modify_internal(): "
549 "add_proc execution failed\n",
551 backsql_PrintErrors( bi->sql_db_env,
554 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
555 SQLFreeStmt( sth, SQL_DROP );
556 rs->sr_err = LDAP_OTHER;
557 rs->sr_text = "SQL-backend error";
561 SQLFreeStmt( sth, SQL_DROP );
565 case LDAP_MOD_DELETE:
566 if ( at->bam_delete_proc == NULL ) {
567 Debug( LDAP_DEBUG_TRACE,
568 " backsql_modify_internal(): "
569 "delete procedure is not defined "
570 "for attribute \"%s\"\n",
571 at->bam_ad->ad_cname.bv_val, 0, 0 );
573 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
574 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
575 rs->sr_text = "operation not permitted "
576 "within namingContext";
583 if ( sm_values == NULL ) {
584 Debug( LDAP_DEBUG_TRACE,
585 " backsql_modify_internal(): "
586 "no values given to delete "
587 "for attribute \"%s\" "
588 "-- deleting all values\n",
589 at->bam_ad->ad_cname.bv_val, 0, 0 );
593 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
594 "deleting values for attribute \"%s\"\n",
595 at->bam_ad->ad_cname.bv_val, 0, 0 );
597 for ( i = 0, at_val = sm_values;
598 !BER_BVISNULL( at_val );
602 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
603 if ( rc != SQL_SUCCESS ) {
604 Debug( LDAP_DEBUG_TRACE,
605 " backsql_modify_internal(): "
606 "error preparing delete query\n",
608 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
610 rs->sr_err = LDAP_OTHER;
611 rs->sr_text = "SQL-backend error";
615 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
617 rc = backsql_BindParamInt( sth, 1,
618 SQL_PARAM_OUTPUT, &prc );
619 if ( rc != SQL_SUCCESS ) {
620 Debug( LDAP_DEBUG_TRACE,
621 " backsql_modify_internal(): "
622 "error binding output parameter for %s[%d]\n",
623 at->bam_ad->ad_cname.bv_val, i, 0 );
624 backsql_PrintErrors( bi->sql_db_env, dbh,
626 SQLFreeStmt( sth, SQL_DROP );
628 rs->sr_text = "SQL-backend error";
629 rs->sr_err = LDAP_OTHER;
636 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
637 rc = backsql_BindParamID( sth, pno + 1 + po,
638 SQL_PARAM_INPUT, &e_id->eid_keyval );
639 if ( rc != SQL_SUCCESS ) {
640 Debug( LDAP_DEBUG_TRACE,
641 " backsql_modify_internal(): "
642 "error binding keyval parameter for %s[%d]\n",
643 at->bam_ad->ad_cname.bv_val, i, 0 );
644 backsql_PrintErrors( bi->sql_db_env, dbh,
646 SQLFreeStmt( sth, SQL_DROP );
648 rs->sr_text = "SQL-backend error";
649 rs->sr_err = LDAP_OTHER;
652 #ifdef BACKSQL_ARBITRARY_KEY
653 Debug( LDAP_DEBUG_TRACE,
654 " backsql_modify_internal(): "
656 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
657 #else /* ! BACKSQL_ARBITRARY_KEY */
658 Debug( LDAP_DEBUG_TRACE,
659 " backsql_modify_internal(): "
661 pno + 1 + po, e_id->eid_keyval, 0 );
662 #endif /* ! BACKSQL_ARBITRARY_KEY */
665 * check for syntax needed here
666 * maybe need binary bind?
668 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
669 SQL_PARAM_INPUT, at_val );
670 if ( rc != SQL_SUCCESS ) {
671 Debug( LDAP_DEBUG_TRACE,
672 " backsql_modify_internal(): "
673 "error binding value parameter for %s[%d]\n",
674 at->bam_ad->ad_cname.bv_val, i, 0 );
675 backsql_PrintErrors( bi->sql_db_env, dbh,
677 SQLFreeStmt( sth, SQL_DROP );
679 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
680 rs->sr_text = "SQL-backend error";
681 rs->sr_err = LDAP_OTHER;
686 Debug( LDAP_DEBUG_TRACE,
687 " backsql_modify_internal(): "
688 "executing \"%s\"\n",
689 at->bam_delete_proc, 0, 0 );
690 rc = SQLExecute( sth );
691 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS )
693 rs->sr_err = LDAP_SUCCESS;
696 Debug( LDAP_DEBUG_TRACE,
697 " backsql_modify_internal(): "
698 "delete_proc execution "
699 "failed (rc=%d, prc=%d)\n",
702 if ( prc != LDAP_SUCCESS ) {
703 /* SQL procedure executed fine
704 * but returned an error */
705 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
706 rs->sr_text = at->bam_ad->ad_cname.bv_val;
710 backsql_PrintErrors( bi->sql_db_env,
712 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
714 SQLFreeStmt( sth, SQL_DROP );
715 rs->sr_err = LDAP_OTHER;
716 rs->sr_text = at->bam_ad->ad_cname.bv_val;
721 SQLFreeStmt( sth, SQL_DROP );
725 case LDAP_MOD_INCREMENT:
726 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
727 "increment not supported yet\n", 0, 0, 0 );
728 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
729 rs->sr_err = LDAP_OTHER;
730 rs->sr_text = "SQL-backend error";
738 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
740 rs->sr_text ? ": " : "",
741 rs->sr_text ? rs->sr_text : "" );
744 * FIXME: should fail in case one change fails?
754 backsql_oc_map_rec *oc,
756 unsigned long new_keyval )
758 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
759 backsql_at_map_rec *at_rec = NULL;
760 struct berval *at_val;
763 SQLUSMALLINT currpos;
764 SQLHSTMT sth = SQL_NULL_HSTMT;
766 at_rec = backsql_ad2at( oc, at->a_desc );
768 if ( at_rec == NULL ) {
769 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
770 "attribute \"%s\" is not registered "
771 "in objectclass \"%s\"\n",
772 op->ora_e->e_name.bv_val,
773 at->a_desc->ad_cname.bv_val,
774 BACKSQL_OC_NAME( oc ) );
776 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
777 rs->sr_text = "operation not permitted "
778 "within namingContext";
779 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
785 if ( at_rec->bam_add_proc == NULL ) {
786 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
787 "add procedure is not defined "
788 "for attribute \"%s\" "
789 "of structuralObjectClass \"%s\"\n",
790 op->ora_e->e_name.bv_val,
791 at->a_desc->ad_cname.bv_val,
792 BACKSQL_OC_NAME( oc ) );
794 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
795 rs->sr_text = "operation not permitted "
796 "within namingContext";
797 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
803 for ( i = 0, at_val = &at->a_vals[ i ];
804 !BER_BVISNULL( at_val );
805 i++, at_val = &at->a_vals[ i ] )
807 /* procedure return code */
808 int prc = LDAP_SUCCESS;
809 /* first parameter #, parameter order */
810 SQLUSMALLINT pno, po;
811 char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
814 * Do not deal with the objectClass that is used
817 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
818 if ( dn_match( at_val, &oc->bom_oc->soc_cname ) )
824 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
825 if ( rc != SQL_SUCCESS ) {
827 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
828 rs->sr_text = "SQL-backend error";
829 return rs->sr_err = LDAP_OTHER;
835 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
837 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
838 if ( rc != SQL_SUCCESS ) {
839 Debug( LDAP_DEBUG_TRACE,
840 " backsql_add_attr(): "
841 "error binding output parameter for %s[%d]\n",
842 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
843 backsql_PrintErrors( bi->sql_db_env, dbh,
845 SQLFreeStmt( sth, SQL_DROP );
847 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
848 rs->sr_text = "SQL-backend error";
849 return rs->sr_err = LDAP_OTHER;
859 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
860 currpos = pno + 1 + po;
861 rc = backsql_BindParamInt( sth, currpos,
862 SQL_PARAM_INPUT, &new_keyval );
863 if ( rc != SQL_SUCCESS ) {
864 Debug( LDAP_DEBUG_TRACE,
865 " backsql_add_attr(): "
866 "error binding keyval parameter for %s[%d]\n",
867 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
868 backsql_PrintErrors( bi->sql_db_env, dbh,
870 SQLFreeStmt( sth, SQL_DROP );
872 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
873 rs->sr_text = "SQL-backend error";
874 return rs->sr_err = LDAP_OTHER;
880 currpos = pno + 2 - po;
883 * check for syntax needed here
884 * maybe need binary bind?
887 rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
888 if ( rc != SQL_SUCCESS ) {
889 Debug( LDAP_DEBUG_TRACE,
890 " backsql_add_attr(): "
891 "error binding value parameter for %s[%d]\n",
892 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
893 backsql_PrintErrors( bi->sql_db_env, dbh,
895 SQLFreeStmt( sth, SQL_DROP );
897 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
898 rs->sr_text = "SQL-backend error";
899 return rs->sr_err = LDAP_OTHER;
906 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
908 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
909 "executing \"%s\" %s\n",
910 op->ora_e->e_name.bv_val,
911 at_rec->bam_add_proc, logbuf );
913 rc = SQLExecute( sth );
914 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
915 rs->sr_err = LDAP_SUCCESS;
918 Debug( LDAP_DEBUG_TRACE,
919 " backsql_add_attr(\"%s\"): "
920 "add_proc execution failed (rc=%d, prc=%d)\n",
921 op->ora_e->e_name.bv_val, rc, prc );
922 if ( prc != LDAP_SUCCESS ) {
923 /* SQL procedure executed fine
924 * but returned an error */
925 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
926 rs->sr_text = op->ora_e->e_name.bv_val;
927 SQLFreeStmt( sth, SQL_DROP );
931 backsql_PrintErrors( bi->sql_db_env, dbh,
933 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
934 rs->sr_err = LDAP_OTHER;
935 rs->sr_text = op->ora_e->e_name.bv_val;
936 SQLFreeStmt( sth, SQL_DROP );
941 SQLFreeStmt( sth, SQL_DROP );
948 backsql_add( Operation *op, SlapReply *rs )
950 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
951 SQLHDBC dbh = SQL_NULL_HDBC;
952 SQLHSTMT sth = SQL_NULL_HSTMT;
953 unsigned long new_keyval = 0;
955 backsql_oc_map_rec *oc = NULL;
956 backsql_srch_info bsi = { 0 };
957 Entry p = { 0 }, *e = NULL;
959 *at_objectClass = NULL;
960 struct berval scname = BER_BVNULL;
962 struct berval realdn = BER_BVNULL;
966 #ifdef BACKSQL_SYNCPROV
968 * NOTE: fake successful result to force contextCSN to be bumped up
971 char buf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
972 struct berval csn = BER_BVNULL;
974 slap_get_csn( op, buf, sizeof( buf ), &csn, 1 );
976 rs->sr_err = LDAP_SUCCESS;
977 send_ldap_result( op, rs );
979 slap_graduate_commit_csn( op );
983 #endif /* BACKSQL_SYNCPROV */
985 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
986 op->ora_e->e_name.bv_val, 0, 0 );
989 if ( global_schemacheck ) {
990 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
992 rs->sr_err = entry_schema_check( op->o_bd, op->ora_e,
994 &rs->sr_text, textbuf, sizeof( textbuf ) );
995 if ( rs->sr_err != LDAP_SUCCESS ) {
996 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
997 "entry failed schema check -- aborting\n",
998 op->ora_e->e_name.bv_val, 0, 0 );
1004 /* search structuralObjectClass */
1005 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1006 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
1011 /* there must exist */
1013 char buf[ SLAP_TEXT_BUFLEN ];
1016 /* search structuralObjectClass */
1017 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1018 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1024 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1026 op->ora_e->e_name.bv_val, 0, 0 );
1027 rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
1032 rs->sr_err = structural_class( at->a_vals, &scname, NULL,
1033 &text, buf, sizeof( buf ) );
1034 if ( rs->sr_err != LDAP_SUCCESS ) {
1035 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1037 op->ora_e->e_name.bv_val, text, rs->sr_err );
1043 scname = at->a_vals[0];
1046 /* I guess we should play with sub/supertypes to find a suitable oc */
1047 oc = backsql_name2oc( bi, &scname );
1050 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1051 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1052 op->ora_e->e_name.bv_val,
1054 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1055 rs->sr_text = "operation not permitted within namingContext";
1060 if ( oc->bom_create_proc == NULL ) {
1061 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1062 "create procedure is not defined "
1063 "for structuralObjectClass \"%s\" - aborting\n",
1064 op->ora_e->e_name.bv_val,
1066 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1067 rs->sr_text = "operation not permitted within namingContext";
1071 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
1072 && oc->bom_create_keyval == NULL ) {
1073 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1074 "create procedure needs select procedure, "
1075 "but none is defined for structuralObjectClass \"%s\" "
1077 op->ora_e->e_name.bv_val,
1079 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1080 rs->sr_text = "operation not permitted within namingContext";
1085 rs->sr_err = backsql_get_db_conn( op, &dbh );
1086 if ( rs->sr_err != LDAP_SUCCESS ) {
1087 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1088 "could not get connection handle - exiting\n",
1089 op->ora_e->e_name.bv_val, 0, 0 );
1090 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1091 ? "SQL-backend error" : NULL;
1097 * Check if entry exists
1099 * NOTE: backsql_api_dn2odbc() is called explicitly because
1100 * we need the mucked DN to pass it to the create procedure.
1102 realdn = op->ora_e->e_name;
1103 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
1104 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1105 "backsql_api_dn2odbc(\"%s\") failed\n",
1106 op->ora_e->e_name.bv_val, realdn.bv_val, 0 );
1107 rs->sr_err = LDAP_OTHER;
1108 rs->sr_text = "SQL-backend error";
1113 rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1114 if ( rs->sr_err == LDAP_SUCCESS ) {
1115 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1117 op->ora_e->e_name.bv_val, 0, 0 );
1118 rs->sr_err = LDAP_ALREADY_EXISTS;
1124 * Get the parent dn and see if the corresponding entry exists.
1126 if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
1127 pdn = slap_empty_bv;
1130 dnParent( &op->ora_e->e_nname, &pdn );
1137 rs->sr_err = backsql_init_search( &bsi, &pdn,
1139 SLAP_NO_LIMIT, SLAP_NO_LIMIT,
1140 (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
1141 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
1142 if ( rs->sr_err != LDAP_SUCCESS ) {
1143 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1144 "could not retrieve addDN parent "
1145 "\"%s\" ID - %s matched=\"%s\"\n",
1147 rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
1148 rs->sr_matched ? rs->sr_matched : "(null)" );
1153 /* check "children" pseudo-attribute access to parent */
1154 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1155 NULL, ACL_WRITE, NULL ) )
1157 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1162 if ( get_assert( op ) &&
1163 ( test_filter( op, op->oq_add.rs_e, get_assertion( op ) )
1164 != LDAP_COMPARE_TRUE ) )
1166 rs->sr_err = LDAP_ASSERTION_FAILED;
1171 if ( !access_allowed_mask( op, op->ora_e,
1172 slap_schema.si_ad_entry,
1173 NULL, ACL_WRITE, NULL, &mask ) )
1175 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1181 * create_proc is executed; if expect_return is set, then
1182 * an output parameter is bound, which should contain
1183 * the id of the added row; otherwise the procedure
1184 * is expected to return the id as the first column of a select
1186 rc = backsql_Prepare( dbh, &sth, oc->bom_create_proc, 0 );
1187 if ( rc != SQL_SUCCESS ) {
1188 rs->sr_err = LDAP_OTHER;
1189 rs->sr_text = "SQL-backend error";
1195 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1196 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1197 if ( rc != SQL_SUCCESS ) {
1198 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1199 "error binding keyval parameter "
1200 "for objectClass %s\n",
1201 op->ora_e->e_name.bv_val,
1202 oc->bom_oc->soc_cname.bv_val, 0 );
1203 backsql_PrintErrors( bi->sql_db_env, dbh,
1205 SQLFreeStmt( sth, SQL_DROP );
1207 rs->sr_text = "SQL-backend error";
1208 rs->sr_err = LDAP_OTHER;
1215 if ( oc->bom_create_hint ) {
1216 at = attr_find( op->ora_e->e_attrs, oc->bom_create_hint );
1217 if ( at && at->a_vals ) {
1218 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1219 at->a_vals[0].bv_val,
1220 at->a_vals[0].bv_len );
1221 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1222 "create_proc hint: param = '%s'\n",
1223 at->a_vals[0].bv_val, 0, 0 );
1226 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1228 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1229 "create_proc hint (%s) not avalable\n",
1230 oc->bom_create_hint->ad_cname.bv_val,
1236 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1237 op->ora_e->e_name.bv_val, oc->bom_create_proc, 0 );
1238 rc = SQLExecute( sth );
1239 if ( rc != SQL_SUCCESS ) {
1240 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1241 "create_proc execution failed\n",
1242 op->ora_e->e_name.bv_val, 0, 0 );
1243 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1244 SQLFreeStmt( sth, SQL_DROP );
1245 rs->sr_err = LDAP_OTHER;
1246 rs->sr_text = "SQL-backend error";
1251 /* FIXME: after SQLExecute(), the row is already inserted
1252 * (at least with PostgreSQL and unixODBC); needs investigation */
1254 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1256 SQLINTEGER value_len;
1258 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1259 SQLFreeStmt( sth, SQL_DROP );
1261 rc = backsql_Prepare( dbh, &sth, oc->bom_create_keyval, 0 );
1262 if ( rc != SQL_SUCCESS ) {
1263 rs->sr_err = LDAP_OTHER;
1264 rs->sr_text = "SQL-backend error";
1269 rc = SQLExecute( sth );
1270 if ( rc != SQL_SUCCESS ) {
1271 rs->sr_err = LDAP_OTHER;
1272 rs->sr_text = "SQL-backend error";
1279 * the query to know the id of the inserted entry
1280 * must be embedded in the create procedure
1282 rc = SQLNumResultCols( sth, &ncols );
1283 if ( rc != SQL_SUCCESS ) {
1284 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1285 "create_proc result evaluation failed\n",
1286 op->ora_e->e_name.bv_val, 0, 0 );
1287 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1288 SQLFreeStmt( sth, SQL_DROP );
1289 rs->sr_err = LDAP_OTHER;
1290 rs->sr_text = "SQL-backend error";
1294 } else if ( ncols != 1 ) {
1295 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1296 "create_proc result is bogus (ncols=%d)\n",
1297 op->ora_e->e_name.bv_val, ncols, 0 );
1298 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1299 SQLFreeStmt( sth, SQL_DROP );
1300 rs->sr_err = LDAP_OTHER;
1301 rs->sr_text = "SQL-backend error";
1308 SQLCHAR colname[ 64 ];
1309 SQLSMALLINT name_len, col_type, col_scale, col_null;
1313 * FIXME: check whether col_type is compatible,
1314 * if it can be null and so on ...
1316 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1318 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1319 &name_len, &col_type,
1320 &col_prec, &col_scale, &col_null );
1324 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1325 (SQLPOINTER)&new_keyval,
1326 (SQLINTEGER)sizeof( new_keyval ),
1329 rc = SQLFetch( sth );
1331 if ( value_len <= 0 ) {
1332 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1333 "create_proc result is empty?\n",
1334 op->ora_e->e_name.bv_val, 0, 0 );
1335 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1336 SQLFreeStmt( sth, SQL_DROP );
1337 rs->sr_err = LDAP_OTHER;
1338 rs->sr_text = "SQL-backend error";
1344 SQLFreeStmt( sth, SQL_DROP );
1346 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1347 "create_proc returned keyval=%ld\n",
1348 op->ora_e->e_name.bv_val, new_keyval, 0 );
1350 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
1351 if ( rc != SQL_SUCCESS ) {
1352 rs->sr_err = LDAP_OTHER;
1353 rs->sr_text = "SQL-backend error";
1358 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1359 if ( rc != SQL_SUCCESS ) {
1360 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1361 "error binding DN parameter for objectClass %s\n",
1362 op->ora_e->e_name.bv_val,
1363 oc->bom_oc->soc_cname.bv_val, 0 );
1364 backsql_PrintErrors( bi->sql_db_env, dbh,
1366 SQLFreeStmt( sth, SQL_DROP );
1368 rs->sr_text = "SQL-backend error";
1369 rs->sr_err = LDAP_OTHER;
1374 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1375 if ( rc != SQL_SUCCESS ) {
1376 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1377 "error binding objectClass ID parameter "
1378 "for objectClass %s\n",
1379 op->ora_e->e_name.bv_val,
1380 oc->bom_oc->soc_cname.bv_val, 0 );
1381 backsql_PrintErrors( bi->sql_db_env, dbh,
1383 SQLFreeStmt( sth, SQL_DROP );
1385 rs->sr_text = "SQL-backend error";
1386 rs->sr_err = LDAP_OTHER;
1391 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &bsi.bsi_base_id.eid_id );
1392 if ( rc != SQL_SUCCESS ) {
1393 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1394 "error binding parent ID parameter "
1395 "for objectClass %s\n",
1396 op->ora_e->e_name.bv_val,
1397 oc->bom_oc->soc_cname.bv_val, 0 );
1398 backsql_PrintErrors( bi->sql_db_env, dbh,
1400 SQLFreeStmt( sth, SQL_DROP );
1402 rs->sr_text = "SQL-backend error";
1403 rs->sr_err = LDAP_OTHER;
1408 rc = backsql_BindParamInt( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1409 if ( rc != SQL_SUCCESS ) {
1410 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1411 "error binding entry ID parameter "
1412 "for objectClass %s\n",
1413 op->ora_e->e_name.bv_val,
1414 oc->bom_oc->soc_cname.bv_val, 0 );
1415 backsql_PrintErrors( bi->sql_db_env, dbh,
1417 SQLFreeStmt( sth, SQL_DROP );
1419 rs->sr_text = "SQL-backend error";
1420 rs->sr_err = LDAP_OTHER;
1425 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1426 bi->sql_insentry_stmt, op->ora_e->e_name.bv_val, 0 );
1427 #ifdef BACKSQL_ARBITRARY_KEY
1428 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1429 "p_id=%s, keyval=%ld\n",
1430 oc->bom_id, bsi.bsi_base_id.eid_id.bv_val, new_keyval );
1431 #else /* ! BACKSQL_ARBITRARY_KEY */
1432 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1433 "p_id=%ld, keyval=%ld\n",
1434 oc->bom_id, bsi.bsi_base_id.eid_id, new_keyval );
1435 #endif /* ! BACKSQL_ARBITRARY_KEY */
1436 rc = SQLExecute( sth );
1437 if ( rc != SQL_SUCCESS ) {
1438 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1439 "could not insert ldap_entries record\n",
1440 op->ora_e->e_name.bv_val, 0, 0 );
1441 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
1444 * execute delete_proc to delete data added !!!
1446 SQLFreeStmt( sth, SQL_DROP );
1447 rs->sr_err = LDAP_OTHER;
1448 rs->sr_text = "SQL-backend error";
1453 SQLFreeStmt( sth, SQL_DROP );
1455 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1456 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1457 "adding attribute \"%s\"\n",
1458 at->a_desc->ad_cname.bv_val, 0, 0 );
1462 * - the first occurrence of objectClass, which is used
1463 * to determine how to build the SQL entry (FIXME ?!?)
1464 * - operational attributes
1465 * - empty attributes (FIXME ?!?)
1467 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1471 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1472 at_objectClass = at;
1476 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1477 if ( rs->sr_err != LDAP_SUCCESS ) {
1483 if ( at_objectClass ) {
1484 rs->sr_err = backsql_add_attr( op, rs, dbh, oc,
1485 at_objectClass, new_keyval );
1486 if ( rs->sr_err != LDAP_SUCCESS ) {
1494 * Commit only if all operations succeed
1496 if ( sth != SQL_NULL_HSTMT ) {
1497 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
1499 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1500 CompletionType = SQL_COMMIT;
1503 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
1507 * FIXME: NOOP does not work for add -- it works for all
1508 * the other operations, and I don't get the reason :(
1510 * hint: there might be some autocommit in Postgres
1511 * so that when the unique id of the key table is
1512 * automatically increased, there's no rollback.
1513 * We might implement a "rollback" procedure consisting
1514 * in deleting that row.
1517 #ifdef SLAP_ACL_HONOR_DISCLOSE
1521 if ( e == op->ora_e && !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
1522 /* mask already collected */
1525 } else if ( e == &p && !access_allowed( op, &p,
1526 slap_schema.si_ad_entry, NULL,
1527 ACL_DISCLOSE, NULL ) )
1532 if ( disclose == 0 ) {
1533 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1535 rs->sr_matched = NULL;
1537 ber_bvarray_free( rs->sr_ref );
1542 #endif /* SLAP_ACL_HONOR_DISCLOSE */
1544 send_ldap_result( op, rs );
1546 if ( !BER_BVISNULL( &realdn )
1547 && realdn.bv_val != op->ora_e->e_name.bv_val )
1549 ch_free( realdn.bv_val );
1552 if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
1553 (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
1556 if ( !BER_BVISNULL( &p.e_nname ) ) {
1560 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1561 op->ora_e->e_name.bv_val,
1563 rs->sr_text ? rs->sr_text : "" );
1566 rs->sr_matched = NULL;
1568 ber_bvarray_free( rs->sr_ref );