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_attr_skip(ad, vals) \
48 ( (ad) == slap_schema.si_ad_objectClass \
49 && (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
50 || is_at_operational( (ad)->ad_type ) \
51 || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
55 backsql_modify_delete_all_values(
59 backsql_entryID *e_id,
60 backsql_at_map_rec *at )
62 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
64 SQLHSTMT asth = SQL_NULL_HSTMT;
68 if ( at->bam_delete_proc == NULL ) {
69 Debug( LDAP_DEBUG_TRACE,
70 " backsql_modify_delete_all_values(): "
71 "missing attribute value delete procedure "
73 at->bam_ad->ad_cname.bv_val, 0, 0 );
74 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
75 rs->sr_text = "SQL-backend error";
76 return rs->sr_err = LDAP_OTHER;
82 rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
83 if ( rc != SQL_SUCCESS ) {
84 Debug( LDAP_DEBUG_TRACE,
85 " backsql_modify_delete_all_values(): "
86 "error preparing attribute value select query "
88 at->bam_query, 0, 0 );
89 backsql_PrintErrors( bi->sql_db_env, dbh,
92 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
93 rs->sr_text = "SQL-backend error";
94 return rs->sr_err = LDAP_OTHER;
99 rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
100 if ( rc != SQL_SUCCESS ) {
101 Debug( LDAP_DEBUG_TRACE,
102 " backsql_modify_delete_all_values(): "
103 "error binding key value parameter "
104 "to attribute value select query\n",
106 backsql_PrintErrors( bi->sql_db_env, dbh,
108 SQLFreeStmt( asth, SQL_DROP );
110 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
111 rs->sr_text = "SQL-backend error";
112 return rs->sr_err = LDAP_OTHER;
118 rc = SQLExecute( asth );
119 if ( !BACKSQL_SUCCESS( rc ) ) {
120 Debug( LDAP_DEBUG_TRACE,
121 " backsql_modify_delete_all_values(): "
122 "error executing attribute value select query\n",
124 backsql_PrintErrors( bi->sql_db_env, dbh,
126 SQLFreeStmt( asth, SQL_DROP );
128 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
129 rs->sr_text = "SQL-backend error";
130 return rs->sr_err = LDAP_OTHER;
136 backsql_BindRowAsStrings( asth, &row );
137 for ( rc = SQLFetch( asth );
138 BACKSQL_SUCCESS( rc );
139 rc = SQLFetch( asth ) )
142 /* first parameter no, parameter order */
143 SQLUSMALLINT pno, po;
144 /* procedure return code */
145 int prc = LDAP_SUCCESS;
147 for ( i = 0; i < row.ncols; i++ ) {
148 SQLHSTMT sth = SQL_NULL_HSTMT;
151 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
152 if ( rc != SQL_SUCCESS ) {
153 Debug( LDAP_DEBUG_TRACE,
154 " backsql_modify_delete_all_values(): "
155 "error preparing attribute value "
158 at->bam_delete_proc, 0, 0 );
159 backsql_PrintErrors( bi->sql_db_env, dbh,
162 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
163 rs->sr_text = "SQL-backend error";
164 return rs->sr_err = LDAP_OTHER;
170 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
172 rc = backsql_BindParamInt( sth, 1,
173 SQL_PARAM_OUTPUT, &prc );
174 if ( rc != SQL_SUCCESS ) {
175 Debug( LDAP_DEBUG_TRACE,
176 " backsql_modify_delete_all_values(): "
177 "error binding output parameter for %s[%d]\n",
178 at->bam_ad->ad_cname.bv_val, i, 0 );
179 backsql_PrintErrors( bi->sql_db_env, dbh,
181 SQLFreeStmt( sth, SQL_DROP );
183 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
184 rs->sr_text = "SQL-backend error";
185 return rs->sr_err = LDAP_OTHER;
194 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
195 rc = backsql_BindParamID( sth, pno + 1 + po,
196 SQL_PARAM_INPUT, &e_id->eid_keyval );
197 if ( rc != SQL_SUCCESS ) {
198 Debug( LDAP_DEBUG_TRACE,
199 " backsql_modify_delete_all_values(): "
200 "error binding keyval parameter for %s[%d]\n",
201 at->bam_ad->ad_cname.bv_val, i, 0 );
202 backsql_PrintErrors( bi->sql_db_env, dbh,
204 SQLFreeStmt( sth, SQL_DROP );
206 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
207 rs->sr_text = "SQL-backend error";
208 return rs->sr_err = LDAP_OTHER;
213 #ifdef BACKSQL_ARBITRARY_KEY
214 Debug( LDAP_DEBUG_TRACE,
215 " backsql_modify_delete_all_values() "
217 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
218 #else /* ! BACKSQL_ARBITRARY_KEY */
219 Debug( LDAP_DEBUG_TRACE,
220 " backsql_modify_delete_all_values() "
222 pno + 1 + po, e_id->eid_keyval, 0 );
223 #endif /* ! BACKSQL_ARBITRARY_KEY */
226 * check for syntax needed here
227 * maybe need binary bind?
229 col_len = strlen( row.cols[ i ] );
230 rc = backsql_BindParamStr( sth, pno + 2 - po,
231 SQL_PARAM_INPUT, row.cols[ i ], col_len );
232 if ( rc != SQL_SUCCESS ) {
233 Debug( LDAP_DEBUG_TRACE,
234 " backsql_modify_delete_all_values(): "
235 "error binding value parameter for %s[%d]\n",
236 at->bam_ad->ad_cname.bv_val, i, 0 );
237 backsql_PrintErrors( bi->sql_db_env, dbh,
239 SQLFreeStmt( sth, SQL_DROP );
241 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
242 rs->sr_text = "SQL-backend error";
243 return rs->sr_err = LDAP_OTHER;
249 Debug( LDAP_DEBUG_TRACE,
250 " backsql_modify_delete_all_values(): "
251 "arg%d=%s; executing \"%s\"\n",
252 pno + 2 - po, row.cols[ i ],
253 at->bam_delete_proc );
254 rc = SQLExecute( sth );
255 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
256 rs->sr_err = LDAP_SUCCESS;
259 Debug( LDAP_DEBUG_TRACE,
260 " backsql_modify_delete_all_values(): "
262 "execution failed (rc=%d, prc=%d)\n",
264 if ( prc != LDAP_SUCCESS ) {
265 /* SQL procedure executed fine
266 * but returned an error */
267 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
268 rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
269 SQLFreeStmt( sth, SQL_DROP );
273 backsql_PrintErrors( bi->sql_db_env, dbh,
275 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
277 rs->sr_err = LDAP_OTHER;
278 rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
279 SQLFreeStmt( sth, SQL_DROP );
284 SQLFreeStmt( sth, SQL_DROP );
287 backsql_FreeRow( &row );
288 SQLFreeStmt( asth, SQL_DROP );
294 backsql_modify_internal(
298 backsql_oc_map_rec *oc,
299 backsql_entryID *e_id,
300 Modifications *modlist )
302 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
304 SQLHSTMT sth = SQL_NULL_HSTMT;
307 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
308 "traversing modifications list\n", 0, 0, 0 );
310 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
311 AttributeDescription *ad;
313 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
317 /* NOTE: some day we'll have to pass
318 * the normalized values as well */
321 backsql_at_map_rec *at = NULL;
322 struct berval *at_val;
324 /* first parameter position, parameter order */
325 SQLUSMALLINT pno, po;
326 /* procedure return code */
327 int prc = LDAP_SUCCESS;
329 ad = ml->sml_mod.sm_desc;
330 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
331 sm_values = ml->sml_mod.sm_values;
333 sm_nvalues = ml->sml_mod.sm_nvalues;
336 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
337 "modifying attribute \"%s\" (%s) according to "
338 "mappings for objectClass \"%s\"\n",
339 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
341 if ( backsql_attr_skip( ad, sm_values ) ) {
345 at = backsql_ad2at( oc, ad );
347 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
348 "attribute \"%s\" is not registered "
349 "in objectClass \"%s\"\n",
350 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
352 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
353 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
354 rs->sr_text = "operation not permitted "
355 "within namingContext";
363 case LDAP_MOD_REPLACE: {
364 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
365 "replacing values for attribute \"%s\"\n",
366 at->bam_ad->ad_cname.bv_val, 0, 0 );
368 if ( at->bam_add_proc == NULL ) {
369 Debug( LDAP_DEBUG_TRACE,
370 " backsql_modify_internal(): "
371 "add procedure is not defined "
372 "for attribute \"%s\" "
373 "- unable to perform replacements\n",
374 at->bam_ad->ad_cname.bv_val, 0, 0 );
376 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
377 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
378 rs->sr_text = "operation not permitted "
379 "within namingContext";
386 if ( at->bam_delete_proc == NULL ) {
387 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
388 Debug( LDAP_DEBUG_TRACE,
389 " backsql_modify_internal(): "
390 "delete procedure is not defined "
391 "for attribute \"%s\"\n",
392 at->bam_ad->ad_cname.bv_val, 0, 0 );
394 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
395 rs->sr_text = "operation not permitted "
396 "within namingContext";
400 Debug( LDAP_DEBUG_TRACE,
401 " backsql_modify_internal(): "
402 "delete procedure is not defined "
403 "for attribute \"%s\" "
405 at->bam_ad->ad_cname.bv_val, 0, 0 );
411 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
412 if ( rs->sr_err != LDAP_SUCCESS ) {
416 /* LDAP_MOD_DELETE gets here if all values must be deleted */
417 if ( sm_op == LDAP_MOD_DELETE ) {
423 * PASSTHROUGH - to add new attributes -- do NOT add break
426 /* case SLAP_MOD_SOFTADD: */
428 if ( at->bam_add_proc == NULL ) {
429 Debug( LDAP_DEBUG_TRACE,
430 " backsql_modify_internal(): "
431 "add procedure is not defined "
432 "for attribute \"%s\"\n",
433 at->bam_ad->ad_cname.bv_val, 0, 0 );
435 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
436 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
437 rs->sr_text = "operation not permitted "
438 "within namingContext";
445 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
446 "adding new values for attribute \"%s\"\n",
447 at->bam_ad->ad_cname.bv_val, 0, 0 );
449 /* can't add a NULL val array */
450 assert( sm_values != NULL );
452 for ( i = 0, at_val = sm_values;
453 !BER_BVISNULL( at_val );
456 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
457 if ( rc != SQL_SUCCESS ) {
458 Debug( LDAP_DEBUG_TRACE,
459 " backsql_modify_internal(): "
460 "error preparing add query\n",
462 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
464 rs->sr_err = LDAP_OTHER;
465 rs->sr_text = "SQL-backend error";
469 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
471 rc = backsql_BindParamInt( sth, 1,
472 SQL_PARAM_OUTPUT, &prc );
473 if ( rc != SQL_SUCCESS ) {
474 Debug( LDAP_DEBUG_TRACE,
475 " backsql_modify_internal(): "
476 "error binding output parameter for %s[%d]\n",
477 at->bam_ad->ad_cname.bv_val, i, 0 );
478 backsql_PrintErrors( bi->sql_db_env, dbh,
480 SQLFreeStmt( sth, SQL_DROP );
482 rs->sr_text = "SQL-backend error";
483 rs->sr_err = LDAP_OTHER;
490 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
491 rc = backsql_BindParamID( sth, pno + 1 + po,
492 SQL_PARAM_INPUT, &e_id->eid_keyval );
493 if ( rc != SQL_SUCCESS ) {
494 Debug( LDAP_DEBUG_TRACE,
495 " backsql_modify_internal(): "
496 "error binding keyval parameter for %s[%d]\n",
497 at->bam_ad->ad_cname.bv_val, i, 0 );
498 backsql_PrintErrors( bi->sql_db_env, dbh,
500 SQLFreeStmt( sth, SQL_DROP );
502 rs->sr_text = "SQL-backend error";
503 rs->sr_err = LDAP_OTHER;
506 #ifdef BACKSQL_ARBITRARY_KEY
507 Debug( LDAP_DEBUG_TRACE,
508 " backsql_modify_internal(): "
510 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
511 #else /* ! BACKSQL_ARBITRARY_KEY */
512 Debug( LDAP_DEBUG_TRACE,
513 " backsql_modify_internal(): "
515 pno + 1 + po, e_id->eid_keyval, 0 );
516 #endif /* ! BACKSQL_ARBITRARY_KEY */
519 * check for syntax needed here
520 * maybe need binary bind?
522 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
523 SQL_PARAM_INPUT, at_val );
524 if ( rc != SQL_SUCCESS ) {
525 Debug( LDAP_DEBUG_TRACE,
526 " backsql_modify_internal(): "
527 "error binding value parameter for %s[%d]\n",
528 at->bam_ad->ad_cname.bv_val, i, 0 );
529 backsql_PrintErrors( bi->sql_db_env, dbh,
531 SQLFreeStmt( sth, SQL_DROP );
533 rs->sr_text = "SQL-backend error";
534 rs->sr_err = LDAP_OTHER;
537 Debug( LDAP_DEBUG_TRACE,
538 " backsql_modify_internal(): "
539 "arg%d=\"%s\"; executing \"%s\"\n",
540 pno + 2 - po, at_val->bv_val,
543 rc = SQLExecute( sth );
544 if ( rc != SQL_SUCCESS ) {
545 Debug( LDAP_DEBUG_TRACE,
546 " backsql_modify_internal(): "
547 "add_proc execution failed\n",
549 backsql_PrintErrors( bi->sql_db_env,
552 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
553 SQLFreeStmt( sth, SQL_DROP );
554 rs->sr_err = LDAP_OTHER;
555 rs->sr_text = "SQL-backend error";
559 SQLFreeStmt( sth, SQL_DROP );
563 case LDAP_MOD_DELETE:
564 if ( at->bam_delete_proc == NULL ) {
565 Debug( LDAP_DEBUG_TRACE,
566 " backsql_modify_internal(): "
567 "delete procedure is not defined "
568 "for attribute \"%s\"\n",
569 at->bam_ad->ad_cname.bv_val, 0, 0 );
571 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
572 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
573 rs->sr_text = "operation not permitted "
574 "within namingContext";
581 if ( sm_values == NULL ) {
582 Debug( LDAP_DEBUG_TRACE,
583 " backsql_modify_internal(): "
584 "no values given to delete "
585 "for attribute \"%s\" "
586 "-- deleting all values\n",
587 at->bam_ad->ad_cname.bv_val, 0, 0 );
591 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
592 "deleting values for attribute \"%s\"\n",
593 at->bam_ad->ad_cname.bv_val, 0, 0 );
595 for ( i = 0, at_val = sm_values;
596 !BER_BVISNULL( at_val );
600 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
601 if ( rc != SQL_SUCCESS ) {
602 Debug( LDAP_DEBUG_TRACE,
603 " backsql_modify_internal(): "
604 "error preparing delete query\n",
606 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
608 rs->sr_err = LDAP_OTHER;
609 rs->sr_text = "SQL-backend error";
613 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
615 rc = backsql_BindParamInt( sth, 1,
616 SQL_PARAM_OUTPUT, &prc );
617 if ( rc != SQL_SUCCESS ) {
618 Debug( LDAP_DEBUG_TRACE,
619 " backsql_modify_internal(): "
620 "error binding output parameter for %s[%d]\n",
621 at->bam_ad->ad_cname.bv_val, i, 0 );
622 backsql_PrintErrors( bi->sql_db_env, dbh,
624 SQLFreeStmt( sth, SQL_DROP );
626 rs->sr_text = "SQL-backend error";
627 rs->sr_err = LDAP_OTHER;
634 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
635 rc = backsql_BindParamID( sth, pno + 1 + po,
636 SQL_PARAM_INPUT, &e_id->eid_keyval );
637 if ( rc != SQL_SUCCESS ) {
638 Debug( LDAP_DEBUG_TRACE,
639 " backsql_modify_internal(): "
640 "error binding keyval parameter for %s[%d]\n",
641 at->bam_ad->ad_cname.bv_val, i, 0 );
642 backsql_PrintErrors( bi->sql_db_env, dbh,
644 SQLFreeStmt( sth, SQL_DROP );
646 rs->sr_text = "SQL-backend error";
647 rs->sr_err = LDAP_OTHER;
650 #ifdef BACKSQL_ARBITRARY_KEY
651 Debug( LDAP_DEBUG_TRACE,
652 " backsql_modify_internal(): "
654 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
655 #else /* ! BACKSQL_ARBITRARY_KEY */
656 Debug( LDAP_DEBUG_TRACE,
657 " backsql_modify_internal(): "
659 pno + 1 + po, e_id->eid_keyval, 0 );
660 #endif /* ! BACKSQL_ARBITRARY_KEY */
663 * check for syntax needed here
664 * maybe need binary bind?
666 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
667 SQL_PARAM_INPUT, at_val );
668 if ( rc != SQL_SUCCESS ) {
669 Debug( LDAP_DEBUG_TRACE,
670 " backsql_modify_internal(): "
671 "error binding value parameter for %s[%d]\n",
672 at->bam_ad->ad_cname.bv_val, i, 0 );
673 backsql_PrintErrors( bi->sql_db_env, dbh,
675 SQLFreeStmt( sth, SQL_DROP );
677 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
678 rs->sr_text = "SQL-backend error";
679 rs->sr_err = LDAP_OTHER;
684 Debug( LDAP_DEBUG_TRACE,
685 " backsql_modify_internal(): "
686 "executing \"%s\"\n",
687 at->bam_delete_proc, 0, 0 );
688 rc = SQLExecute( sth );
689 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS )
691 rs->sr_err = LDAP_SUCCESS;
694 Debug( LDAP_DEBUG_TRACE,
695 " backsql_modify_internal(): "
696 "delete_proc execution "
697 "failed (rc=%d, prc=%d)\n",
700 if ( prc != LDAP_SUCCESS ) {
701 /* SQL procedure executed fine
702 * but returned an error */
703 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
704 rs->sr_text = at->bam_ad->ad_cname.bv_val;
708 backsql_PrintErrors( bi->sql_db_env,
710 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
712 SQLFreeStmt( sth, SQL_DROP );
713 rs->sr_err = LDAP_OTHER;
714 rs->sr_text = at->bam_ad->ad_cname.bv_val;
719 SQLFreeStmt( sth, SQL_DROP );
723 case LDAP_MOD_INCREMENT:
724 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
725 "increment not supported yet\n", 0, 0, 0 );
726 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
727 rs->sr_err = LDAP_OTHER;
728 rs->sr_text = "SQL-backend error";
736 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
738 rs->sr_text ? ": " : "",
739 rs->sr_text ? rs->sr_text : "" );
742 * FIXME: should fail in case one change fails?
752 backsql_oc_map_rec *oc,
754 unsigned long new_keyval )
756 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
757 backsql_at_map_rec *at_rec = NULL;
758 struct berval *at_val;
761 SQLUSMALLINT currpos;
762 SQLHSTMT sth = SQL_NULL_HSTMT;
764 at_rec = backsql_ad2at( oc, at->a_desc );
766 if ( at_rec == NULL ) {
767 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
768 "attribute \"%s\" is not registered "
769 "in objectclass \"%s\"\n",
770 op->oq_add.rs_e->e_name.bv_val,
771 at->a_desc->ad_cname.bv_val,
772 BACKSQL_OC_NAME( oc ) );
774 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
775 rs->sr_text = "operation not permitted "
776 "within namingContext";
777 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
783 if ( at_rec->bam_add_proc == NULL ) {
784 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
785 "add procedure is not defined "
786 "for attribute \"%s\" "
787 "of structuralObjectClass \"%s\"\n",
788 op->oq_add.rs_e->e_name.bv_val,
789 at->a_desc->ad_cname.bv_val,
790 BACKSQL_OC_NAME( oc ) );
792 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
793 rs->sr_text = "operation not permitted "
794 "within namingContext";
795 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
801 for ( i = 0, at_val = &at->a_vals[ i ];
802 !BER_BVISNULL( at_val );
803 i++, at_val = &at->a_vals[ i ] )
805 /* procedure return code */
806 int prc = LDAP_SUCCESS;
807 /* first parameter #, parameter order */
808 SQLUSMALLINT pno, po;
809 char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
812 * Do not deal with the objectClass that is used
815 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
816 if ( dn_match( at_val, &oc->bom_oc->soc_cname ) )
822 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
823 if ( rc != SQL_SUCCESS ) {
825 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
826 rs->sr_text = "SQL-backend error";
827 return rs->sr_err = LDAP_OTHER;
833 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
835 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
836 if ( rc != SQL_SUCCESS ) {
837 Debug( LDAP_DEBUG_TRACE,
838 " backsql_add_attr(): "
839 "error binding output parameter for %s[%d]\n",
840 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
841 backsql_PrintErrors( bi->sql_db_env, dbh,
843 SQLFreeStmt( sth, SQL_DROP );
845 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
846 rs->sr_text = "SQL-backend error";
847 return rs->sr_err = LDAP_OTHER;
857 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
858 currpos = pno + 1 + po;
859 rc = backsql_BindParamInt( sth, currpos,
860 SQL_PARAM_INPUT, &new_keyval );
861 if ( rc != SQL_SUCCESS ) {
862 Debug( LDAP_DEBUG_TRACE,
863 " backsql_add_attr(): "
864 "error binding keyval parameter for %s[%d]\n",
865 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
866 backsql_PrintErrors( bi->sql_db_env, dbh,
868 SQLFreeStmt( sth, SQL_DROP );
870 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
871 rs->sr_text = "SQL-backend error";
872 return rs->sr_err = LDAP_OTHER;
878 currpos = pno + 2 - po;
881 * check for syntax needed here
882 * maybe need binary bind?
885 rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
886 if ( rc != SQL_SUCCESS ) {
887 Debug( LDAP_DEBUG_TRACE,
888 " backsql_add_attr(): "
889 "error binding value parameter for %s[%d]\n",
890 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
891 backsql_PrintErrors( bi->sql_db_env, dbh,
893 SQLFreeStmt( sth, SQL_DROP );
895 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
896 rs->sr_text = "SQL-backend error";
897 return rs->sr_err = LDAP_OTHER;
904 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
906 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
907 "executing \"%s\" %s\n",
908 op->oq_add.rs_e->e_name.bv_val,
909 at_rec->bam_add_proc, logbuf );
911 rc = SQLExecute( sth );
912 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
913 rs->sr_err = LDAP_SUCCESS;
916 Debug( LDAP_DEBUG_TRACE,
917 " backsql_add_attr(\"%s\"): "
918 "add_proc execution failed (rc=%d, prc=%d)\n",
919 op->oq_add.rs_e->e_name.bv_val, rc, prc );
920 if ( prc != LDAP_SUCCESS ) {
921 /* SQL procedure executed fine
922 * but returned an error */
923 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
924 rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
925 SQLFreeStmt( sth, SQL_DROP );
929 backsql_PrintErrors( bi->sql_db_env, dbh,
931 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
932 rs->sr_err = LDAP_OTHER;
933 rs->sr_text = op->oq_add.rs_e->e_name.bv_val;
934 SQLFreeStmt( sth, SQL_DROP );
939 SQLFreeStmt( sth, SQL_DROP );
946 backsql_add( Operation *op, SlapReply *rs )
948 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
949 SQLHDBC dbh = SQL_NULL_HDBC;
950 SQLHSTMT sth = SQL_NULL_HSTMT;
951 unsigned long new_keyval = 0;
953 backsql_oc_map_rec *oc = NULL;
954 backsql_entryID parent_id = BACKSQL_ENTRYID_INIT;
957 *at_objectClass = NULL;
959 struct berval realdn = BER_BVNULL;
962 #ifdef BACKSQL_SYNCPROV
964 * NOTE: fake successful result to force contextCSN to be bumped up
967 char buf[ LDAP_LUTIL_CSNSTR_BUFSIZE ];
968 struct berval csn = BER_BVNULL;
970 slap_get_csn( op, buf, sizeof( buf ), &csn, 1 );
972 rs->sr_err = LDAP_SUCCESS;
973 send_ldap_result( op, rs );
975 slap_graduate_commit_csn( op );
979 #endif /* BACKSQL_SYNCPROV */
981 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
982 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
985 if ( global_schemacheck ) {
986 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
988 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e,
990 &rs->sr_text, textbuf, sizeof( textbuf ) );
991 if ( rs->sr_err != LDAP_SUCCESS ) {
992 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
993 "entry failed schema check -- aborting\n",
994 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
999 /* search structural objectClass */
1000 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
1001 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
1006 /* there must exist */
1007 assert( at != NULL );
1009 /* I guess we should play with sub/supertypes to find a suitable oc */
1010 oc = backsql_name2oc( bi, &at->a_vals[0] );
1013 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1014 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1015 op->oq_add.rs_e->e_name.bv_val,
1016 at->a_vals[0].bv_val, 0 );
1017 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1018 rs->sr_text = "operation not permitted within namingContext";
1022 if ( oc->bom_create_proc == NULL ) {
1023 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1024 "create procedure is not defined "
1025 "for structuralObjectClass \"%s\" - aborting\n",
1026 op->oq_add.rs_e->e_name.bv_val,
1027 at->a_vals[0].bv_val, 0 );
1028 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1029 rs->sr_text = "operation not permitted within namingContext";
1032 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
1033 && oc->bom_create_keyval == NULL ) {
1034 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1035 "create procedure needs select procedure, "
1036 "but none is defined for structuralObjectClass \"%s\" "
1038 op->oq_add.rs_e->e_name.bv_val,
1039 at->a_vals[0].bv_val, 0 );
1040 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1041 rs->sr_text = "operation not permitted within namingContext";
1045 rs->sr_err = backsql_get_db_conn( op, &dbh );
1046 if ( rs->sr_err != LDAP_SUCCESS ) {
1047 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1048 "could not get connection handle - exiting\n",
1049 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1050 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1051 ? "SQL-backend error" : NULL;
1056 * Check if entry exists
1058 * NOTE: backsql_api_dn2odbc() is called explicitly because
1059 * we need the mucked DN to pass it to the create procedure.
1061 realdn = op->oq_add.rs_e->e_name;
1062 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
1063 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1064 "backsql_api_dn2odbc(\"%s\") failed\n",
1065 op->oq_add.rs_e->e_name.bv_val, realdn.bv_val, 0 );
1066 rs->sr_err = LDAP_OTHER;
1067 rs->sr_text = "SQL-backend error";
1071 rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1072 if ( rs->sr_err == LDAP_SUCCESS ) {
1073 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1075 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1076 rs->sr_err = LDAP_ALREADY_EXISTS;
1081 * Get the parent dn and see if the corresponding entry exists.
1083 if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
1084 pdn = slap_empty_bv;
1087 dnParent( &op->oq_add.rs_e->e_nname, &pdn );
1090 rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, &parent_id, 0, 1 );
1091 if ( rs->sr_err != LDAP_SUCCESS ) {
1092 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1093 "could not lookup parent entry for new record \"%s\"\n",
1094 op->oq_add.rs_e->e_name.bv_val, pdn.bv_val, 0 );
1096 if ( rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
1102 * if not attempting to add entry at suffix or with parent ""
1104 if ( ( ( !be_isroot( op ) && !be_shadow_update( op ) )
1105 || !BER_BVISEMPTY( &pdn ) ) && !is_entry_glue( op->oq_add.rs_e )
1106 && !BACKSQL_ALLOW_ORPHANS( bi ) )
1108 Debug( LDAP_DEBUG_TRACE, " backsql_add: %s denied\n",
1109 BER_BVISEMPTY( &pdn ) ? "suffix" : "entry at root",
1116 char *matched = NULL;
1119 dnParent( &dn, &pdn );
1122 * Empty DN ("") defaults to LDAP_SUCCESS
1124 rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, NULL, 0, 1 );
1125 switch ( rs->sr_err ) {
1126 case LDAP_NO_SUCH_OBJECT:
1127 if ( !BER_BVISEMPTY( &pdn ) ) {
1130 /* fail over to next case */
1133 matched = pdn.bv_val;
1134 /* fail over to next case */
1137 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1138 rs->sr_matched = matched;
1144 #ifdef BACKSQL_ARBITRARY_KEY
1145 ber_str2bv( "SUFFIX", 0, 1, &parent_id.eid_id );
1146 #else /* ! BACKSQL_ARBITRARY_KEY */
1147 parent_id.eid_id = 0;
1148 #endif /* ! BACKSQL_ARBITRARY_KEY */
1149 rs->sr_err = LDAP_SUCCESS;
1153 /* check "children" pseudo-attribute access to parent */
1156 dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
1158 /* FIXME: need the whole entry (ITS#3480) */
1159 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1160 NULL, ACL_WRITE, NULL ) ) {
1161 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1166 * create_proc is executed; if expect_return is set, then
1167 * an output parameter is bound, which should contain
1168 * the id of the added row; otherwise the procedure
1169 * is expected to return the id as the first column of a select
1172 rc = SQLAllocStmt( dbh, &sth );
1173 if ( rc != SQL_SUCCESS ) {
1174 rs->sr_err = LDAP_OTHER;
1175 rs->sr_text = "SQL-backend error";
1180 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1181 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1182 if ( rc != SQL_SUCCESS ) {
1183 Debug( LDAP_DEBUG_TRACE,
1184 " backsql_add_attr(): "
1185 "error binding keyval parameter for objectClass %s\n",
1186 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1187 backsql_PrintErrors( bi->sql_db_env, dbh,
1189 SQLFreeStmt( sth, SQL_DROP );
1191 rs->sr_text = "SQL-backend error";
1192 rs->sr_err = LDAP_OTHER;
1198 if ( oc->bom_create_hint ) {
1199 at = attr_find( op->oq_add.rs_e->e_attrs, oc->bom_create_hint );
1200 if ( at && at->a_vals ) {
1201 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1202 at->a_vals[0].bv_val,
1203 at->a_vals[0].bv_len );
1204 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1205 "create_proc hint: param = '%s'\n",
1206 at->a_vals[0].bv_val, 0, 0 );
1209 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1211 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1212 "create_proc hint (%s) not avalable\n",
1213 oc->bom_create_hint->ad_cname.bv_val,
1218 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1219 op->oq_add.rs_e->e_name.bv_val, oc->bom_create_proc, 0 );
1220 rc = SQLExecDirect( sth, oc->bom_create_proc, SQL_NTS );
1221 if ( rc != SQL_SUCCESS ) {
1222 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1223 "create_proc execution failed\n",
1224 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1225 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1226 SQLFreeStmt( sth, SQL_DROP );
1227 rs->sr_err = LDAP_OTHER;
1228 rs->sr_text = "SQL-backend error";
1233 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1236 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1238 SQLINTEGER value_len;
1240 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1241 SQLFreeStmt( sth, SQL_DROP );
1242 rc = SQLAllocStmt( dbh, &sth );
1243 if ( rc != SQL_SUCCESS ) {
1244 rs->sr_err = LDAP_OTHER;
1245 rs->sr_text = "SQL-backend error";
1249 rc = SQLExecDirect( sth, oc->bom_create_keyval, SQL_NTS );
1250 if ( rc != SQL_SUCCESS ) {
1251 rs->sr_err = LDAP_OTHER;
1252 rs->sr_text = "SQL-backend error";
1258 * the query to know the id of the inserted entry
1259 * must be embedded in the create procedure
1261 rc = SQLNumResultCols( sth, &ncols );
1262 if ( rc != SQL_SUCCESS ) {
1263 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1264 "create_proc result evaluation failed\n",
1265 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1266 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1267 SQLFreeStmt( sth, SQL_DROP );
1268 rs->sr_err = LDAP_OTHER;
1269 rs->sr_text = "SQL-backend error";
1272 } else if ( ncols != 1 ) {
1273 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1274 "create_proc result is bogus (ncols=%d)\n",
1275 op->oq_add.rs_e->e_name.bv_val, ncols, 0 );
1276 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1277 SQLFreeStmt( sth, SQL_DROP );
1278 rs->sr_err = LDAP_OTHER;
1279 rs->sr_text = "SQL-backend error";
1285 SQLCHAR colname[ 64 ];
1286 SQLSMALLINT name_len, col_type, col_scale, col_null;
1290 * FIXME: check whether col_type is compatible,
1291 * if it can be null and so on ...
1293 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1295 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1296 &name_len, &col_type,
1297 &col_prec, &col_scale, &col_null );
1301 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1302 (SQLPOINTER)&new_keyval,
1303 (SQLINTEGER)sizeof( new_keyval ),
1306 rc = SQLFetch( sth );
1308 if ( value_len <= 0 ) {
1309 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1310 "create_proc result is empty?\n",
1311 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1312 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1313 SQLFreeStmt( sth, SQL_DROP );
1314 rs->sr_err = LDAP_OTHER;
1315 rs->sr_text = "SQL-backend error";
1320 SQLFreeStmt( sth, SQL_DROP );
1322 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1323 "create_proc returned keyval=%ld\n",
1324 op->oq_add.rs_e->e_name.bv_val, new_keyval, 0 );
1326 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
1327 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1328 "adding attribute \"%s\"\n",
1329 at->a_desc->ad_cname.bv_val, 0, 0 );
1333 * - the first occurrence of objectClass, which is used
1334 * to determine how to build the SQL entry (FIXME ?!?)
1335 * - operational attributes
1336 * - empty attributes (FIXME ?!?)
1338 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1342 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1343 at_objectClass = at;
1347 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1348 if ( rs->sr_err != LDAP_SUCCESS ) {
1353 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
1354 if ( rc != SQL_SUCCESS ) {
1355 rs->sr_err = LDAP_OTHER;
1356 rs->sr_text = "SQL-backend error";
1360 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1361 if ( rc != SQL_SUCCESS ) {
1362 Debug( LDAP_DEBUG_TRACE,
1363 " backsql_add_attr(): "
1364 "error binding DN parameter for objectClass %s\n",
1365 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1366 backsql_PrintErrors( bi->sql_db_env, dbh,
1368 SQLFreeStmt( sth, SQL_DROP );
1370 rs->sr_text = "SQL-backend error";
1371 rs->sr_err = LDAP_OTHER;
1375 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1376 if ( rc != SQL_SUCCESS ) {
1377 Debug( LDAP_DEBUG_TRACE,
1378 " backsql_add_attr(): "
1379 "error binding objectClass ID parameter for objectClass %s\n",
1380 oc->bom_oc->soc_cname.bv_val, 0, 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;
1390 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &parent_id.eid_id );
1391 if ( rc != SQL_SUCCESS ) {
1392 Debug( LDAP_DEBUG_TRACE,
1393 " backsql_add_attr(): "
1394 "error binding parent ID parameter for objectClass %s\n",
1395 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1396 backsql_PrintErrors( bi->sql_db_env, dbh,
1398 SQLFreeStmt( sth, SQL_DROP );
1400 rs->sr_text = "SQL-backend error";
1401 rs->sr_err = LDAP_OTHER;
1405 rc = backsql_BindParamInt( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1406 if ( rc != SQL_SUCCESS ) {
1407 Debug( LDAP_DEBUG_TRACE,
1408 " backsql_add_attr(): "
1409 "error binding entry ID parameter for objectClass %s\n",
1410 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1411 backsql_PrintErrors( bi->sql_db_env, dbh,
1413 SQLFreeStmt( sth, SQL_DROP );
1415 rs->sr_text = "SQL-backend error";
1416 rs->sr_err = LDAP_OTHER;
1420 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1421 bi->sql_insentry_stmt, op->oq_add.rs_e->e_name.bv_val, 0 );
1422 #ifdef BACKSQL_ARBITRARY_KEY
1423 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1424 "parent_id=%s, keyval=%ld\n",
1425 oc->bom_id, parent_id.eid_id.bv_val, new_keyval );
1426 #else /* ! BACKSQL_ARBITRARY_KEY */
1427 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1428 "parent_id=%ld, keyval=%ld\n",
1429 oc->bom_id, parent_id.eid_id, new_keyval );
1430 #endif /* ! BACKSQL_ARBITRARY_KEY */
1431 rc = SQLExecute( sth );
1432 if ( rc != SQL_SUCCESS ) {
1433 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1434 "could not insert ldap_entries record\n",
1435 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1436 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
1439 * execute delete_proc to delete data added !!!
1441 SQLFreeStmt( sth, SQL_DROP );
1442 rs->sr_err = LDAP_OTHER;
1443 rs->sr_text = "SQL-backend error";
1447 /* FIXME: need ldap_entries.id of newly added entry */
1448 if ( at_objectClass ) {
1449 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at_objectClass, new_keyval );
1450 if ( rs->sr_err != LDAP_SUCCESS ) {
1455 SQLFreeStmt( sth, SQL_DROP );
1459 * Commit only if all operations succeed
1461 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1462 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
1465 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1469 * FIXME: NOOP does not work for add -- it works for all
1470 * the other operations, and I don't get the reason :(
1472 * hint: there might be some autocommit in Postgres
1473 * so that when the unique id of the key table is
1474 * automatically increased, there's no rollback.
1475 * We might implement a "rollback" procedure consisting
1476 * in deleting that row.
1479 send_ldap_result( op, rs );
1481 if ( !BER_BVISNULL( &realdn )
1482 && realdn.bv_val != op->oq_add.rs_e->e_name.bv_val )
1484 ch_free( realdn.bv_val );
1486 if ( !BER_BVISNULL( &parent_id.eid_ndn ) ) {
1487 (void)backsql_free_entryID( &parent_id, 0 );
1490 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1491 op->oq_add.rs_e->e_name.bv_val,
1493 rs->sr_text ? rs->sr_text : "" );
1495 return ( ( rs->sr_err == LDAP_SUCCESS ) ? op->o_noop : 1 );