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 && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
44 || is_at_operational( (ad)->ad_type ) \
45 || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
49 backsql_modify_delete_all_values(
53 backsql_entryID *e_id,
54 backsql_at_map_rec *at )
56 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
61 rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
62 if ( rc != SQL_SUCCESS ) {
63 Debug( LDAP_DEBUG_TRACE,
64 " backsql_modify_delete_all_values(): "
65 "error preparing query\n", 0, 0, 0 );
66 backsql_PrintErrors( bi->db_env, dbh,
69 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
70 rs->sr_text = "SQL-backend error";
71 return rs->sr_err = LDAP_OTHER;
76 rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
77 if ( rc != SQL_SUCCESS ) {
78 Debug( LDAP_DEBUG_TRACE,
79 " backsql_modify_delete_all_values(): "
80 "error binding key value parameter\n",
82 backsql_PrintErrors( bi->db_env, dbh,
84 SQLFreeStmt( asth, SQL_DROP );
86 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
87 rs->sr_text = "SQL-backend error";
88 return rs->sr_err = LDAP_OTHER;
94 rc = SQLExecute( asth );
95 if ( !BACKSQL_SUCCESS( rc ) ) {
96 Debug( LDAP_DEBUG_TRACE,
97 " backsql_modify_delete_all_values(): "
98 "error executing attribute query\n",
100 backsql_PrintErrors( bi->db_env, dbh,
102 SQLFreeStmt( asth, SQL_DROP );
104 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
105 rs->sr_text = "SQL-backend error";
106 return rs->sr_err = LDAP_OTHER;
112 backsql_BindRowAsStrings( asth, &row );
113 for ( rc = SQLFetch( asth );
114 BACKSQL_SUCCESS( rc );
115 rc = SQLFetch( asth ) )
118 /* first parameter no, parameter order */
119 SQLUSMALLINT pno, po;
120 /* procedure return code */
123 for ( i = 0; i < row.ncols; i++ ) {
127 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
128 if ( rc != SQL_SUCCESS ) {
129 Debug( LDAP_DEBUG_TRACE,
130 " backsql_modify_delete_all_values(): "
131 "error preparing query %s\n",
132 at->bam_delete_proc, 0, 0 );
133 backsql_PrintErrors( bi->db_env, dbh,
136 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
137 rs->sr_text = "SQL-backend error";
138 return rs->sr_err = LDAP_OTHER;
144 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
146 rc = backsql_BindParamInt( sth, 1,
147 SQL_PARAM_OUTPUT, &prc );
148 if ( rc != SQL_SUCCESS ) {
149 Debug( LDAP_DEBUG_TRACE,
150 " backsql_modify_delete_all_values(): "
151 "error binding output parameter for %s[%d]\n",
152 at->bam_ad->ad_cname.bv_val, i, 0 );
153 backsql_PrintErrors( bi->db_env, dbh,
155 SQLFreeStmt( sth, SQL_DROP );
157 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
158 rs->sr_text = "SQL-backend error";
159 return rs->sr_err = LDAP_OTHER;
168 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
169 rc = backsql_BindParamID( sth, pno + 1 + po,
170 SQL_PARAM_INPUT, &e_id->eid_keyval );
171 if ( rc != SQL_SUCCESS ) {
172 Debug( LDAP_DEBUG_TRACE,
173 " backsql_modify_delete_all_values(): "
174 "error binding keyval parameter for %s[%d]\n",
175 at->bam_ad->ad_cname.bv_val, i, 0 );
176 backsql_PrintErrors( bi->db_env, dbh,
178 SQLFreeStmt( sth, SQL_DROP );
180 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
181 rs->sr_text = "SQL-backend error";
182 return rs->sr_err = LDAP_OTHER;
187 #ifdef BACKSQL_ARBITRARY_KEY
188 Debug( LDAP_DEBUG_TRACE,
189 " backsql_modify_delete_all_values() "
191 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
192 #else /* ! BACKSQL_ARBITRARY_KEY */
193 Debug( LDAP_DEBUG_TRACE,
194 " backsql_modify_delete_all_values() "
196 pno + 1 + po, e_id->eid_keyval, 0 );
197 #endif /* ! BACKSQL_ARBITRARY_KEY */
200 * check for syntax needed here
201 * maybe need binary bind?
203 col_len = strlen( row.cols[ i ] );
204 rc = backsql_BindParamStr( sth, pno + 2 - po,
205 SQL_PARAM_INPUT, row.cols[ i ], col_len );
206 if ( rc != SQL_SUCCESS ) {
207 Debug( LDAP_DEBUG_TRACE,
208 " backsql_modify_delete_all_values(): "
209 "error binding value parameter for %s[%d]\n",
210 at->bam_ad->ad_cname.bv_val, i, 0 );
211 backsql_PrintErrors( bi->db_env, dbh,
213 SQLFreeStmt( sth, SQL_DROP );
215 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
216 rs->sr_text = "SQL-backend error";
217 return rs->sr_err = LDAP_OTHER;
223 Debug( LDAP_DEBUG_TRACE,
224 " backsql_modify_delete_all_values(): "
225 "arg%d=%s; executing \"%s\"\n",
226 pno + 2 - po, row.cols[ i ],
227 at->bam_delete_proc );
228 rc = SQLExecute( sth );
229 if ( rc != SQL_SUCCESS ) {
230 Debug( LDAP_DEBUG_TRACE,
231 " backsql_modify_delete_all_values(): "
233 "execution failed\n",
235 backsql_PrintErrors( bi->db_env,
238 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
239 SQLFreeStmt( sth, SQL_DROP );
240 rs->sr_text = "SQL-backend error";
241 return rs->sr_err = LDAP_OTHER;
244 SQLFreeStmt( sth, SQL_DROP );
247 backsql_FreeRow( &row );
248 SQLFreeStmt( asth, SQL_DROP );
254 backsql_modify_internal(
258 backsql_oc_map_rec *oc,
259 backsql_entryID *e_id,
260 Modifications *modlist )
262 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
267 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
268 "traversing modifications list\n", 0, 0, 0 );
270 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
271 AttributeDescription *ad;
273 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
277 /* NOTE: some time we'll have to pass
278 * the normalized values as well */
281 backsql_at_map_rec *at = NULL;
282 struct berval *at_val;
284 /* first parameter no, parameter order */
285 SQLUSMALLINT pno, po;
286 /* procedure return code */
289 ad = ml->sml_mod.sm_desc;
290 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
291 sm_values = ml->sml_mod.sm_values;
293 sm_nvalues = ml->sml_mod.sm_nvalues;
296 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
297 "modifying attribute \"%s\" (%s) according to "
298 "mappings for objectClass \"%s\"\n",
299 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
301 if ( backsql_attr_skip( ad, sm_values ) ) {
305 at = backsql_ad2at( oc, ad );
307 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
308 "attribute \"%s\" is not registered "
309 "in objectClass \"%s\"\n",
310 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
312 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
313 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
314 rs->sr_text = "operation not permitted "
315 "within namingContext";
323 case LDAP_MOD_REPLACE: {
324 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
325 "replacing values for attribute \"%s\"\n",
326 at->bam_ad->ad_cname.bv_val, 0, 0 );
328 if ( at->bam_add_proc == NULL ) {
329 Debug( LDAP_DEBUG_TRACE,
330 " backsql_modify_internal(): "
331 "add procedure is not defined "
332 "for attribute \"%s\" "
333 "- unable to perform replacements\n",
334 at->bam_ad->ad_cname.bv_val, 0, 0 );
336 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
337 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
338 rs->sr_text = "operation not permitted "
339 "within namingContext";
346 if ( at->bam_delete_proc == NULL ) {
347 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
348 Debug( LDAP_DEBUG_TRACE,
349 " backsql_modify_internal(): "
350 "delete procedure is not defined "
351 "for attribute \"%s\"\n",
352 at->bam_ad->ad_cname.bv_val, 0, 0 );
354 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
355 rs->sr_text = "operation not permitted "
356 "within namingContext";
360 Debug( LDAP_DEBUG_TRACE,
361 " backsql_modify_internal(): "
362 "delete procedure is not defined "
363 "for attribute \"%s\" "
365 at->bam_ad->ad_cname.bv_val, 0, 0 );
371 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
372 if ( rs->sr_err != LDAP_SUCCESS ) {
376 /* LDAP_MOD_DELETE gets here if all values must be deleted */
377 if ( sm_op == LDAP_MOD_DELETE ) {
383 * PASSTHROUGH - to add new attributes -- do NOT add break
386 /* case SLAP_MOD_SOFTADD: */
388 if ( at->bam_add_proc == NULL ) {
389 Debug( LDAP_DEBUG_TRACE,
390 " backsql_modify_internal(): "
391 "add procedure is not defined "
392 "for attribute \"%s\"\n",
393 at->bam_ad->ad_cname.bv_val, 0, 0 );
395 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
396 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
397 rs->sr_text = "operation not permitted "
398 "within namingContext";
405 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
406 "adding new values for attribute \"%s\"\n",
407 at->bam_ad->ad_cname.bv_val, 0, 0 );
408 for ( i = 0, at_val = sm_values;
409 !BER_BVISNULL( at_val );
412 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
413 if ( rc != SQL_SUCCESS ) {
414 Debug( LDAP_DEBUG_TRACE,
415 " backsql_modify_internal(): "
416 "error preparing add query\n",
418 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
420 rs->sr_err = LDAP_OTHER;
421 rs->sr_text = "SQL-backend error";
425 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
427 rc = backsql_BindParamInt( sth, 1,
428 SQL_PARAM_OUTPUT, &prc );
429 if ( rc != SQL_SUCCESS ) {
430 Debug( LDAP_DEBUG_TRACE,
431 " backsql_modify_internal(): "
432 "error binding output parameter for %s[%d]\n",
433 at->bam_ad->ad_cname.bv_val, i, 0 );
434 backsql_PrintErrors( bi->db_env, dbh,
436 SQLFreeStmt( sth, SQL_DROP );
438 rs->sr_text = "SQL-backend error";
439 rs->sr_err = LDAP_OTHER;
446 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
447 rc = backsql_BindParamID( sth, pno + 1 + po,
448 SQL_PARAM_INPUT, &e_id->eid_keyval );
449 if ( rc != SQL_SUCCESS ) {
450 Debug( LDAP_DEBUG_TRACE,
451 " backsql_modify_internal(): "
452 "error binding keyval parameter for %s[%d]\n",
453 at->bam_ad->ad_cname.bv_val, i, 0 );
454 backsql_PrintErrors( bi->db_env, dbh,
456 SQLFreeStmt( sth, SQL_DROP );
458 rs->sr_text = "SQL-backend error";
459 rs->sr_err = LDAP_OTHER;
462 #ifdef BACKSQL_ARBITRARY_KEY
463 Debug( LDAP_DEBUG_TRACE,
464 " backsql_modify_internal(): "
466 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
467 #else /* ! BACKSQL_ARBITRARY_KEY */
468 Debug( LDAP_DEBUG_TRACE,
469 " backsql_modify_internal(): "
471 pno + 1 + po, e_id->eid_keyval, 0 );
472 #endif /* ! BACKSQL_ARBITRARY_KEY */
475 * check for syntax needed here
476 * maybe need binary bind?
478 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
479 SQL_PARAM_INPUT, at_val );
480 if ( rc != SQL_SUCCESS ) {
481 Debug( LDAP_DEBUG_TRACE,
482 " backsql_modify_internal(): "
483 "error binding value parameter for %s[%d]\n",
484 at->bam_ad->ad_cname.bv_val, i, 0 );
485 backsql_PrintErrors( bi->db_env, dbh,
487 SQLFreeStmt( sth, SQL_DROP );
489 rs->sr_text = "SQL-backend error";
490 rs->sr_err = LDAP_OTHER;
493 Debug( LDAP_DEBUG_TRACE,
494 " backsql_modify_internal(): "
495 "arg%d=\"%s\"; executing \"%s\"\n",
496 pno + 2 - po, at_val->bv_val,
499 rc = SQLExecute( sth );
500 if ( rc != SQL_SUCCESS ) {
501 Debug( LDAP_DEBUG_TRACE,
502 " backsql_modify_internal(): "
503 "add_proc execution failed\n",
505 backsql_PrintErrors( bi->db_env,
508 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
509 SQLFreeStmt( sth, SQL_DROP );
510 rs->sr_err = LDAP_OTHER;
511 rs->sr_text = "SQL-backend error";
515 SQLFreeStmt( sth, SQL_DROP );
519 case LDAP_MOD_DELETE:
520 if ( at->bam_delete_proc == NULL ) {
521 Debug( LDAP_DEBUG_TRACE,
522 " backsql_modify_internal(): "
523 "delete procedure is not defined "
524 "for attribute \"%s\"\n",
525 at->bam_ad->ad_cname.bv_val, 0, 0 );
527 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
528 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
529 rs->sr_text = "operation not permitted "
530 "within namingContext";
537 if ( sm_values == NULL ) {
538 Debug( LDAP_DEBUG_TRACE,
539 " backsql_modify_internal(): "
540 "no values given to delete "
541 "for attribute \"%s\" "
542 "-- deleting all values\n",
543 at->bam_ad->ad_cname.bv_val, 0, 0 );
547 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
548 "deleting values for attribute \"%s\"\n",
549 at->bam_ad->ad_cname.bv_val, 0, 0 );
551 for ( i = 0, at_val = sm_values;
552 !BER_BVISNULL( at_val );
555 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
556 if ( rc != SQL_SUCCESS ) {
557 Debug( LDAP_DEBUG_TRACE,
558 " backsql_modify_internal(): "
559 "error preparing delete query\n",
561 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
563 rs->sr_err = LDAP_OTHER;
564 rs->sr_text = "SQL-backend error";
568 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
570 rc = backsql_BindParamInt( sth, 1,
571 SQL_PARAM_OUTPUT, &prc );
572 if ( rc != SQL_SUCCESS ) {
573 Debug( LDAP_DEBUG_TRACE,
574 " backsql_modify_internal(): "
575 "error binding output parameter for %s[%d]\n",
576 at->bam_ad->ad_cname.bv_val, i, 0 );
577 backsql_PrintErrors( bi->db_env, dbh,
579 SQLFreeStmt( sth, SQL_DROP );
581 rs->sr_text = "SQL-backend error";
582 rs->sr_err = LDAP_OTHER;
589 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
590 rc = backsql_BindParamID( sth, pno + 1 + po,
591 SQL_PARAM_INPUT, &e_id->eid_keyval );
592 if ( rc != SQL_SUCCESS ) {
593 Debug( LDAP_DEBUG_TRACE,
594 " backsql_modify_internal(): "
595 "error binding keyval parameter for %s[%d]\n",
596 at->bam_ad->ad_cname.bv_val, i, 0 );
597 backsql_PrintErrors( bi->db_env, dbh,
599 SQLFreeStmt( sth, SQL_DROP );
601 rs->sr_text = "SQL-backend error";
602 rs->sr_err = LDAP_OTHER;
605 #ifdef BACKSQL_ARBITRARY_KEY
606 Debug( LDAP_DEBUG_TRACE,
607 " backsql_modify_internal(): "
609 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
610 #else /* ! BACKSQL_ARBITRARY_KEY */
611 Debug( LDAP_DEBUG_TRACE,
612 " backsql_modify_internal(): "
614 pno + 1 + po, e_id->eid_keyval, 0 );
615 #endif /* ! BACKSQL_ARBITRARY_KEY */
618 * check for syntax needed here
619 * maybe need binary bind?
621 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
622 SQL_PARAM_INPUT, at_val );
623 if ( rc != SQL_SUCCESS ) {
624 Debug( LDAP_DEBUG_TRACE,
625 " backsql_modify_internal(): "
626 "error binding value parameter for %s[%d]\n",
627 at->bam_ad->ad_cname.bv_val, i, 0 );
628 backsql_PrintErrors( bi->db_env, dbh,
630 SQLFreeStmt( sth, SQL_DROP );
632 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
633 rs->sr_text = "SQL-backend error";
634 rs->sr_err = LDAP_OTHER;
639 Debug( LDAP_DEBUG_TRACE,
640 " backsql_modify_internal(): "
641 "executing \"%s\"\n",
642 at->bam_delete_proc, 0, 0 );
643 rc = SQLExecute( sth );
644 if ( rc != SQL_SUCCESS ) {
645 Debug( LDAP_DEBUG_TRACE,
646 " backsql_modify_internal(): "
647 "delete_proc execution "
648 "failed\n", 0, 0, 0 );
649 backsql_PrintErrors( bi->db_env,
652 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
653 SQLFreeStmt( sth, SQL_DROP );
654 rs->sr_err = LDAP_OTHER;
655 rs->sr_text = "SQL-backend error";
659 SQLFreeStmt( sth, SQL_DROP );
663 case LDAP_MOD_INCREMENT:
664 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
665 "increment not supported yet\n", 0, 0, 0 );
666 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
667 rs->sr_err = LDAP_OTHER;
668 rs->sr_text = "SQL-backend error";
676 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
678 rs->sr_text ? ": " : "",
679 rs->sr_text ? rs->sr_text : "" );
682 * FIXME: should fail in case one change fails?
692 backsql_oc_map_rec *oc,
694 unsigned long new_keyval )
696 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
697 backsql_at_map_rec *at_rec = NULL;
698 struct berval *at_val;
701 /* first parameter #, parameter order */
702 SQLUSMALLINT pno, po;
703 /* procedure return code */
705 SQLUSMALLINT currpos;
708 at_rec = backsql_ad2at( oc, at->a_desc );
710 if ( at_rec == NULL ) {
711 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
712 "attribute \"%s\" is not registered "
713 "in objectclass \"%s\"\n",
714 op->oq_add.rs_e->e_name.bv_val,
715 at->a_desc->ad_cname.bv_val,
716 BACKSQL_OC_NAME( oc ) );
718 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
719 rs->sr_text = "operation not permitted "
720 "within namingContext";
721 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
727 if ( at_rec->bam_add_proc == NULL ) {
728 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
729 "add procedure is not defined "
730 "for attribute \"%s\" "
731 "of structuralObjectClass \"%s\"\n",
732 op->oq_add.rs_e->e_name.bv_val,
733 at->a_desc->ad_cname.bv_val,
734 BACKSQL_OC_NAME( oc ) );
736 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
737 rs->sr_text = "operation not permitted "
738 "within namingContext";
739 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
745 for ( i = 0, at_val = &at->a_vals[ i ];
746 !BER_BVISNULL( at_val );
747 i++, at_val = &at->a_vals[ i ] )
749 char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
752 * Do not deal with the objectClass that is used
755 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
756 if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) )
762 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
763 if ( rc != SQL_SUCCESS ) {
765 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
766 rs->sr_text = "SQL-backend error";
767 return rs->sr_err = LDAP_OTHER;
773 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
775 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
776 if ( rc != SQL_SUCCESS ) {
777 Debug( LDAP_DEBUG_TRACE,
778 " backsql_add_attr(): "
779 "error binding output parameter for %s[%d]\n",
780 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
781 backsql_PrintErrors( bi->db_env, dbh,
783 SQLFreeStmt( sth, SQL_DROP );
785 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
786 rs->sr_text = "SQL-backend error";
787 return rs->sr_err = LDAP_OTHER;
797 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
798 currpos = pno + 1 + po;
799 rc = backsql_BindParamInt( sth, currpos,
800 SQL_PARAM_INPUT, &new_keyval );
801 if ( rc != SQL_SUCCESS ) {
802 Debug( LDAP_DEBUG_TRACE,
803 " backsql_add_attr(): "
804 "error binding keyval parameter for %s[%d]\n",
805 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
806 backsql_PrintErrors( bi->db_env, dbh,
808 SQLFreeStmt( sth, SQL_DROP );
810 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
811 rs->sr_text = "SQL-backend error";
812 return rs->sr_err = LDAP_OTHER;
818 currpos = pno + 2 - po;
821 * check for syntax needed here
822 * maybe need binary bind?
825 rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
826 if ( rc != SQL_SUCCESS ) {
827 Debug( LDAP_DEBUG_TRACE,
828 " backsql_add_attr(): "
829 "error binding value parameter for %s[%d]\n",
830 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
831 backsql_PrintErrors( bi->db_env, dbh,
833 SQLFreeStmt( sth, SQL_DROP );
835 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
836 rs->sr_text = "SQL-backend error";
837 return rs->sr_err = LDAP_OTHER;
844 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
846 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
847 "executing \"%s\" %s\n",
848 op->oq_add.rs_e->e_name.bv_val,
849 at_rec->bam_add_proc, logbuf );
851 rc = SQLExecute( sth );
852 if ( rc != SQL_SUCCESS ) {
853 Debug( LDAP_DEBUG_TRACE,
854 " backsql_add_attr(\"%s\"): "
855 "add_proc execution failed\n",
856 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
857 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
859 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
860 SQLFreeStmt( sth, SQL_DROP );
861 rs->sr_text = "SQL-backend error";
862 return rs->sr_err = LDAP_OTHER;
865 SQLFreeStmt( sth, SQL_DROP );
872 backsql_add( Operation *op, SlapReply *rs )
874 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
877 unsigned long new_keyval = 0;
879 backsql_oc_map_rec *oc = NULL;
880 backsql_entryID parent_id = BACKSQL_ENTRYID_INIT;
883 *at_objectClass = NULL;
885 struct berval realdn = BER_BVNULL,
886 realpdn = BER_BVNULL;
888 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
889 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
892 if ( global_schemacheck ) {
893 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
895 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e,
897 &rs->sr_text, textbuf, sizeof( textbuf ) );
898 if ( rs->sr_err != LDAP_SUCCESS ) {
899 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
900 "entry failed schema check -- aborting\n",
901 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
906 /* search structural objectClass */
907 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
908 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
913 /* there must exist */
914 assert( at != NULL );
916 /* I guess we should play with sub/supertypes to find a suitable oc */
917 oc = backsql_name2oc( bi, &at->a_vals[0] );
920 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
921 "cannot map structuralObjectClass \"%s\" -- aborting\n",
922 op->oq_add.rs_e->e_name.bv_val,
923 at->a_vals[0].bv_val, 0 );
924 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
925 rs->sr_text = "operation not permitted within namingContext";
929 if ( oc->bom_create_proc == NULL ) {
930 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
931 "create procedure is not defined "
932 "for structuralObjectClass \"%s\" - aborting\n",
933 op->oq_add.rs_e->e_name.bv_val,
934 at->a_vals[0].bv_val, 0 );
935 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
936 rs->sr_text = "operation not permitted within namingContext";
939 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
940 && oc->bom_create_keyval == NULL ) {
941 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
942 "create procedure needs select procedure, "
943 "but none is defined for structuralObjectClass \"%s\" "
945 op->oq_add.rs_e->e_name.bv_val,
946 at->a_vals[0].bv_val, 0 );
947 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
948 rs->sr_text = "operation not permitted within namingContext";
952 rs->sr_err = backsql_get_db_conn( op, &dbh );
953 if ( rs->sr_err != LDAP_SUCCESS ) {
954 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
955 "could not get connection handle - exiting\n",
956 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
957 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
958 ? "SQL-backend error" : NULL;
963 * Check if entry exists
965 realdn = op->oq_add.rs_e->e_name;
966 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
967 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
968 "backsql_api_dn2odbc(\"%s\") failed\n",
969 op->oq_add.rs_e->e_name.bv_val,
970 op->oq_add.rs_e->e_name.bv_val, 0 );
971 rs->sr_err = LDAP_OTHER;
972 rs->sr_text = "SQL-backend error";
976 rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realdn );
977 if ( rs->sr_err == LDAP_SUCCESS ) {
978 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
980 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
981 rs->sr_err = LDAP_ALREADY_EXISTS;
986 * Get the parent dn and see if the corresponding entry exists.
988 if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
992 dnParent( &op->oq_add.rs_e->e_nname, &pdn );
996 if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
997 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
998 "backsql_api_dn2odbc(\"%s\") failed\n",
999 op->oq_add.rs_e->e_name.bv_val, pdn.bv_val, 0 );
1000 rs->sr_err = LDAP_OTHER;
1001 rs->sr_text = "SQL-backend error";
1005 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &realpdn );
1006 if ( rs->sr_err != LDAP_SUCCESS ) {
1007 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1008 "could not lookup parent entry for new record \"%s\"\n",
1009 op->oq_add.rs_e->e_name.bv_val, pdn.bv_val, 0 );
1011 if ( rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
1017 * if not attempting to add entry at suffix or with parent ""
1019 if ( ( ( !be_isroot( op ) && !be_shadow_update( op ) )
1020 || !BER_BVISEMPTY( &pdn ) ) && !is_entry_glue( op->oq_add.rs_e ) )
1022 Debug( LDAP_DEBUG_TRACE, " backsql_add: %s denied\n",
1023 BER_BVISEMPTY( &pdn ) ? "suffix" : "entry at root",
1030 char *matched = NULL;
1032 if ( realpdn.bv_val != pdn.bv_val ) {
1033 ch_free( realpdn.bv_val );
1037 dnParent( &dn, &pdn );
1040 * Empty DN ("") defaults to LDAP_SUCCESS
1043 if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
1044 Debug( LDAP_DEBUG_TRACE,
1045 " backsql_add(\"%s\"): "
1046 "backsql_api_dn2odbc failed\n",
1047 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1048 rs->sr_err = LDAP_OTHER;
1049 rs->sr_text = "SQL-backend error";
1053 rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn );
1054 switch ( rs->sr_err ) {
1055 case LDAP_NO_SUCH_OBJECT:
1056 if ( !BER_BVISEMPTY( &pdn ) ) {
1059 /* fail over to next case */
1062 matched = pdn.bv_val;
1063 /* fail over to next case */
1066 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1067 rs->sr_matched = matched;
1073 #ifdef BACKSQL_ARBITRARY_KEY
1074 ber_str2bv( "SUFFIX", 0, 1, &parent_id.eid_id );
1075 #else /* ! BACKSQL_ARBITRARY_KEY */
1076 parent_id.eid_id = 0;
1077 #endif /* ! BACKSQL_ARBITRARY_KEY */
1078 rs->sr_err = LDAP_SUCCESS;
1082 /* check "children" pseudo-attribute access to parent */
1085 dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
1086 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1087 NULL, ACL_WRITE, NULL ) ) {
1088 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1093 * create_proc is executed; if expect_return is set, then
1094 * an output parameter is bound, which should contain
1095 * the id of the added row; otherwise the procedure
1096 * is expected to return the id as the first column of a select
1099 rc = SQLAllocStmt( dbh, &sth );
1100 if ( rc != SQL_SUCCESS ) {
1101 rs->sr_err = LDAP_OTHER;
1102 rs->sr_text = "SQL-backend error";
1106 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1107 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1108 if ( rc != SQL_SUCCESS ) {
1109 Debug( LDAP_DEBUG_TRACE,
1110 " backsql_add_attr(): "
1111 "error binding keyval parameter for objectClass %s\n",
1112 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1113 backsql_PrintErrors( bi->db_env, dbh,
1115 SQLFreeStmt( sth, SQL_DROP );
1117 rs->sr_text = "SQL-backend error";
1118 rs->sr_err = LDAP_OTHER;
1123 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1124 op->oq_add.rs_e->e_name.bv_val, oc->bom_create_proc, 0 );
1125 rc = SQLExecDirect( sth, oc->bom_create_proc, SQL_NTS );
1126 if ( rc != SQL_SUCCESS ) {
1127 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1128 "create_proc execution failed\n",
1129 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1130 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1131 SQLFreeStmt( sth, SQL_DROP );
1132 rs->sr_err = LDAP_OTHER;
1133 rs->sr_text = "SQL-backend error";
1138 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1141 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1143 SQLINTEGER value_len;
1145 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1146 SQLFreeStmt( sth, SQL_DROP );
1147 rc = SQLAllocStmt( dbh, &sth );
1148 if ( rc != SQL_SUCCESS ) {
1149 rs->sr_err = LDAP_OTHER;
1150 rs->sr_text = "SQL-backend error";
1154 rc = SQLExecDirect( sth, oc->bom_create_keyval, SQL_NTS );
1155 if ( rc != SQL_SUCCESS ) {
1156 rs->sr_err = LDAP_OTHER;
1157 rs->sr_text = "SQL-backend error";
1163 * the query to know the id of the inserted entry
1164 * must be embedded in the create procedure
1166 rc = SQLNumResultCols( sth, &ncols );
1167 if ( rc != SQL_SUCCESS ) {
1168 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1169 "create_proc result evaluation failed\n",
1170 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1171 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1172 SQLFreeStmt( sth, SQL_DROP );
1173 rs->sr_err = LDAP_OTHER;
1174 rs->sr_text = "SQL-backend error";
1177 } else if ( ncols != 1 ) {
1178 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1179 "create_proc result is bogus (ncols=%d)\n",
1180 op->oq_add.rs_e->e_name.bv_val, ncols, 0 );
1181 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1182 SQLFreeStmt( sth, SQL_DROP );
1183 rs->sr_err = LDAP_OTHER;
1184 rs->sr_text = "SQL-backend error";
1190 SQLCHAR colname[ 64 ];
1191 SQLSMALLINT name_len, col_type, col_scale, col_null;
1195 * FIXME: check whether col_type is compatible,
1196 * if it can be null and so on ...
1198 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1200 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1201 &name_len, &col_type,
1202 &col_prec, &col_scale, &col_null );
1206 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1207 (SQLPOINTER)&new_keyval,
1208 (SQLINTEGER)sizeof( new_keyval ),
1211 rc = SQLFetch( sth );
1213 if ( value_len <= 0 ) {
1214 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1215 "create_proc result is empty?\n",
1216 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1217 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1218 SQLFreeStmt( sth, SQL_DROP );
1219 rs->sr_err = LDAP_OTHER;
1220 rs->sr_text = "SQL-backend error";
1225 SQLFreeStmt( sth, SQL_DROP );
1227 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1228 "create_proc returned keyval=%ld\n",
1229 op->oq_add.rs_e->e_name.bv_val, new_keyval, 0 );
1231 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
1232 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1233 "adding attribute \"%s\"\n",
1234 at->a_desc->ad_cname.bv_val, 0, 0 );
1238 * - the first occurrence of objectClass, which is used
1239 * to determine how to build the SQL entry (FIXME ?!?)
1240 * - operational attributes
1241 * - empty attributes (FIXME ?!?)
1243 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1247 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1248 at_objectClass = at;
1252 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1253 if ( rs->sr_err != LDAP_SUCCESS ) {
1258 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1259 if ( rc != SQL_SUCCESS ) {
1260 rs->sr_err = LDAP_OTHER;
1261 rs->sr_text = "SQL-backend error";
1265 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1266 if ( rc != SQL_SUCCESS ) {
1267 Debug( LDAP_DEBUG_TRACE,
1268 " backsql_add_attr(): "
1269 "error binding DN parameter for objectClass %s\n",
1270 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1271 backsql_PrintErrors( bi->db_env, dbh,
1273 SQLFreeStmt( sth, SQL_DROP );
1275 rs->sr_text = "SQL-backend error";
1276 rs->sr_err = LDAP_OTHER;
1280 rc = backsql_BindParamInt( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1281 if ( rc != SQL_SUCCESS ) {
1282 Debug( LDAP_DEBUG_TRACE,
1283 " backsql_add_attr(): "
1284 "error binding objectClass ID parameter for objectClass %s\n",
1285 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1286 backsql_PrintErrors( bi->db_env, dbh,
1288 SQLFreeStmt( sth, SQL_DROP );
1290 rs->sr_text = "SQL-backend error";
1291 rs->sr_err = LDAP_OTHER;
1295 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &parent_id.eid_id );
1296 if ( rc != SQL_SUCCESS ) {
1297 Debug( LDAP_DEBUG_TRACE,
1298 " backsql_add_attr(): "
1299 "error binding parent ID parameter for objectClass %s\n",
1300 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1301 backsql_PrintErrors( bi->db_env, dbh,
1303 SQLFreeStmt( sth, SQL_DROP );
1305 rs->sr_text = "SQL-backend error";
1306 rs->sr_err = LDAP_OTHER;
1310 rc = backsql_BindParamInt( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1311 if ( rc != SQL_SUCCESS ) {
1312 Debug( LDAP_DEBUG_TRACE,
1313 " backsql_add_attr(): "
1314 "error binding entry ID parameter for objectClass %s\n",
1315 oc->bom_oc->soc_cname.bv_val, 0, 0 );
1316 backsql_PrintErrors( bi->db_env, dbh,
1318 SQLFreeStmt( sth, SQL_DROP );
1320 rs->sr_text = "SQL-backend error";
1321 rs->sr_err = LDAP_OTHER;
1325 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1326 bi->insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 );
1327 #ifdef BACKSQL_ARBITRARY_KEY
1328 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1329 "parent_id=%s, keyval=%ld\n",
1330 oc->bom_id, parent_id.eid_id.bv_val, new_keyval );
1331 #else /* ! BACKSQL_ARBITRARY_KEY */
1332 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1333 "parent_id=%ld, keyval=%ld\n",
1334 oc->bom_id, parent_id.eid_id, new_keyval );
1335 #endif /* ! BACKSQL_ARBITRARY_KEY */
1336 rc = SQLExecute( sth );
1337 if ( rc != SQL_SUCCESS ) {
1338 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1339 "could not insert ldap_entries record\n",
1340 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1341 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1344 * execute delete_proc to delete data added !!!
1346 SQLFreeStmt( sth, SQL_DROP );
1347 rs->sr_err = LDAP_OTHER;
1348 rs->sr_text = "SQL-backend error";
1352 /* FIXME: need ldap_entries.id of newly added entry */
1353 if ( at_objectClass ) {
1354 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at_objectClass, new_keyval );
1355 if ( rs->sr_err != LDAP_SUCCESS ) {
1360 SQLFreeStmt( sth, SQL_DROP );
1364 * Commit only if all operations succeed
1366 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1367 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
1370 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1374 * FIXME: NOOP does not work for add -- it works for all
1375 * the other operations, and I don't get the reason :(
1377 * hint: there might be some autocommit in Postgres
1378 * so that when the unique id of the key table is
1379 * automatically increased, there's no rollback.
1380 * We might implement a "rollback" procedure consisting
1381 * in deleting that row.
1384 send_ldap_result( op, rs );
1386 if ( !BER_BVISNULL( &realdn )
1387 && realdn.bv_val != op->oq_add.rs_e->e_name.bv_val )
1389 ch_free( realdn.bv_val );
1391 if ( !BER_BVISNULL( &realpdn ) && realpdn.bv_val != pdn.bv_val ) {
1392 ch_free( realpdn.bv_val );
1394 if ( !BER_BVISNULL( &parent_id.eid_dn ) ) {
1395 backsql_free_entryID( &parent_id, 0 );
1398 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1399 op->oq_add.rs_e->e_name.bv_val,
1401 rs->sr_text ? rs->sr_text : "" );
1403 return ( ( rs->sr_err == LDAP_SUCCESS ) ? op->o_noop : 1 );
1406 #endif /* SLAPD_SQL */