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 ( BACKSQL_CHECK_SCHEMA( bi ) ) {
990 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
992 rs->sr_err = entry_schema_check( op->o_bd, op->ora_e, NULL, 0,
993 &rs->sr_text, textbuf, sizeof( textbuf ) );
994 if ( rs->sr_err != LDAP_SUCCESS ) {
995 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
996 "entry failed schema check -- aborting\n",
997 op->ora_e->e_name.bv_val, 0, 0 );
1003 /* search structuralObjectClass */
1004 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1005 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
1010 /* there must exist */
1012 char buf[ SLAP_TEXT_BUFLEN ];
1015 /* search structuralObjectClass */
1016 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1017 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1023 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1025 op->ora_e->e_name.bv_val, 0, 0 );
1026 rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
1031 rs->sr_err = structural_class( at->a_vals, &scname, NULL,
1032 &text, buf, sizeof( buf ) );
1033 if ( rs->sr_err != LDAP_SUCCESS ) {
1034 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1036 op->ora_e->e_name.bv_val, text, rs->sr_err );
1042 scname = at->a_vals[0];
1045 /* I guess we should play with sub/supertypes to find a suitable oc */
1046 oc = backsql_name2oc( bi, &scname );
1049 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1050 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1051 op->ora_e->e_name.bv_val,
1053 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1054 rs->sr_text = "operation not permitted within namingContext";
1059 if ( oc->bom_create_proc == NULL ) {
1060 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1061 "create procedure is not defined "
1062 "for structuralObjectClass \"%s\" - aborting\n",
1063 op->ora_e->e_name.bv_val,
1065 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1066 rs->sr_text = "operation not permitted within namingContext";
1070 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
1071 && oc->bom_create_keyval == NULL ) {
1072 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1073 "create procedure needs select procedure, "
1074 "but none is defined for structuralObjectClass \"%s\" "
1076 op->ora_e->e_name.bv_val,
1078 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1079 rs->sr_text = "operation not permitted within namingContext";
1084 rs->sr_err = backsql_get_db_conn( op, &dbh );
1085 if ( rs->sr_err != LDAP_SUCCESS ) {
1086 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1087 "could not get connection handle - exiting\n",
1088 op->ora_e->e_name.bv_val, 0, 0 );
1089 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1090 ? "SQL-backend error" : NULL;
1096 * Check if entry exists
1098 * NOTE: backsql_api_dn2odbc() is called explicitly because
1099 * we need the mucked DN to pass it to the create procedure.
1101 realdn = op->ora_e->e_name;
1102 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
1103 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1104 "backsql_api_dn2odbc(\"%s\") failed\n",
1105 op->ora_e->e_name.bv_val, realdn.bv_val, 0 );
1106 rs->sr_err = LDAP_OTHER;
1107 rs->sr_text = "SQL-backend error";
1112 rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1113 if ( rs->sr_err == LDAP_SUCCESS ) {
1114 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1116 op->ora_e->e_name.bv_val, 0, 0 );
1117 rs->sr_err = LDAP_ALREADY_EXISTS;
1123 * Get the parent dn and see if the corresponding entry exists.
1125 if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
1126 pdn = slap_empty_bv;
1129 dnParent( &op->ora_e->e_nname, &pdn );
1136 rs->sr_err = backsql_init_search( &bsi, &pdn,
1138 SLAP_NO_LIMIT, SLAP_NO_LIMIT,
1139 (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
1140 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
1141 if ( rs->sr_err != LDAP_SUCCESS ) {
1142 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1143 "could not retrieve addDN parent "
1144 "\"%s\" ID - %s matched=\"%s\"\n",
1146 rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
1147 rs->sr_matched ? rs->sr_matched : "(null)" );
1152 /* check "children" pseudo-attribute access to parent */
1153 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1154 NULL, ACL_WADD, NULL ) )
1156 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1161 if ( get_assert( op ) &&
1162 ( test_filter( op, op->oq_add.rs_e, get_assertion( op ) )
1163 != LDAP_COMPARE_TRUE ) )
1165 rs->sr_err = LDAP_ASSERTION_FAILED;
1170 if ( !access_allowed_mask( op, op->ora_e,
1171 slap_schema.si_ad_entry,
1172 NULL, ACL_WADD, NULL, &mask ) )
1174 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1180 * create_proc is executed; if expect_return is set, then
1181 * an output parameter is bound, which should contain
1182 * the id of the added row; otherwise the procedure
1183 * is expected to return the id as the first column of a select
1185 rc = backsql_Prepare( dbh, &sth, oc->bom_create_proc, 0 );
1186 if ( rc != SQL_SUCCESS ) {
1187 rs->sr_err = LDAP_OTHER;
1188 rs->sr_text = "SQL-backend error";
1194 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1195 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1196 if ( rc != SQL_SUCCESS ) {
1197 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1198 "error binding keyval parameter "
1199 "for objectClass %s\n",
1200 op->ora_e->e_name.bv_val,
1201 oc->bom_oc->soc_cname.bv_val, 0 );
1202 backsql_PrintErrors( bi->sql_db_env, dbh,
1204 SQLFreeStmt( sth, SQL_DROP );
1206 rs->sr_text = "SQL-backend error";
1207 rs->sr_err = LDAP_OTHER;
1214 if ( oc->bom_create_hint ) {
1215 at = attr_find( op->ora_e->e_attrs, oc->bom_create_hint );
1216 if ( at && at->a_vals ) {
1217 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1218 at->a_vals[0].bv_val,
1219 at->a_vals[0].bv_len );
1220 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1221 "create_proc hint: param = '%s'\n",
1222 at->a_vals[0].bv_val, 0, 0 );
1225 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1227 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1228 "create_proc hint (%s) not avalable\n",
1229 oc->bom_create_hint->ad_cname.bv_val,
1235 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1236 op->ora_e->e_name.bv_val, oc->bom_create_proc, 0 );
1237 rc = SQLExecute( sth );
1238 if ( rc != SQL_SUCCESS ) {
1239 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1240 "create_proc execution failed\n",
1241 op->ora_e->e_name.bv_val, 0, 0 );
1242 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1243 SQLFreeStmt( sth, SQL_DROP );
1244 rs->sr_err = LDAP_OTHER;
1245 rs->sr_text = "SQL-backend error";
1250 /* FIXME: after SQLExecute(), the row is already inserted
1251 * (at least with PostgreSQL and unixODBC); needs investigation */
1253 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1255 SQLINTEGER value_len;
1257 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1258 SQLFreeStmt( sth, SQL_DROP );
1260 rc = backsql_Prepare( dbh, &sth, oc->bom_create_keyval, 0 );
1261 if ( rc != SQL_SUCCESS ) {
1262 rs->sr_err = LDAP_OTHER;
1263 rs->sr_text = "SQL-backend error";
1268 rc = SQLExecute( sth );
1269 if ( rc != SQL_SUCCESS ) {
1270 rs->sr_err = LDAP_OTHER;
1271 rs->sr_text = "SQL-backend error";
1278 * the query to know the id of the inserted entry
1279 * must be embedded in the create procedure
1281 rc = SQLNumResultCols( sth, &ncols );
1282 if ( rc != SQL_SUCCESS ) {
1283 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1284 "create_proc result evaluation failed\n",
1285 op->ora_e->e_name.bv_val, 0, 0 );
1286 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1287 SQLFreeStmt( sth, SQL_DROP );
1288 rs->sr_err = LDAP_OTHER;
1289 rs->sr_text = "SQL-backend error";
1293 } else if ( ncols != 1 ) {
1294 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1295 "create_proc result is bogus (ncols=%d)\n",
1296 op->ora_e->e_name.bv_val, ncols, 0 );
1297 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1298 SQLFreeStmt( sth, SQL_DROP );
1299 rs->sr_err = LDAP_OTHER;
1300 rs->sr_text = "SQL-backend error";
1307 SQLCHAR colname[ 64 ];
1308 SQLSMALLINT name_len, col_type, col_scale, col_null;
1312 * FIXME: check whether col_type is compatible,
1313 * if it can be null and so on ...
1315 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1317 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1318 &name_len, &col_type,
1319 &col_prec, &col_scale, &col_null );
1323 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1324 (SQLPOINTER)&new_keyval,
1325 (SQLINTEGER)sizeof( new_keyval ),
1328 rc = SQLFetch( sth );
1330 if ( value_len <= 0 ) {
1331 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1332 "create_proc result is empty?\n",
1333 op->ora_e->e_name.bv_val, 0, 0 );
1334 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1335 SQLFreeStmt( sth, SQL_DROP );
1336 rs->sr_err = LDAP_OTHER;
1337 rs->sr_text = "SQL-backend error";
1343 SQLFreeStmt( sth, SQL_DROP );
1345 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1346 "create_proc returned keyval=%ld\n",
1347 op->ora_e->e_name.bv_val, new_keyval, 0 );
1349 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
1350 if ( rc != SQL_SUCCESS ) {
1351 rs->sr_err = LDAP_OTHER;
1352 rs->sr_text = "SQL-backend error";
1357 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1358 if ( rc != SQL_SUCCESS ) {
1359 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1360 "error binding DN parameter for objectClass %s\n",
1361 op->ora_e->e_name.bv_val,
1362 oc->bom_oc->soc_cname.bv_val, 0 );
1363 backsql_PrintErrors( bi->sql_db_env, dbh,
1365 SQLFreeStmt( sth, SQL_DROP );
1367 rs->sr_text = "SQL-backend error";
1368 rs->sr_err = LDAP_OTHER;
1373 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1374 if ( rc != SQL_SUCCESS ) {
1375 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1376 "error binding objectClass ID parameter "
1377 "for objectClass %s\n",
1378 op->ora_e->e_name.bv_val,
1379 oc->bom_oc->soc_cname.bv_val, 0 );
1380 backsql_PrintErrors( bi->sql_db_env, dbh,
1382 SQLFreeStmt( sth, SQL_DROP );
1384 rs->sr_text = "SQL-backend error";
1385 rs->sr_err = LDAP_OTHER;
1390 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &bsi.bsi_base_id.eid_id );
1391 if ( rc != SQL_SUCCESS ) {
1392 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1393 "error binding parent ID parameter "
1394 "for objectClass %s\n",
1395 op->ora_e->e_name.bv_val,
1396 oc->bom_oc->soc_cname.bv_val, 0 );
1397 backsql_PrintErrors( bi->sql_db_env, dbh,
1399 SQLFreeStmt( sth, SQL_DROP );
1401 rs->sr_text = "SQL-backend error";
1402 rs->sr_err = LDAP_OTHER;
1407 rc = backsql_BindParamInt( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1408 if ( rc != SQL_SUCCESS ) {
1409 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1410 "error binding entry ID parameter "
1411 "for objectClass %s\n",
1412 op->ora_e->e_name.bv_val,
1413 oc->bom_oc->soc_cname.bv_val, 0 );
1414 backsql_PrintErrors( bi->sql_db_env, dbh,
1416 SQLFreeStmt( sth, SQL_DROP );
1418 rs->sr_text = "SQL-backend error";
1419 rs->sr_err = LDAP_OTHER;
1424 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1425 bi->sql_insentry_stmt, op->ora_e->e_name.bv_val, 0 );
1426 #ifdef BACKSQL_ARBITRARY_KEY
1427 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1428 "p_id=%s, keyval=%ld\n",
1429 oc->bom_id, bsi.bsi_base_id.eid_id.bv_val, new_keyval );
1430 #else /* ! BACKSQL_ARBITRARY_KEY */
1431 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1432 "p_id=%ld, keyval=%ld\n",
1433 oc->bom_id, bsi.bsi_base_id.eid_id, new_keyval );
1434 #endif /* ! BACKSQL_ARBITRARY_KEY */
1435 rc = SQLExecute( sth );
1436 if ( rc != SQL_SUCCESS ) {
1437 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1438 "could not insert ldap_entries record\n",
1439 op->ora_e->e_name.bv_val, 0, 0 );
1440 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
1443 * execute delete_proc to delete data added !!!
1445 SQLFreeStmt( sth, SQL_DROP );
1446 rs->sr_err = LDAP_OTHER;
1447 rs->sr_text = "SQL-backend error";
1452 SQLFreeStmt( sth, SQL_DROP );
1454 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1455 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1456 "adding attribute \"%s\"\n",
1457 at->a_desc->ad_cname.bv_val, 0, 0 );
1461 * - the first occurrence of objectClass, which is used
1462 * to determine how to build the SQL entry (FIXME ?!?)
1463 * - operational attributes
1464 * - empty attributes (FIXME ?!?)
1466 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1470 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1471 at_objectClass = at;
1475 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1476 if ( rs->sr_err != LDAP_SUCCESS ) {
1482 if ( at_objectClass ) {
1483 rs->sr_err = backsql_add_attr( op, rs, dbh, oc,
1484 at_objectClass, new_keyval );
1485 if ( rs->sr_err != LDAP_SUCCESS ) {
1493 * Commit only if all operations succeed
1495 if ( sth != SQL_NULL_HSTMT ) {
1496 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
1498 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1499 CompletionType = SQL_COMMIT;
1502 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
1506 * FIXME: NOOP does not work for add -- it works for all
1507 * the other operations, and I don't get the reason :(
1509 * hint: there might be some autocommit in Postgres
1510 * so that when the unique id of the key table is
1511 * automatically increased, there's no rollback.
1512 * We might implement a "rollback" procedure consisting
1513 * in deleting that row.
1516 #ifdef SLAP_ACL_HONOR_DISCLOSE
1520 if ( e == op->ora_e && !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
1521 /* mask already collected */
1524 } else if ( e == &p && !access_allowed( op, &p,
1525 slap_schema.si_ad_entry, NULL,
1526 ACL_DISCLOSE, NULL ) )
1531 if ( disclose == 0 ) {
1532 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1534 rs->sr_matched = NULL;
1536 ber_bvarray_free( rs->sr_ref );
1541 #endif /* SLAP_ACL_HONOR_DISCLOSE */
1543 send_ldap_result( op, rs );
1545 if ( !BER_BVISNULL( &realdn )
1546 && realdn.bv_val != op->ora_e->e_name.bv_val )
1548 ch_free( realdn.bv_val );
1551 if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
1552 (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 );
1555 if ( !BER_BVISNULL( &p.e_nname ) ) {
1559 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1560 op->ora_e->e_name.bv_val,
1562 rs->sr_text ? rs->sr_text : "" );
1565 rs->sr_matched = NULL;
1567 ber_bvarray_free( rs->sr_ref );