2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2004 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by Dmitry Kovalev for inclusion
18 * by OpenLDAP Software.
26 #include <sys/types.h>
27 #include "ac/string.h"
31 #include "proto-sql.h"
35 * - the first occurrence of objectClass, which is used
36 * to determine how to build the SQL entry (FIXME ?!?)
37 * - operational attributes
38 * empty attributes (FIXME ?!?)
40 #define backsql_attr_skip(ad,vals) \
42 ( (ad) == slap_schema.si_ad_objectClass \
43 && (vals)[ 1 ].bv_val == NULL ) \
44 || is_at_operational( (ad)->ad_type ) \
45 || ( (vals)[ 0 ].bv_val == NULL ) \
49 backsql_modify_internal(
53 backsql_oc_map_rec *oc,
54 backsql_entryID *e_id,
55 Modifications *modlist )
57 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
62 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
63 "traversing modifications list\n", 0, 0, 0 );
65 #ifndef BACKSQL_REALLOC_STMT
66 SQLAllocStmt( dbh, &sth );
67 #endif /* BACKSQL_REALLOC_STMT */
69 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
70 AttributeDescription *ad;
71 backsql_at_map_rec *at = NULL;
72 struct berval *at_val;
75 /* first parameter no, parameter order */
77 /* procedure return code */
80 #ifdef BACKSQL_REALLOC_STMT
81 SQLAllocStmt( dbh, &sth );
82 #endif /* BACKSQL_REALLOC_STMT */
87 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
88 "modifying attribute \"%s\" according to "
89 "mappings for objectClass \"%s\"\n",
90 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
92 if ( backsql_attr_skip( ad, c_mod->sm_values ) ) {
96 at = backsql_ad2at( oc, ad );
98 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
99 "attribute \"%s\" is not registered "
100 "in objectClass \"%s\"\n",
101 ad->ad_cname.bv_val, oc, 0 );
103 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
104 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
105 rs->sr_text = "operation not permitted "
106 "within namingContext";
113 switch( c_mod->sm_op ) {
114 case LDAP_MOD_REPLACE: {
118 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
119 "replacing values for attribute \"%s\"\n",
120 at->bam_ad->ad_cname.bv_val, 0, 0 );
122 if ( at->bam_add_proc == NULL ) {
123 Debug( LDAP_DEBUG_TRACE,
124 " backsql_modify_internal(): "
125 "add procedure is not defined "
126 "for attribute \"%s\" "
127 "- unable to perform replacements\n",
128 at->bam_ad->ad_cname.bv_val, 0, 0 );
130 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
131 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
132 rs->sr_text = "operation not permitted "
133 "within namingContext";
140 if ( at->bam_delete_proc == NULL ) {
141 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
142 Debug( LDAP_DEBUG_TRACE,
143 " backsql_modify_internal(): "
144 "delete procedure is not defined "
145 "for attribute \"%s\"\n",
146 at->bam_ad->ad_cname.bv_val, 0, 0 );
148 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
149 rs->sr_text = "operation not permitted "
150 "within namingContext";
154 Debug( LDAP_DEBUG_TRACE,
155 " backsql_modify_internal(): "
156 "delete procedure is not defined "
157 "for attribute \"%s\" "
159 at->bam_ad->ad_cname.bv_val, 0, 0 );
165 rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
166 if ( rc != SQL_SUCCESS ) {
167 Debug( LDAP_DEBUG_TRACE,
168 " backsql_modify_internal(): "
169 "error preparing query\n", 0, 0, 0 );
170 backsql_PrintErrors( bi->db_env, dbh,
173 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
174 rs->sr_err = LDAP_OTHER;
175 rs->sr_text = "SQL-backend error";
182 #ifdef BACKSQL_ARBITRARY_KEY
183 rc = backsql_BindParamStr( asth, 1,
184 e_id->eid_keyval.bv_val,
185 BACKSQL_MAX_KEY_LEN );
186 #else /* ! BACKSQL_ARBITRARY_KEY */
187 rc = backsql_BindParamID( asth, 1, &e_id->eid_keyval );
188 #endif /* ! BACKSQL_ARBITRARY_KEY */
189 if ( rc != SQL_SUCCESS ) {
190 Debug( LDAP_DEBUG_TRACE,
191 " backsql_modify_internal(): "
192 "error binding key value parameter\n",
194 backsql_PrintErrors( bi->db_env, dbh,
196 SQLFreeStmt( asth, SQL_DROP );
198 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
199 rs->sr_err = LDAP_OTHER;
200 rs->sr_text = "SQL-backend error";
207 rc = SQLExecute( asth );
208 if ( !BACKSQL_SUCCESS( rc ) ) {
209 Debug( LDAP_DEBUG_TRACE,
210 " backsql_modify_internal(): "
211 "error executing attribute query\n",
213 backsql_PrintErrors( bi->db_env, dbh,
215 SQLFreeStmt( asth, SQL_DROP );
217 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
218 rs->sr_err = LDAP_OTHER;
219 rs->sr_text = "SQL-backend error";
226 backsql_BindRowAsStrings( asth, &row );
227 rc = SQLFetch( asth );
228 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
229 for ( i = 0; i < row.ncols; i++ ) {
230 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
232 SQLBindParameter(sth, 1,
240 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
241 #ifdef BACKSQL_ARBITRARY_KEY
242 SQLBindParameter( sth, pno + 1 + po,
244 SQL_C_CHAR, SQL_VARCHAR,
245 0, 0, e_id->eid_keyval.bv_val,
247 #else /* ! BACKSQL_ARBITRARY_KEY */
248 SQLBindParameter( sth, pno + 1 + po,
250 SQL_C_ULONG, SQL_INTEGER,
251 0, 0, &e_id->eid_keyval, 0, 0 );
252 #endif /* ! BACKSQL_ARBITRARY_KEY */
255 * check for syntax needed here
256 * maybe need binary bind?
258 SQLBindParameter(sth, pno + 2 - po,
260 SQL_C_CHAR, SQL_CHAR,
262 strlen( row.cols[ i ] ), 0 );
264 Debug( LDAP_DEBUG_TRACE,
265 " backsql_modify_internal(): "
266 "executing \"%s\"\n",
267 at->bam_delete_proc, 0, 0 );
268 rc = SQLExecDirect( sth,
269 at->bam_delete_proc, SQL_NTS );
270 if ( rc != SQL_SUCCESS ) {
271 Debug( LDAP_DEBUG_TRACE,
272 " backsql_modify_internal(): "
274 "execution failed\n",
276 backsql_PrintErrors( bi->db_env,
279 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
280 rs->sr_err = LDAP_OTHER;
281 rs->sr_text = "SQL-backend error";
285 #ifdef BACKSQL_REALLOC_STMT
286 SQLFreeStmt( sth, SQL_DROP );
287 SQLAllocStmt( dbh, &sth );
288 #endif /* BACKSQL_REALLOC_STMT */
291 backsql_FreeRow( &row );
292 SQLFreeStmt( asth, SQL_DROP );
296 * PASSTHROUGH - to add new attributes -- do NOT add break
299 case SLAP_MOD_SOFTADD:
301 if ( at->bam_add_proc == NULL ) {
302 Debug( LDAP_DEBUG_TRACE,
303 " backsql_modify_internal(): "
304 "add procedure is not defined "
305 "for attribute \"%s\"\n",
306 at->bam_ad->ad_cname.bv_val, 0, 0 );
308 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
309 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
310 rs->sr_text = "operation not permitted "
311 "within namingContext";
318 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
319 "adding new values for attribute \"%s\"\n",
320 at->bam_ad->ad_cname.bv_val, 0, 0 );
321 for ( i = 0, at_val = c_mod->sm_values;
322 at_val->bv_val != NULL;
324 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
326 SQLBindParameter( sth, 1,
328 SQL_C_ULONG, SQL_INTEGER,
333 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
334 #ifdef BACKSQL_ARBITRARY_KEY
335 SQLBindParameter( sth, pno + 1 + po,
337 SQL_C_CHAR, SQL_VARCHAR,
338 0, 0, e_id->eid_keyval.bv_val, 0, 0 );
339 #else /* ! BACKSQL_ARBITRARY_KEY */
340 SQLBindParameter( sth, pno + 1 + po,
342 SQL_C_ULONG, SQL_INTEGER,
343 0, 0, &e_id->eid_keyval, 0, 0 );
344 #endif /* ! BACKSQL_ARBITRARY_KEY */
347 * check for syntax needed here
348 * maybe need binary bind?
350 SQLBindParameter( sth, pno + 2 - po,
352 SQL_C_CHAR, SQL_CHAR,
353 0, 0, at_val->bv_val,
356 Debug( LDAP_DEBUG_TRACE,
357 " backsql_modify_internal(): "
358 "executing \"%s\"\n",
359 at->bam_add_proc, 0, 0 );
360 rc = SQLExecDirect( sth, at->bam_add_proc,
362 if ( rc != SQL_SUCCESS ) {
363 Debug( LDAP_DEBUG_TRACE,
364 " backsql_modify_internal(): "
365 "add_proc execution failed\n",
367 backsql_PrintErrors( bi->db_env,
370 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
371 rs->sr_err = LDAP_OTHER;
372 rs->sr_text = "SQL-backend error";
376 #ifdef BACKSQL_REALLOC_STMT
377 SQLFreeStmt( sth, SQL_DROP );
378 SQLAllocStmt( dbh, &sth );
379 #endif /* BACKSQL_REALLOC_STMT */
383 case LDAP_MOD_DELETE:
384 if ( at->bam_delete_proc == NULL ) {
385 Debug( LDAP_DEBUG_TRACE,
386 " backsql_modify_internal(): "
387 "delete procedure is not defined "
388 "for attribute \"%s\"\n",
389 at->bam_ad->ad_cname.bv_val, 0, 0 );
391 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
392 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
393 rs->sr_text = "operation not permitted "
394 "within namingContext";
401 if ( c_mod->sm_values == NULL ) {
402 Debug( LDAP_DEBUG_TRACE,
403 " backsql_modify_internal(): "
404 "no values given to delete "
405 "for attribute \"%s\" "
406 "-- deleting all values\n",
407 at->bam_ad->ad_cname.bv_val, 0, 0 );
411 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
412 "deleting values for attribute \"%s\"\n",
413 at->bam_ad->ad_cname.bv_val, 0, 0 );
415 for ( i = 0, at_val = c_mod->sm_values;
416 at_val->bv_val != NULL;
418 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
420 SQLBindParameter( sth, 1,
422 SQL_C_ULONG, SQL_INTEGER,
427 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
428 #ifdef BACKSQL_ARBITRARY_KEY
429 SQLBindParameter( sth, pno + 1 + po,
431 SQL_C_CHAR, SQL_VARCHAR,
432 0, 0, e_id->eid_keyval.bv_val, 0, 0 );
433 #else /* ! BACKSQL_ARBITRARY_KEY */
434 SQLBindParameter( sth, pno + 1 + po,
436 SQL_C_ULONG, SQL_INTEGER,
437 0, 0, &e_id->eid_keyval, 0, 0 );
438 #endif /* ! BACKSQL_ARBITRARY_KEY */
441 * check for syntax needed here
442 * maybe need binary bind?
444 SQLBindParameter( sth, pno + 2 - po,
445 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
446 0, 0, at_val->bv_val,
449 Debug( LDAP_DEBUG_TRACE,
450 " backsql_modify_internal(): "
451 "executing \"%s\"\n",
452 at->bam_delete_proc, 0, 0 );
453 rc = SQLExecDirect( sth, at->bam_delete_proc,
455 if ( rc != SQL_SUCCESS ) {
456 Debug( LDAP_DEBUG_TRACE,
457 " backsql_modify_internal(): "
458 "delete_proc execution "
459 "failed\n", 0, 0, 0 );
460 backsql_PrintErrors( bi->db_env,
463 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
464 rs->sr_err = LDAP_OTHER;
465 rs->sr_text = "SQL-backend error";
469 #ifdef BACKSQL_REALLOC_STMT
470 SQLFreeStmt( sth, SQL_DROP );
471 SQLAllocStmt( dbh, &sth );
472 #endif /* BACKSQL_REALLOC_STMT */
476 #ifndef BACKSQL_REALLOC_STMT
477 SQLFreeStmt( sth, SQL_RESET_PARAMS );
478 #else /* BACKSQL_REALLOC_STMT */
479 SQLFreeStmt( sth, SQL_DROP );
480 #endif /* BACKSQL_REALLOC_STMT */
485 #ifndef BACKSQL_REALLOC_STMT
486 SQLFreeStmt( sth, SQL_DROP );
487 #endif /* BACKSQL_REALLOC_STMT */
489 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%d%s\n",
490 rs->sr_err, rs->sr_text ? ": " : "",
491 rs->sr_text ? rs->sr_text : "" );
494 * FIXME: should fail in case one change fails?
500 backsql_add( Operation *op, SlapReply *rs )
502 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
505 unsigned long new_keyval = 0;
508 backsql_oc_map_rec *oc = NULL;
509 backsql_at_map_rec *at_rec = NULL;
510 backsql_entryID e_id, parent_id;
513 struct berval *at_val;
515 /* first parameter #, parameter order */
516 SQLUSMALLINT pno, po;
517 /* procedure return code */
520 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry \"%s\"\n",
521 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
524 if ( global_schemacheck ) {
525 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
527 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e,
529 &rs->sr_text, textbuf, sizeof( textbuf ) );
530 if ( rs->sr_err != LDAP_SUCCESS ) {
531 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
532 "entry failed schema check -- aborting\n",
538 /* search structural objectClass */
539 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
540 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
545 /* there must exist */
546 assert( at != NULL );
548 /* I guess we should play with sub/supertypes to find a suitable oc */
549 oc = backsql_name2oc( bi, &at->a_vals[0] );
552 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
553 "cannot determine objectclass of entry -- aborting\n",
555 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
556 rs->sr_text = "operation not permitted within namingContext";
560 if ( oc->bom_create_proc == NULL ) {
561 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
562 "create procedure is not defined for this objectclass "
563 "- aborting\n", 0, 0, 0 );
564 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
565 rs->sr_text = "operation not permitted within namingContext";
568 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
569 && oc->bom_create_keyval == NULL ) {
570 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
571 "create procedure needs select procedure, "
572 "but none is defined - aborting\n", 0, 0, 0 );
573 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
574 rs->sr_text = "operation not permitted within namingContext";
578 rs->sr_err = backsql_get_db_conn( op, &dbh );
579 if ( rs->sr_err != LDAP_SUCCESS ) {
580 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
581 "could not get connection handle - exiting\n",
583 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
584 ? "SQL-backend error" : NULL;
589 * Check if entry exists
591 rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->oq_add.rs_e->e_name );
592 if ( rs->sr_err == LDAP_SUCCESS ) {
593 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
594 "entry \"%s\" exists\n",
595 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
596 rs->sr_err = LDAP_ALREADY_EXISTS;
601 * Check if parent exists
603 dnParent( &op->oq_add.rs_e->e_name, &pdn );
604 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &pdn );
605 if ( rs->sr_err != LDAP_SUCCESS ) {
606 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
607 "could not lookup parent entry for new record \"%s\"\n",
610 if ( rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
619 char *matched = NULL;
622 dnParent( &dn, &pdn );
625 * Empty DN ("") defaults to LDAP_SUCCESS
627 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &pdn );
628 switch ( rs->sr_err ) {
629 case LDAP_NO_SUCH_OBJECT:
630 if ( pdn.bv_len > 0 ) {
633 /* fail over to next case */
636 matched = pdn.bv_val;
637 /* fail over to next case */
640 rs->sr_err = LDAP_NO_SUCH_OBJECT;
641 rs->sr_matched = matched;
648 * create_proc is executed; if expect_return is set, then
649 * an output parameter is bound, which should contain
650 * the id of the added row; otherwise the procedure
651 * is expected to return the id as the first column of a select
656 dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
657 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
658 NULL, ACL_WRITE, NULL ) ) {
659 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
663 rc = SQLAllocStmt( dbh, &sth );
664 if ( rc != SQL_SUCCESS ) {
665 rs->sr_err = LDAP_OTHER;
666 rs->sr_text = "SQL-backend error";
670 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
671 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
672 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
675 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\"\n",
676 oc->bom_create_proc, 0, 0 );
677 rc = SQLExecDirect( sth, oc->bom_create_proc, SQL_NTS );
678 if ( rc != SQL_SUCCESS ) {
679 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
680 "create_proc execution failed\n", 0, 0, 0 );
681 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
682 SQLFreeStmt( sth, SQL_DROP );
683 rs->sr_err = LDAP_OTHER;
684 rs->sr_text = "SQL-backend error";
688 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
691 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
693 SQLINTEGER value_len;
695 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
696 #ifndef BACKSQL_REALLOC_STMT
697 SQLFreeStmt( sth, SQL_RESET_PARAMS );
698 #else /* BACKSQL_REALLOC_STMT */
699 SQLFreeStmt( sth, SQL_DROP );
700 rc = SQLAllocStmt( dbh, &sth );
701 if ( rc != SQL_SUCCESS ) {
702 rs->sr_err = LDAP_OTHER;
703 rs->sr_text = "SQL-backend error";
706 #endif /* BACKSQL_REALLOC_STMT */
708 rc = SQLExecDirect( sth, oc->bom_create_keyval, SQL_NTS );
709 if ( rc != SQL_SUCCESS ) {
710 rs->sr_err = LDAP_OTHER;
711 rs->sr_text = "SQL-backend error";
717 * the query to know the id of the inserted entry
718 * must be embedded in the create procedure
720 rc = SQLNumResultCols( sth, &ncols );
721 if ( rc != SQL_SUCCESS ) {
722 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
723 "create_proc result evaluation failed\n",
725 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
726 SQLFreeStmt( sth, SQL_DROP );
727 rs->sr_err = LDAP_OTHER;
728 rs->sr_text = "SQL-backend error";
731 } else if ( ncols != 1 ) {
732 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
733 "create_proc result is bogus (ncols=%d)\n",
735 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
736 SQLFreeStmt( sth, SQL_DROP );
737 rs->sr_err = LDAP_OTHER;
738 rs->sr_text = "SQL-backend error";
744 SQLCHAR colname[ 64 ];
745 SQLSMALLINT name_len, col_type, col_scale, col_null;
749 * FIXME: check whether col_type is compatible,
750 * if it can be null and so on ...
752 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
754 (SQLUINTEGER)( sizeof( colname ) - 1 ),
755 &name_len, &col_type,
756 &col_prec, &col_scale, &col_null );
760 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
761 (SQLPOINTER)&new_keyval,
762 (SQLINTEGER)sizeof( new_keyval ),
765 rc = SQLFetch( sth );
767 if ( value_len <= 0 ) {
768 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
769 "create_proc result is empty?\n",
771 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
772 SQLFreeStmt( sth, SQL_DROP );
773 rs->sr_err = LDAP_OTHER;
774 rs->sr_text = "SQL-backend error";
779 #ifndef BACKSQL_REALLOC_STMT
780 SQLFreeStmt( sth, SQL_RESET_PARAMS );
781 #else /* BACKSQL_REALLOC_STMT */
782 SQLFreeStmt( sth, SQL_DROP );
783 #endif /* BACKSQL_REALLOC_STMT */
785 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
786 "create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
788 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
789 SQLUSMALLINT currpos;
791 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
792 "adding attribute \"%s\"\n",
793 at->a_desc->ad_cname.bv_val, 0, 0 );
797 * - the first occurrence of objectClass, which is used
798 * to determine how to bulid the SQL entry (FIXME ?!?)
799 * - operational attributes
800 * empty attributes (FIXME ?!?)
802 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
806 at_rec = backsql_ad2at( oc, at->a_desc );
808 if ( at_rec == NULL ) {
809 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
810 "attribute \"%s\" is not registered "
811 "in objectclass \"%s\"\n",
812 at->a_desc->ad_cname.bv_val,
813 BACKSQL_OC_NAME( oc ), 0 );
815 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
816 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
817 rs->sr_text = "operation not permitted "
818 "within namingContext";
825 if ( at_rec->bam_add_proc == NULL ) {
826 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
827 "add procedure is not defined "
828 "for attribute \"%s\"\n",
829 at->a_desc->ad_cname.bv_val, 0, 0 );
831 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
832 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
833 rs->sr_text = "operation not permitted "
834 "within namingContext";
841 #ifdef BACKSQL_REALLOC_STMT
842 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
843 if ( rc != SQL_SUCCESS ) {
845 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
846 rs->sr_err = LDAP_OTHER;
847 rs->sr_text = "SQL-backend error";
853 #endif /* BACKSQL_REALLOC_STMT */
855 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
857 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
858 SQL_C_ULONG, SQL_INTEGER,
864 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
865 currpos = pno + 1 + po;
866 SQLBindParameter( sth, currpos,
867 SQL_PARAM_INPUT, SQL_C_ULONG,
868 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
869 currpos = pno + 2 - po;
871 for ( i = 0, at_val = &at->a_vals[ i ];
872 at_val->bv_val != NULL;
873 i++, at_val = &at->a_vals[ i ] ) {
876 * Do not deal with the objectClass that is used
879 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
880 if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) ) {
886 * check for syntax needed here
887 * maybe need binary bind?
890 backsql_BindParamStr( sth, currpos,
891 at_val->bv_val, at_val->bv_len + 1 );
892 #ifdef SECURITY_PARANOID
893 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
894 "executing \"%s\", id=%ld\n",
895 at_rec->bam_add_proc, new_keyval, 0 );
897 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
898 "executing \"%s\" for val[%d], id=%ld\n",
899 at_rec->bam_add_proc, i, new_keyval );
901 #ifndef BACKSQL_REALLOC_STMT
902 rc = SQLExecDirect( sth, at_rec->bam_add_proc, SQL_NTS );
903 #else /* BACKSQL_REALLOC_STMT */
904 rc = SQLExecute( sth );
905 #endif /* BACKSQL_REALLOC_STMT */
906 if ( rc != SQL_SUCCESS ) {
907 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
908 "add_proc execution failed\n",
910 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
912 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
913 rs->sr_err = LDAP_OTHER;
914 rs->sr_text = "SQL-backend error";
919 #ifndef BACKSQL_REALLOC_STMT
920 SQLFreeStmt( sth, SQL_RESET_PARAMS );
921 #else /* BACKSQL_REALLOC_STMT */
922 SQLFreeStmt( sth, SQL_DROP );
923 #endif /* BACKSQL_REALLOC_STMT */
926 #ifdef BACKSQL_REALLOC_STMT
927 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
928 if ( rc != SQL_SUCCESS ) {
929 rs->sr_err = LDAP_OTHER;
930 rs->sr_text = "SQL-backend error";
933 #endif /* BACKSQL_REALLOC_STMT */
935 backsql_BindParamStr( sth, 1, op->oq_add.rs_e->e_name.bv_val,
936 BACKSQL_MAX_DN_LEN );
937 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
938 0, 0, &oc->bom_id, 0, 0 );
939 #ifdef BACKSQL_ARBITRARY_KEY
940 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
941 0, 0, parent_id.eid_id.bv_val, 0, 0 );
942 #else /* ! BACKSQL_ARBITRARY_KEY */
943 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
944 0, 0, &parent_id.eid_id, 0, 0 );
945 #endif /* ! BACKSQL_ARBITRARY_KEY */
946 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
947 0, 0, &new_keyval, 0, 0 );
949 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
950 bi->insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 );
951 #ifdef BACKSQL_ARBITRARY_KEY
952 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
953 "parent_id=%s, keyval=%ld\n",
954 oc->bom_id, parent_id.eid_id.bv_val, new_keyval );
955 #else /* ! BACKSQL_ARBITRARY_KEY */
956 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
957 "parent_id=%ld, keyval=%ld\n",
958 oc->bom_id, parent_id.eid_id, new_keyval );
959 #endif /* ! BACKSQL_ARBITRARY_KEY */
960 #ifndef BACKSQL_REALLOC_STMT
961 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
962 #else /* BACKSQL_REALLOC_STMT */
963 rc = SQLExecute( sth );
964 #endif /* BACKSQL_REALLOC_STMT */
965 if ( rc != SQL_SUCCESS ) {
966 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
967 "could not insert ldap_entries record\n", 0, 0, 0 );
968 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
971 * execute delete_proc to delete data added !!!
973 SQLFreeStmt( sth, SQL_DROP );
974 rs->sr_err = LDAP_OTHER;
975 rs->sr_text = "SQL-backend error";
979 SQLFreeStmt( sth, SQL_DROP );
982 * Commit only if all operations succeed
984 SQLTransact( SQL_NULL_HENV, dbh,
985 op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
988 * FIXME: NOOP does not work for add -- it works for all
989 * the other operations, and I don't get the reason :(
991 * hint: there might be some autocommit in Postgres
992 * so that when the unique id of the key table is
993 * automatically increased, there's no rollback.
994 * We might implement a "rollback" procedure consisting
995 * in deleting that row.
999 send_ldap_result( op, rs );
1001 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(): %d%s%s\n",
1003 rs->sr_text ? ": " : "",
1004 rs->sr_text ? rs->sr_text : "" );
1006 return ( ( rs->sr_err == LDAP_SUCCESS ) ? op->o_noop : 1 );
1009 #endif /* SLAPD_SQL */