1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-sql/add.c,v 1.50.2.6 2008/02/11 23:26:48 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2008 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * Portions Copyright 2004 Mark Adamson.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
19 * This work was initially developed by Dmitry Kovalev for inclusion
20 * by OpenLDAP Software. Additional significant contributors include
21 * Pierangelo Masarati and Mark Adamson.
28 #include <sys/types.h>
29 #include "ac/string.h"
32 #include "proto-sql.h"
34 #ifdef BACKSQL_SYNCPROV
36 #endif /* BACKSQL_SYNCPROV */
40 * - null values (e.g. delete modification)
41 * - single occurrence of objectClass, because it is already used
42 * to determine how to build the SQL entry
43 * - operational attributes
46 #define backsql_opattr_skip(ad) \
47 (is_at_operational( (ad)->ad_type ) && (ad) != slap_schema.si_ad_ref )
48 #define backsql_attr_skip(ad, vals) \
50 ( (ad) == slap_schema.si_ad_objectClass \
51 && (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
52 || backsql_opattr_skip( (ad) ) \
53 || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
57 backsql_modify_delete_all_values(
61 backsql_entryID
*e_id
,
62 backsql_at_map_rec
*at
)
64 backsql_info
*bi
= (backsql_info
*)op
->o_bd
->be_private
;
66 SQLHSTMT asth
= SQL_NULL_HSTMT
;
70 if ( at
->bam_delete_proc
== NULL
) {
71 Debug( LDAP_DEBUG_TRACE
,
72 " backsql_modify_delete_all_values(): "
73 "missing attribute value delete procedure "
75 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
76 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
77 rs
->sr_text
= "SQL-backend error";
78 return rs
->sr_err
= LDAP_OTHER
;
84 rc
= backsql_Prepare( dbh
, &asth
, at
->bam_query
, 0 );
85 if ( rc
!= SQL_SUCCESS
) {
86 Debug( LDAP_DEBUG_TRACE
,
87 " backsql_modify_delete_all_values(): "
88 "error preparing attribute value select query "
90 at
->bam_query
, 0, 0 );
91 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
94 rs
->sr_text
= "SQL-backend error";
95 return rs
->sr_err
= LDAP_OTHER
;
98 rc
= backsql_BindParamID( asth
, 1, SQL_PARAM_INPUT
, &e_id
->eid_keyval
);
99 if ( rc
!= SQL_SUCCESS
) {
100 Debug( LDAP_DEBUG_TRACE
,
101 " backsql_modify_delete_all_values(): "
102 "error binding key value parameter "
103 "to attribute value select query\n",
105 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
107 SQLFreeStmt( asth
, SQL_DROP
);
109 rs
->sr_text
= "SQL-backend error";
110 return rs
->sr_err
= LDAP_OTHER
;
113 rc
= SQLExecute( asth
);
114 if ( !BACKSQL_SUCCESS( rc
) ) {
115 Debug( LDAP_DEBUG_TRACE
,
116 " backsql_modify_delete_all_values(): "
117 "error executing attribute value select query\n",
119 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
121 SQLFreeStmt( asth
, SQL_DROP
);
123 rs
->sr_text
= "SQL-backend error";
124 return rs
->sr_err
= LDAP_OTHER
;
127 backsql_BindRowAsStrings_x( asth
, &row
, op
->o_tmpmemctx
);
128 for ( rc
= SQLFetch( asth
);
129 BACKSQL_SUCCESS( rc
);
130 rc
= SQLFetch( asth
) )
133 /* first parameter no, parameter order */
134 SQLUSMALLINT pno
= 0,
136 /* procedure return code */
137 int prc
= LDAP_SUCCESS
;
139 for ( i
= 0; i
< row
.ncols
; i
++ ) {
140 SQLHSTMT sth
= SQL_NULL_HSTMT
;
143 rc
= backsql_Prepare( dbh
, &sth
, at
->bam_delete_proc
, 0 );
144 if ( rc
!= SQL_SUCCESS
) {
145 Debug( LDAP_DEBUG_TRACE
,
146 " backsql_modify_delete_all_values(): "
147 "error preparing attribute value "
150 at
->bam_delete_proc
, 0, 0 );
151 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
154 rs
->sr_text
= "SQL-backend error";
155 rs
->sr_err
= LDAP_OTHER
;
159 if ( BACKSQL_IS_DEL( at
->bam_expect_return
) ) {
161 rc
= backsql_BindParamInt( sth
, 1,
162 SQL_PARAM_OUTPUT
, &prc
);
163 if ( rc
!= SQL_SUCCESS
) {
164 Debug( LDAP_DEBUG_TRACE
,
165 " backsql_modify_delete_all_values(): "
166 "error binding output parameter for %s[%d]\n",
167 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
168 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
170 SQLFreeStmt( sth
, SQL_DROP
);
172 rs
->sr_text
= "SQL-backend error";
173 rs
->sr_err
= LDAP_OTHER
;
177 po
= ( BACKSQL_IS_DEL( at
->bam_param_order
) ) > 0;
178 rc
= backsql_BindParamID( sth
, pno
+ 1 + po
,
179 SQL_PARAM_INPUT
, &e_id
->eid_keyval
);
180 if ( rc
!= SQL_SUCCESS
) {
181 Debug( LDAP_DEBUG_TRACE
,
182 " backsql_modify_delete_all_values(): "
183 "error binding keyval parameter for %s[%d]\n",
184 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
185 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
187 SQLFreeStmt( sth
, SQL_DROP
);
189 rs
->sr_text
= "SQL-backend error";
190 rs
->sr_err
= LDAP_OTHER
;
193 #ifdef BACKSQL_ARBITRARY_KEY
194 Debug( LDAP_DEBUG_TRACE
,
195 " backsql_modify_delete_all_values() "
197 pno
+ 1 + po
, e_id
->eid_keyval
.bv_val
, 0 );
198 #else /* ! BACKSQL_ARBITRARY_KEY */
199 Debug( LDAP_DEBUG_TRACE
,
200 " backsql_modify_delete_all_values() "
202 pno
+ 1 + po
, e_id
->eid_keyval
, 0 );
203 #endif /* ! BACKSQL_ARBITRARY_KEY */
206 * check for syntax needed here
207 * maybe need binary bind?
209 col_len
= strlen( row
.cols
[ i
] );
210 rc
= backsql_BindParamStr( sth
, pno
+ 2 - po
,
211 SQL_PARAM_INPUT
, row
.cols
[ i
], col_len
);
212 if ( rc
!= SQL_SUCCESS
) {
213 Debug( LDAP_DEBUG_TRACE
,
214 " backsql_modify_delete_all_values(): "
215 "error binding value parameter for %s[%d]\n",
216 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
217 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
219 SQLFreeStmt( sth
, SQL_DROP
);
221 rs
->sr_text
= "SQL-backend error";
222 rs
->sr_err
= LDAP_OTHER
;
226 Debug( LDAP_DEBUG_TRACE
,
227 " backsql_modify_delete_all_values(): "
228 "arg(%d)=%s; executing \"%s\"\n",
229 pno
+ 2 - po
, row
.cols
[ i
],
230 at
->bam_delete_proc
);
231 rc
= SQLExecute( sth
);
232 if ( rc
== SQL_SUCCESS
&& prc
== LDAP_SUCCESS
) {
233 rs
->sr_err
= LDAP_SUCCESS
;
236 Debug( LDAP_DEBUG_TRACE
,
237 " backsql_modify_delete_all_values(): "
239 "execution failed (rc=%d, prc=%d)\n",
241 if ( prc
!= LDAP_SUCCESS
) {
242 /* SQL procedure executed fine
243 * but returned an error */
244 rs
->sr_err
= BACKSQL_SANITIZE_ERROR( prc
);
247 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
249 rs
->sr_err
= LDAP_OTHER
;
251 rs
->sr_text
= op
->o_req_dn
.bv_val
;
252 SQLFreeStmt( sth
, SQL_DROP
);
255 SQLFreeStmt( sth
, SQL_DROP
);
259 rs
->sr_err
= LDAP_SUCCESS
;
262 backsql_FreeRow_x( &row
, op
->o_tmpmemctx
);
263 SQLFreeStmt( asth
, SQL_DROP
);
269 backsql_modify_internal(
273 backsql_oc_map_rec
*oc
,
274 backsql_entryID
*e_id
,
275 Modifications
*modlist
)
277 backsql_info
*bi
= (backsql_info
*)op
->o_bd
->be_private
;
281 Debug( LDAP_DEBUG_TRACE
, "==>backsql_modify_internal(): "
282 "traversing modifications list\n", 0, 0, 0 );
284 for ( ml
= modlist
; ml
!= NULL
; ml
= ml
->sml_next
) {
285 AttributeDescription
*ad
;
287 static char *sm_ops
[] = { "add", "delete", "replace", "increment", NULL
};
291 /* NOTE: some day we'll have to pass
292 * the normalized values as well */
293 BerVarray sm_nvalues
;
295 backsql_at_map_rec
*at
= NULL
;
296 struct berval
*at_val
;
299 ad
= ml
->sml_mod
.sm_desc
;
300 sm_op
= ( ml
->sml_mod
.sm_op
& LDAP_MOD_OP
);
301 sm_values
= ml
->sml_mod
.sm_values
;
303 sm_nvalues
= ml
->sml_mod
.sm_nvalues
;
306 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
307 "modifying attribute \"%s\" (%s) according to "
308 "mappings for objectClass \"%s\"\n",
309 ad
->ad_cname
.bv_val
, sm_ops
[ sm_op
], BACKSQL_OC_NAME( oc
) );
311 if ( backsql_attr_skip( ad
, sm_values
) ) {
315 at
= backsql_ad2at( oc
, ad
);
317 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
318 "attribute \"%s\" is not registered "
319 "in objectClass \"%s\"\n",
320 ad
->ad_cname
.bv_val
, BACKSQL_OC_NAME( oc
), 0 );
322 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
323 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
324 rs
->sr_text
= "operation not permitted "
325 "within namingContext";
333 case LDAP_MOD_REPLACE
: {
334 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
335 "replacing values for attribute \"%s\"\n",
336 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
338 if ( at
->bam_add_proc
== NULL
) {
339 Debug( LDAP_DEBUG_TRACE
,
340 " backsql_modify_internal(): "
341 "add procedure is not defined "
342 "for attribute \"%s\" "
343 "- unable to perform replacements\n",
344 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
346 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
347 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
348 rs
->sr_text
= "operation not permitted "
349 "within namingContext";
356 if ( at
->bam_delete_proc
== NULL
) {
357 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
358 Debug( LDAP_DEBUG_TRACE
,
359 " backsql_modify_internal(): "
360 "delete procedure is not defined "
361 "for attribute \"%s\"\n",
362 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
364 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
365 rs
->sr_text
= "operation not permitted "
366 "within namingContext";
370 Debug( LDAP_DEBUG_TRACE
,
371 " backsql_modify_internal(): "
372 "delete procedure is not defined "
373 "for attribute \"%s\" "
375 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
381 rs
->sr_err
= backsql_modify_delete_all_values( op
, rs
, dbh
, e_id
, at
);
382 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
386 /* LDAP_MOD_DELETE gets here if all values must be deleted */
387 if ( sm_op
== LDAP_MOD_DELETE
) {
393 * PASSTHROUGH - to add new attributes -- do NOT add break
396 /* case SLAP_MOD_SOFTADD: */
398 if ( at
->bam_add_proc
== NULL
) {
399 Debug( LDAP_DEBUG_TRACE
,
400 " backsql_modify_internal(): "
401 "add procedure is not defined "
402 "for attribute \"%s\"\n",
403 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
405 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
406 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
407 rs
->sr_text
= "operation not permitted "
408 "within namingContext";
415 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
416 "adding new values for attribute \"%s\"\n",
417 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
419 /* can't add a NULL val array */
420 assert( sm_values
!= NULL
);
422 for ( i
= 0, at_val
= sm_values
;
423 !BER_BVISNULL( at_val
);
426 SQLHSTMT sth
= SQL_NULL_HSTMT
;
427 /* first parameter position, parameter order */
428 SQLUSMALLINT pno
= 0,
430 /* procedure return code */
431 int prc
= LDAP_SUCCESS
;
433 rc
= backsql_Prepare( dbh
, &sth
, at
->bam_add_proc
, 0 );
434 if ( rc
!= SQL_SUCCESS
) {
435 Debug( LDAP_DEBUG_TRACE
,
436 " backsql_modify_internal(): "
437 "error preparing add query\n",
439 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
441 rs
->sr_err
= LDAP_OTHER
;
442 rs
->sr_text
= "SQL-backend error";
446 if ( BACKSQL_IS_ADD( at
->bam_expect_return
) ) {
448 rc
= backsql_BindParamInt( sth
, 1,
449 SQL_PARAM_OUTPUT
, &prc
);
450 if ( rc
!= SQL_SUCCESS
) {
451 Debug( LDAP_DEBUG_TRACE
,
452 " backsql_modify_internal(): "
453 "error binding output parameter for %s[%d]\n",
454 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
455 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
457 SQLFreeStmt( sth
, SQL_DROP
);
459 rs
->sr_text
= "SQL-backend error";
460 rs
->sr_err
= LDAP_OTHER
;
464 po
= ( BACKSQL_IS_ADD( at
->bam_param_order
) ) > 0;
465 rc
= backsql_BindParamID( sth
, pno
+ 1 + po
,
466 SQL_PARAM_INPUT
, &e_id
->eid_keyval
);
467 if ( rc
!= SQL_SUCCESS
) {
468 Debug( LDAP_DEBUG_TRACE
,
469 " backsql_modify_internal(): "
470 "error binding keyval parameter for %s[%d]\n",
471 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
472 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
474 SQLFreeStmt( sth
, SQL_DROP
);
476 rs
->sr_text
= "SQL-backend error";
477 rs
->sr_err
= LDAP_OTHER
;
480 #ifdef BACKSQL_ARBITRARY_KEY
481 Debug( LDAP_DEBUG_TRACE
,
482 " backsql_modify_internal(): "
484 pno
+ 1 + po
, e_id
->eid_keyval
.bv_val
, 0 );
485 #else /* ! BACKSQL_ARBITRARY_KEY */
486 Debug( LDAP_DEBUG_TRACE
,
487 " backsql_modify_internal(): "
489 pno
+ 1 + po
, e_id
->eid_keyval
, 0 );
490 #endif /* ! BACKSQL_ARBITRARY_KEY */
493 * check for syntax needed here
494 * maybe need binary bind?
496 rc
= backsql_BindParamBerVal( sth
, pno
+ 2 - po
,
497 SQL_PARAM_INPUT
, at_val
);
498 if ( rc
!= SQL_SUCCESS
) {
499 Debug( LDAP_DEBUG_TRACE
,
500 " backsql_modify_internal(): "
501 "error binding value parameter for %s[%d]\n",
502 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
503 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
505 SQLFreeStmt( sth
, SQL_DROP
);
507 rs
->sr_text
= "SQL-backend error";
508 rs
->sr_err
= LDAP_OTHER
;
511 Debug( LDAP_DEBUG_TRACE
,
512 " backsql_modify_internal(): "
513 "arg(%d)=\"%s\"; executing \"%s\"\n",
514 pno
+ 2 - po
, at_val
->bv_val
,
517 rc
= SQLExecute( sth
);
518 if ( rc
== SQL_SUCCESS
&& prc
== LDAP_SUCCESS
) {
519 rs
->sr_err
= LDAP_SUCCESS
;
522 Debug( LDAP_DEBUG_TRACE
,
523 " backsql_modify_internal(): "
524 "add_proc execution failed "
527 if ( prc
!= LDAP_SUCCESS
) {
528 /* SQL procedure executed fine
529 * but returned an error */
530 SQLFreeStmt( sth
, SQL_DROP
);
532 rs
->sr_err
= BACKSQL_SANITIZE_ERROR( prc
);
533 rs
->sr_text
= at
->bam_ad
->ad_cname
.bv_val
;
537 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
539 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) )
541 SQLFreeStmt( sth
, SQL_DROP
);
543 rs
->sr_err
= LDAP_OTHER
;
544 rs
->sr_text
= "SQL-backend error";
549 SQLFreeStmt( sth
, SQL_DROP
);
553 case LDAP_MOD_DELETE
:
554 if ( at
->bam_delete_proc
== NULL
) {
555 Debug( LDAP_DEBUG_TRACE
,
556 " backsql_modify_internal(): "
557 "delete procedure is not defined "
558 "for attribute \"%s\"\n",
559 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
561 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
562 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
563 rs
->sr_text
= "operation not permitted "
564 "within namingContext";
571 if ( sm_values
== NULL
) {
572 Debug( LDAP_DEBUG_TRACE
,
573 " backsql_modify_internal(): "
574 "no values given to delete "
575 "for attribute \"%s\" "
576 "-- deleting all values\n",
577 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
581 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
582 "deleting values for attribute \"%s\"\n",
583 at
->bam_ad
->ad_cname
.bv_val
, 0, 0 );
585 for ( i
= 0, at_val
= sm_values
;
586 !BER_BVISNULL( at_val
);
589 SQLHSTMT sth
= SQL_NULL_HSTMT
;
590 /* first parameter position, parameter order */
591 SQLUSMALLINT pno
= 0,
593 /* procedure return code */
594 int prc
= LDAP_SUCCESS
;
596 rc
= backsql_Prepare( dbh
, &sth
, at
->bam_delete_proc
, 0 );
597 if ( rc
!= SQL_SUCCESS
) {
598 Debug( LDAP_DEBUG_TRACE
,
599 " backsql_modify_internal(): "
600 "error preparing delete query\n",
602 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
604 rs
->sr_err
= LDAP_OTHER
;
605 rs
->sr_text
= "SQL-backend error";
609 if ( BACKSQL_IS_DEL( at
->bam_expect_return
) ) {
611 rc
= backsql_BindParamInt( sth
, 1,
612 SQL_PARAM_OUTPUT
, &prc
);
613 if ( rc
!= SQL_SUCCESS
) {
614 Debug( LDAP_DEBUG_TRACE
,
615 " backsql_modify_internal(): "
616 "error binding output parameter for %s[%d]\n",
617 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
618 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
620 SQLFreeStmt( sth
, SQL_DROP
);
622 rs
->sr_text
= "SQL-backend error";
623 rs
->sr_err
= LDAP_OTHER
;
627 po
= ( BACKSQL_IS_DEL( at
->bam_param_order
) ) > 0;
628 rc
= backsql_BindParamID( sth
, pno
+ 1 + po
,
629 SQL_PARAM_INPUT
, &e_id
->eid_keyval
);
630 if ( rc
!= SQL_SUCCESS
) {
631 Debug( LDAP_DEBUG_TRACE
,
632 " backsql_modify_internal(): "
633 "error binding keyval parameter for %s[%d]\n",
634 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
635 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
637 SQLFreeStmt( sth
, SQL_DROP
);
639 rs
->sr_text
= "SQL-backend error";
640 rs
->sr_err
= LDAP_OTHER
;
643 #ifdef BACKSQL_ARBITRARY_KEY
644 Debug( LDAP_DEBUG_TRACE
,
645 " backsql_modify_internal(): "
647 pno
+ 1 + po
, e_id
->eid_keyval
.bv_val
, 0 );
648 #else /* ! BACKSQL_ARBITRARY_KEY */
649 Debug( LDAP_DEBUG_TRACE
,
650 " backsql_modify_internal(): "
652 pno
+ 1 + po
, e_id
->eid_keyval
, 0 );
653 #endif /* ! BACKSQL_ARBITRARY_KEY */
656 * check for syntax needed here
657 * maybe need binary bind?
659 rc
= backsql_BindParamBerVal( sth
, pno
+ 2 - po
,
660 SQL_PARAM_INPUT
, at_val
);
661 if ( rc
!= SQL_SUCCESS
) {
662 Debug( LDAP_DEBUG_TRACE
,
663 " backsql_modify_internal(): "
664 "error binding value parameter for %s[%d]\n",
665 at
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
666 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
668 SQLFreeStmt( sth
, SQL_DROP
);
670 rs
->sr_text
= "SQL-backend error";
671 rs
->sr_err
= LDAP_OTHER
;
675 Debug( LDAP_DEBUG_TRACE
,
676 " backsql_modify_internal(): "
677 "executing \"%s\"\n",
678 at
->bam_delete_proc
, 0, 0 );
679 rc
= SQLExecute( sth
);
680 if ( rc
== SQL_SUCCESS
&& prc
== LDAP_SUCCESS
)
682 rs
->sr_err
= LDAP_SUCCESS
;
685 Debug( LDAP_DEBUG_TRACE
,
686 " backsql_modify_internal(): "
687 "delete_proc execution "
688 "failed (rc=%d, prc=%d)\n",
691 if ( prc
!= LDAP_SUCCESS
) {
692 /* SQL procedure executed fine
693 * but returned an error */
694 rs
->sr_err
= BACKSQL_SANITIZE_ERROR( prc
);
695 rs
->sr_text
= at
->bam_ad
->ad_cname
.bv_val
;
699 backsql_PrintErrors( bi
->sql_db_env
,
701 SQLFreeStmt( sth
, SQL_DROP
);
702 rs
->sr_err
= LDAP_OTHER
;
703 rs
->sr_text
= at
->bam_ad
->ad_cname
.bv_val
;
707 SQLFreeStmt( sth
, SQL_DROP
);
711 case LDAP_MOD_INCREMENT
:
712 Debug( LDAP_DEBUG_TRACE
, " backsql_modify_internal(): "
713 "increment not supported yet\n", 0, 0, 0 );
714 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
715 rs
->sr_err
= LDAP_OTHER
;
716 rs
->sr_text
= "SQL-backend error";
724 Debug( LDAP_DEBUG_TRACE
, "<==backsql_modify_internal(): %d%s%s\n",
726 rs
->sr_text
? ": " : "",
727 rs
->sr_text
? rs
->sr_text
: "" );
730 * FIXME: should fail in case one change fails?
740 backsql_oc_map_rec
*oc
,
742 unsigned long new_keyval
)
744 backsql_info
*bi
= (backsql_info
*)op
->o_bd
->be_private
;
745 backsql_at_map_rec
*at_rec
= NULL
;
746 struct berval
*at_val
;
749 SQLUSMALLINT currpos
;
750 SQLHSTMT sth
= SQL_NULL_HSTMT
;
752 at_rec
= backsql_ad2at( oc
, at
->a_desc
);
754 if ( at_rec
== NULL
) {
755 Debug( LDAP_DEBUG_TRACE
, " backsql_add_attr(\"%s\"): "
756 "attribute \"%s\" is not registered "
757 "in objectclass \"%s\"\n",
758 op
->ora_e
->e_name
.bv_val
,
759 at
->a_desc
->ad_cname
.bv_val
,
760 BACKSQL_OC_NAME( oc
) );
762 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
763 rs
->sr_text
= "operation not permitted "
764 "within namingContext";
765 return rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
771 if ( at_rec
->bam_add_proc
== NULL
) {
772 Debug( LDAP_DEBUG_TRACE
, " backsql_add_attr(\"%s\"): "
773 "add procedure is not defined "
774 "for attribute \"%s\" "
775 "of structuralObjectClass \"%s\"\n",
776 op
->ora_e
->e_name
.bv_val
,
777 at
->a_desc
->ad_cname
.bv_val
,
778 BACKSQL_OC_NAME( oc
) );
780 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi
) ) {
781 rs
->sr_text
= "operation not permitted "
782 "within namingContext";
783 return rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
789 for ( i
= 0, at_val
= &at
->a_vals
[ i
];
790 !BER_BVISNULL( at_val
);
791 i
++, at_val
= &at
->a_vals
[ i
] )
793 /* procedure return code */
794 int prc
= LDAP_SUCCESS
;
795 /* first parameter #, parameter order */
796 SQLUSMALLINT pno
, po
;
797 char logbuf
[ STRLENOF("val[], id=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long)];
800 * Do not deal with the objectClass that is used
803 if ( at
->a_desc
== slap_schema
.si_ad_objectClass
) {
804 if ( dn_match( at_val
, &oc
->bom_oc
->soc_cname
) )
810 rc
= backsql_Prepare( dbh
, &sth
, at_rec
->bam_add_proc
, 0 );
811 if ( rc
!= SQL_SUCCESS
) {
812 rs
->sr_text
= "SQL-backend error";
813 return rs
->sr_err
= LDAP_OTHER
;
816 if ( BACKSQL_IS_ADD( at_rec
->bam_expect_return
) ) {
818 rc
= backsql_BindParamInt( sth
, 1, SQL_PARAM_OUTPUT
, &prc
);
819 if ( rc
!= SQL_SUCCESS
) {
820 Debug( LDAP_DEBUG_TRACE
,
821 " backsql_add_attr(): "
822 "error binding output parameter for %s[%lu]\n",
823 at_rec
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
824 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
826 SQLFreeStmt( sth
, SQL_DROP
);
828 rs
->sr_text
= "SQL-backend error";
829 return rs
->sr_err
= LDAP_OTHER
;
836 po
= ( BACKSQL_IS_ADD( at_rec
->bam_param_order
) ) > 0;
837 currpos
= pno
+ 1 + po
;
838 rc
= backsql_BindParamInt( sth
, currpos
,
839 SQL_PARAM_INPUT
, &new_keyval
);
840 if ( rc
!= SQL_SUCCESS
) {
841 Debug( LDAP_DEBUG_TRACE
,
842 " backsql_add_attr(): "
843 "error binding keyval parameter for %s[%lu]\n",
844 at_rec
->bam_ad
->ad_cname
.bv_val
, i
, 0 );
845 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
847 SQLFreeStmt( sth
, SQL_DROP
);
849 rs
->sr_text
= "SQL-backend error";
850 return rs
->sr_err
= LDAP_OTHER
;
853 currpos
= pno
+ 2 - po
;
856 * check for syntax needed here
857 * maybe need binary bind?
860 rc
= backsql_BindParamBerVal( sth
, currpos
, SQL_PARAM_INPUT
, at_val
);
861 if ( rc
!= SQL_SUCCESS
) {
862 Debug( LDAP_DEBUG_TRACE
,
863 " backsql_add_attr(): "
864 "error binding value parameter for %s[%lu]\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 rs
->sr_text
= "SQL-backend error";
871 return rs
->sr_err
= LDAP_OTHER
;
875 snprintf( logbuf
, sizeof( logbuf
), "val[%lu], id=%lu",
877 Debug( LDAP_DEBUG_TRACE
, " backsql_add_attr(\"%s\"): "
878 "executing \"%s\" %s\n",
879 op
->ora_e
->e_name
.bv_val
,
880 at_rec
->bam_add_proc
, logbuf
);
882 rc
= SQLExecute( sth
);
883 if ( rc
== SQL_SUCCESS
&& prc
== LDAP_SUCCESS
) {
884 rs
->sr_err
= LDAP_SUCCESS
;
887 Debug( LDAP_DEBUG_TRACE
,
888 " backsql_add_attr(\"%s\"): "
889 "add_proc execution failed (rc=%d, prc=%d)\n",
890 op
->ora_e
->e_name
.bv_val
, rc
, prc
);
891 if ( prc
!= LDAP_SUCCESS
) {
892 /* SQL procedure executed fine
893 * but returned an error */
894 rs
->sr_err
= BACKSQL_SANITIZE_ERROR( prc
);
895 rs
->sr_text
= op
->ora_e
->e_name
.bv_val
;
896 SQLFreeStmt( sth
, SQL_DROP
);
900 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
902 rs
->sr_err
= LDAP_OTHER
;
903 rs
->sr_text
= op
->ora_e
->e_name
.bv_val
;
904 SQLFreeStmt( sth
, SQL_DROP
);
908 SQLFreeStmt( sth
, SQL_DROP
);
915 backsql_add( Operation
*op
, SlapReply
*rs
)
917 backsql_info
*bi
= (backsql_info
*)op
->o_bd
->be_private
;
918 SQLHDBC dbh
= SQL_NULL_HDBC
;
919 SQLHSTMT sth
= SQL_NULL_HSTMT
;
920 unsigned long new_keyval
= 0;
922 backsql_oc_map_rec
*oc
= NULL
;
923 backsql_srch_info bsi
= { 0 };
924 Entry p
= { 0 }, *e
= NULL
;
926 *at_objectClass
= NULL
;
927 ObjectClass
*soc
= NULL
;
928 struct berval scname
= BER_BVNULL
;
930 struct berval realdn
= BER_BVNULL
;
934 char textbuf
[ SLAP_TEXT_BUFLEN
];
935 size_t textlen
= sizeof( textbuf
);
937 #ifdef BACKSQL_SYNCPROV
939 * NOTE: fake successful result to force contextCSN to be bumped up
942 char buf
[ LDAP_LUTIL_CSNSTR_BUFSIZE
];
946 csn
.bv_len
= sizeof( buf
);
947 slap_get_csn( op
, &csn
, 1 );
949 rs
->sr_err
= LDAP_SUCCESS
;
950 send_ldap_result( op
, rs
);
952 slap_graduate_commit_csn( op
);
956 #endif /* BACKSQL_SYNCPROV */
958 Debug( LDAP_DEBUG_TRACE
, "==>backsql_add(\"%s\")\n",
959 op
->ora_e
->e_name
.bv_val
, 0, 0 );
962 if ( BACKSQL_CHECK_SCHEMA( bi
) ) {
963 char textbuf
[ SLAP_TEXT_BUFLEN
] = { '\0' };
965 rs
->sr_err
= entry_schema_check( op
, op
->ora_e
, NULL
, 0, 1,
966 &rs
->sr_text
, textbuf
, sizeof( textbuf
) );
967 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
968 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
969 "entry failed schema check -- aborting\n",
970 op
->ora_e
->e_name
.bv_val
, 0, 0 );
976 slap_add_opattrs( op
, &rs
->sr_text
, textbuf
, textlen
, 1 );
978 /* search structuralObjectClass */
979 for ( at
= op
->ora_e
->e_attrs
; at
!= NULL
; at
= at
->a_next
) {
980 if ( at
->a_desc
== slap_schema
.si_ad_structuralObjectClass
) {
985 /* there must exist */
987 char buf
[ SLAP_TEXT_BUFLEN
];
990 /* search structuralObjectClass */
991 for ( at
= op
->ora_e
->e_attrs
; at
!= NULL
; at
= at
->a_next
) {
992 if ( at
->a_desc
== slap_schema
.si_ad_objectClass
) {
998 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1000 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1001 rs
->sr_err
= LDAP_OBJECT_CLASS_VIOLATION
;
1006 rs
->sr_err
= structural_class( at
->a_vals
, &soc
, NULL
,
1007 &text
, buf
, sizeof( buf
), op
->o_tmpmemctx
);
1008 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1009 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1011 op
->ora_e
->e_name
.bv_val
, text
, rs
->sr_err
);
1015 scname
= soc
->soc_cname
;
1018 scname
= at
->a_vals
[0];
1021 /* I guess we should play with sub/supertypes to find a suitable oc */
1022 oc
= backsql_name2oc( bi
, &scname
);
1025 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1026 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1027 op
->ora_e
->e_name
.bv_val
,
1029 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1030 rs
->sr_text
= "operation not permitted within namingContext";
1035 if ( oc
->bom_create_proc
== NULL
) {
1036 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1037 "create procedure is not defined "
1038 "for structuralObjectClass \"%s\" - aborting\n",
1039 op
->ora_e
->e_name
.bv_val
,
1041 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
1042 rs
->sr_text
= "operation not permitted within namingContext";
1046 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi
)
1047 && oc
->bom_create_keyval
== NULL
) {
1048 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1049 "create procedure needs select procedure, "
1050 "but none is defined for structuralObjectClass \"%s\" "
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 /* check write access */
1061 if ( !access_allowed_mask( op
, op
->ora_e
,
1062 slap_schema
.si_ad_entry
,
1063 NULL
, ACL_WADD
, NULL
, &mask
) )
1065 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
1070 rs
->sr_err
= backsql_get_db_conn( op
, &dbh
);
1071 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1072 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1073 "could not get connection handle - exiting\n",
1074 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1075 rs
->sr_text
= ( rs
->sr_err
== LDAP_OTHER
)
1076 ? "SQL-backend error" : NULL
;
1082 * Check if entry exists
1084 * NOTE: backsql_api_dn2odbc() is called explicitly because
1085 * we need the mucked DN to pass it to the create procedure.
1087 realdn
= op
->ora_e
->e_name
;
1088 if ( backsql_api_dn2odbc( op
, rs
, &realdn
) ) {
1089 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1090 "backsql_api_dn2odbc(\"%s\") failed\n",
1091 op
->ora_e
->e_name
.bv_val
, realdn
.bv_val
, 0 );
1092 rs
->sr_err
= LDAP_OTHER
;
1093 rs
->sr_text
= "SQL-backend error";
1098 rs
->sr_err
= backsql_dn2id( op
, rs
, dbh
, &realdn
, NULL
, 0, 0 );
1099 if ( rs
->sr_err
== LDAP_SUCCESS
) {
1100 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1102 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1103 rs
->sr_err
= LDAP_ALREADY_EXISTS
;
1109 * Get the parent dn and see if the corresponding entry exists.
1111 if ( be_issuffix( op
->o_bd
, &op
->ora_e
->e_nname
) ) {
1112 pdn
= slap_empty_bv
;
1115 dnParent( &op
->ora_e
->e_nname
, &pdn
);
1121 rs
->sr_err
= backsql_init_search( &bsi
, &pdn
,
1123 (time_t)(-1), NULL
, dbh
, op
, rs
, slap_anlist_no_attrs
,
1124 ( BACKSQL_ISF_MATCHED
| BACKSQL_ISF_GET_ENTRY
) );
1125 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1126 Debug( LDAP_DEBUG_TRACE
, "backsql_add(): "
1127 "could not retrieve addDN parent "
1128 "\"%s\" ID - %s matched=\"%s\"\n",
1130 rs
->sr_err
== LDAP_REFERRAL
? "referral" : "no such entry",
1131 rs
->sr_matched
? rs
->sr_matched
: "(null)" );
1136 /* check "children" pseudo-attribute access to parent */
1137 if ( !access_allowed( op
, &p
, slap_schema
.si_ad_children
,
1138 NULL
, ACL_WADD
, NULL
) )
1140 rs
->sr_err
= LDAP_INSUFFICIENT_ACCESS
;
1147 * create_proc is executed; if expect_return is set, then
1148 * an output parameter is bound, which should contain
1149 * the id of the added row; otherwise the procedure
1150 * is expected to return the id as the first column of a select
1152 rc
= backsql_Prepare( dbh
, &sth
, oc
->bom_create_proc
, 0 );
1153 if ( rc
!= SQL_SUCCESS
) {
1154 rs
->sr_err
= LDAP_OTHER
;
1155 rs
->sr_text
= "SQL-backend error";
1161 if ( BACKSQL_IS_ADD( oc
->bom_expect_return
) ) {
1162 rc
= backsql_BindParamInt( sth
, 1, SQL_PARAM_OUTPUT
, &new_keyval
);
1163 if ( rc
!= SQL_SUCCESS
) {
1164 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1165 "error binding keyval parameter "
1166 "for objectClass %s\n",
1167 op
->ora_e
->e_name
.bv_val
,
1168 oc
->bom_oc
->soc_cname
.bv_val
, 0 );
1169 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
1171 SQLFreeStmt( sth
, SQL_DROP
);
1173 rs
->sr_text
= "SQL-backend error";
1174 rs
->sr_err
= LDAP_OTHER
;
1181 if ( oc
->bom_create_hint
) {
1182 at
= attr_find( op
->ora_e
->e_attrs
, oc
->bom_create_hint
);
1183 if ( at
&& at
->a_vals
) {
1184 backsql_BindParamStr( sth
, colnum
, SQL_PARAM_INPUT
,
1185 at
->a_vals
[0].bv_val
,
1186 at
->a_vals
[0].bv_len
);
1187 Debug( LDAP_DEBUG_TRACE
, "backsql_add(): "
1188 "create_proc hint: param = '%s'\n",
1189 at
->a_vals
[0].bv_val
, 0, 0 );
1192 backsql_BindParamStr( sth
, colnum
, SQL_PARAM_INPUT
,
1194 Debug( LDAP_DEBUG_TRACE
, "backsql_add(): "
1195 "create_proc hint (%s) not avalable\n",
1196 oc
->bom_create_hint
->ad_cname
.bv_val
,
1202 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): executing \"%s\"\n",
1203 op
->ora_e
->e_name
.bv_val
, oc
->bom_create_proc
, 0 );
1204 rc
= SQLExecute( sth
);
1205 if ( rc
!= SQL_SUCCESS
) {
1206 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1207 "create_proc execution failed\n",
1208 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1209 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
1210 SQLFreeStmt( sth
, SQL_DROP
);
1211 rs
->sr_err
= LDAP_OTHER
;
1212 rs
->sr_text
= "SQL-backend error";
1217 /* FIXME: after SQLExecute(), the row is already inserted
1218 * (at least with PostgreSQL and unixODBC); needs investigation */
1220 if ( !BACKSQL_IS_ADD( oc
->bom_expect_return
) ) {
1222 SQLINTEGER value_len
;
1224 if ( BACKSQL_CREATE_NEEDS_SELECT( bi
) ) {
1225 SQLFreeStmt( sth
, SQL_DROP
);
1227 rc
= backsql_Prepare( dbh
, &sth
, oc
->bom_create_keyval
, 0 );
1228 if ( rc
!= SQL_SUCCESS
) {
1229 rs
->sr_err
= LDAP_OTHER
;
1230 rs
->sr_text
= "SQL-backend error";
1235 rc
= SQLExecute( sth
);
1236 if ( rc
!= SQL_SUCCESS
) {
1237 rs
->sr_err
= LDAP_OTHER
;
1238 rs
->sr_text
= "SQL-backend error";
1245 * the query to know the id of the inserted entry
1246 * must be embedded in the create procedure
1248 rc
= SQLNumResultCols( sth
, &ncols
);
1249 if ( rc
!= SQL_SUCCESS
) {
1250 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1251 "create_proc result evaluation failed\n",
1252 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1253 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
1254 SQLFreeStmt( sth
, SQL_DROP
);
1255 rs
->sr_err
= LDAP_OTHER
;
1256 rs
->sr_text
= "SQL-backend error";
1260 } else if ( ncols
!= 1 ) {
1261 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1262 "create_proc result is bogus (ncols=%d)\n",
1263 op
->ora_e
->e_name
.bv_val
, ncols
, 0 );
1264 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
1265 SQLFreeStmt( sth
, SQL_DROP
);
1266 rs
->sr_err
= LDAP_OTHER
;
1267 rs
->sr_text
= "SQL-backend error";
1274 SQLCHAR colname
[ 64 ];
1275 SQLSMALLINT name_len
, col_type
, col_scale
, col_null
;
1279 * FIXME: check whether col_type is compatible,
1280 * if it can be null and so on ...
1282 rc
= SQLDescribeCol( sth
, (SQLUSMALLINT
)1,
1284 (SQLUINTEGER
)( sizeof( colname
) - 1 ),
1285 &name_len
, &col_type
,
1286 &col_prec
, &col_scale
, &col_null
);
1290 rc
= SQLBindCol( sth
, (SQLUSMALLINT
)1, SQL_C_ULONG
,
1291 (SQLPOINTER
)&new_keyval
,
1292 (SQLINTEGER
)sizeof( new_keyval
),
1295 rc
= SQLFetch( sth
);
1297 if ( value_len
<= 0 ) {
1298 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1299 "create_proc result is empty?\n",
1300 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1301 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
1302 SQLFreeStmt( sth
, SQL_DROP
);
1303 rs
->sr_err
= LDAP_OTHER
;
1304 rs
->sr_text
= "SQL-backend error";
1310 SQLFreeStmt( sth
, SQL_DROP
);
1312 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1313 "create_proc returned keyval=%ld\n",
1314 op
->ora_e
->e_name
.bv_val
, new_keyval
, 0 );
1316 rc
= backsql_Prepare( dbh
, &sth
, bi
->sql_insentry_stmt
, 0 );
1317 if ( rc
!= SQL_SUCCESS
) {
1318 rs
->sr_err
= LDAP_OTHER
;
1319 rs
->sr_text
= "SQL-backend error";
1324 rc
= backsql_BindParamBerVal( sth
, 1, SQL_PARAM_INPUT
, &realdn
);
1325 if ( rc
!= SQL_SUCCESS
) {
1326 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1327 "error binding DN parameter for objectClass %s\n",
1328 op
->ora_e
->e_name
.bv_val
,
1329 oc
->bom_oc
->soc_cname
.bv_val
, 0 );
1330 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
1332 SQLFreeStmt( sth
, SQL_DROP
);
1334 rs
->sr_text
= "SQL-backend error";
1335 rs
->sr_err
= LDAP_OTHER
;
1340 rc
= backsql_BindParamInt( sth
, 2, SQL_PARAM_INPUT
, &oc
->bom_id
);
1341 if ( rc
!= SQL_SUCCESS
) {
1342 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1343 "error binding objectClass ID parameter "
1344 "for objectClass %s\n",
1345 op
->ora_e
->e_name
.bv_val
,
1346 oc
->bom_oc
->soc_cname
.bv_val
, 0 );
1347 backsql_PrintErrors( bi
->sql_db_env
, dbh
,
1349 SQLFreeStmt( sth
, SQL_DROP
);
1351 rs
->sr_text
= "SQL-backend error";
1352 rs
->sr_err
= LDAP_OTHER
;
1357 rc
= backsql_BindParamID( sth
, 3, SQL_PARAM_INPUT
, &bsi
.bsi_base_id
.eid_id
);
1358 if ( rc
!= SQL_SUCCESS
) {
1359 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1360 "error binding parent ID parameter "
1361 "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
, 4, SQL_PARAM_INPUT
, &new_keyval
);
1375 if ( rc
!= SQL_SUCCESS
) {
1376 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1377 "error binding entry 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 Debug( LDAP_DEBUG_TRACE
, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1392 bi
->sql_insentry_stmt
, op
->ora_e
->e_name
.bv_val
, 0 );
1393 #ifdef BACKSQL_ARBITRARY_KEY
1394 Debug( LDAP_DEBUG_TRACE
, " for oc_map_id=%ld, "
1395 "p_id=%s, keyval=%ld\n",
1396 oc
->bom_id
, bsi
.bsi_base_id
.eid_id
.bv_val
, new_keyval
);
1397 #else /* ! BACKSQL_ARBITRARY_KEY */
1398 Debug( LDAP_DEBUG_TRACE
, " for oc_map_id=%ld, "
1399 "p_id=%ld, keyval=%ld\n",
1400 oc
->bom_id
, bsi
.bsi_base_id
.eid_id
, new_keyval
);
1401 #endif /* ! BACKSQL_ARBITRARY_KEY */
1402 rc
= SQLExecute( sth
);
1403 if ( rc
!= SQL_SUCCESS
) {
1404 Debug( LDAP_DEBUG_TRACE
, " backsql_add(\"%s\"): "
1405 "could not insert ldap_entries record\n",
1406 op
->ora_e
->e_name
.bv_val
, 0, 0 );
1407 backsql_PrintErrors( bi
->sql_db_env
, dbh
, sth
, rc
);
1410 * execute delete_proc to delete data added !!!
1412 SQLFreeStmt( sth
, SQL_DROP
);
1413 rs
->sr_err
= LDAP_OTHER
;
1414 rs
->sr_text
= "SQL-backend error";
1419 SQLFreeStmt( sth
, SQL_DROP
);
1421 for ( at
= op
->ora_e
->e_attrs
; at
!= NULL
; at
= at
->a_next
) {
1422 Debug( LDAP_DEBUG_TRACE
, " backsql_add(): "
1423 "adding attribute \"%s\"\n",
1424 at
->a_desc
->ad_cname
.bv_val
, 0, 0 );
1428 * - the first occurrence of objectClass, which is used
1429 * to determine how to build the SQL entry (FIXME ?!?)
1430 * - operational attributes
1431 * - empty attributes (FIXME ?!?)
1433 if ( backsql_attr_skip( at
->a_desc
, at
->a_vals
) ) {
1437 if ( at
->a_desc
== slap_schema
.si_ad_objectClass
) {
1438 at_objectClass
= at
;
1442 rs
->sr_err
= backsql_add_attr( op
, rs
, dbh
, oc
, at
, new_keyval
);
1443 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1449 if ( at_objectClass
) {
1450 rs
->sr_err
= backsql_add_attr( op
, rs
, dbh
, oc
,
1451 at_objectClass
, new_keyval
);
1452 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1460 * Commit only if all operations succeed
1462 if ( sth
!= SQL_NULL_HSTMT
) {
1463 SQLUSMALLINT CompletionType
= SQL_ROLLBACK
;
1465 if ( rs
->sr_err
== LDAP_SUCCESS
&& !op
->o_noop
) {
1466 assert( e
== NULL
);
1467 CompletionType
= SQL_COMMIT
;
1470 SQLTransact( SQL_NULL_HENV
, dbh
, CompletionType
);
1474 * FIXME: NOOP does not work for add -- it works for all
1475 * the other operations, and I don't get the reason :(
1477 * hint: there might be some autocommit in Postgres
1478 * so that when the unique id of the key table is
1479 * automatically increased, there's no rollback.
1480 * We might implement a "rollback" procedure consisting
1481 * in deleting that row.
1487 if ( e
== op
->ora_e
&& !ACL_GRANT( mask
, ACL_DISCLOSE
) ) {
1488 /* mask already collected */
1491 } else if ( e
== &p
&& !access_allowed( op
, &p
,
1492 slap_schema
.si_ad_entry
, NULL
,
1493 ACL_DISCLOSE
, NULL
) )
1498 if ( disclose
== 0 ) {
1499 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
1501 rs
->sr_matched
= NULL
;
1503 ber_bvarray_free( rs
->sr_ref
);
1509 if ( op
->o_noop
&& rs
->sr_err
== LDAP_SUCCESS
) {
1510 rs
->sr_err
= LDAP_X_NO_OPERATION
;
1513 send_ldap_result( op
, rs
);
1514 slap_graduate_commit_csn( op
);
1516 if ( !BER_BVISNULL( &realdn
)
1517 && realdn
.bv_val
!= op
->ora_e
->e_name
.bv_val
)
1519 ch_free( realdn
.bv_val
);
1522 if ( !BER_BVISNULL( &bsi
.bsi_base_id
.eid_ndn
) ) {
1523 (void)backsql_free_entryID( &bsi
.bsi_base_id
, 0, op
->o_tmpmemctx
);
1526 if ( !BER_BVISNULL( &p
.e_nname
) ) {
1527 backsql_entry_clean( op
, &p
);
1530 Debug( LDAP_DEBUG_TRACE
, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1531 op
->ora_e
->e_name
.bv_val
,
1533 rs
->sr_text
? rs
->sr_text
: "" );
1536 rs
->sr_matched
= NULL
;
1538 ber_bvarray_free( rs
->sr_ref
);