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 #ifdef BACKSQL_ARBITRARY_KEY
77 rc = backsql_BindParamStr( asth, 1,
78 e_id->eid_keyval.bv_val,
79 BACKSQL_MAX_KEY_LEN );
80 #else /* ! BACKSQL_ARBITRARY_KEY */
81 rc = backsql_BindParamID( asth, 1, &e_id->eid_keyval );
82 #endif /* ! BACKSQL_ARBITRARY_KEY */
83 if ( rc != SQL_SUCCESS ) {
84 Debug( LDAP_DEBUG_TRACE,
85 " backsql_modify_delete_all_values(): "
86 "error binding key value parameter\n",
88 backsql_PrintErrors( bi->db_env, dbh,
90 SQLFreeStmt( asth, SQL_DROP );
92 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
93 rs->sr_text = "SQL-backend error";
94 return rs->sr_err = LDAP_OTHER;
100 rc = SQLExecute( asth );
101 if ( !BACKSQL_SUCCESS( rc ) ) {
102 Debug( LDAP_DEBUG_TRACE,
103 " backsql_modify_delete_all_values(): "
104 "error executing attribute query\n",
106 backsql_PrintErrors( bi->db_env, dbh,
108 SQLFreeStmt( asth, SQL_DROP );
110 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
111 rs->sr_text = "SQL-backend error";
112 return rs->sr_err = LDAP_OTHER;
118 backsql_BindRowAsStrings( asth, &row );
119 for ( rc = SQLFetch( asth );
120 BACKSQL_SUCCESS( rc );
121 rc = SQLFetch( asth ) )
124 /* first parameter no, parameter order */
125 SQLUSMALLINT pno, po;
126 /* procedure return code */
129 for ( i = 0; i < row.ncols; i++ ) {
132 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
133 if ( rc != SQL_SUCCESS ) {
134 Debug( LDAP_DEBUG_TRACE,
135 " backsql_modify_delete_all_values(): "
136 "error preparing query %s\n",
137 at->bam_delete_proc, 0, 0 );
138 backsql_PrintErrors( bi->db_env, dbh,
141 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
142 rs->sr_text = "SQL-backend error";
143 return rs->sr_err = LDAP_OTHER;
148 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
150 SQLBindParameter( sth, 1,
158 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
159 #ifdef BACKSQL_ARBITRARY_KEY
160 SQLBindParameter( sth, pno + 1 + po,
162 SQL_C_CHAR, SQL_VARCHAR,
163 0, 0, e_id->eid_keyval.bv_val,
165 Debug( LDAP_DEBUG_TRACE,
166 " backsql_modify_delete_all_values() arg%d=%s\n",
167 pno + 1 + po, e_id->eid_keyval.bv_val, 0 );
168 #else /* ! BACKSQL_ARBITRARY_KEY */
169 SQLBindParameter( sth, pno + 1 + po,
171 SQL_C_ULONG, SQL_INTEGER,
172 0, 0, &e_id->eid_keyval, 0, 0 );
173 Debug( LDAP_DEBUG_TRACE,
174 " backsql_modify_delete_all_values() arg%d=%lu\n",
175 pno + 1 + po, e_id->eid_keyval, 0 );
176 #endif /* ! BACKSQL_ARBITRARY_KEY */
179 * check for syntax needed here
180 * maybe need binary bind?
182 SQLBindParameter( sth, pno + 2 - po,
184 SQL_C_CHAR, SQL_CHAR,
186 strlen( row.cols[ i ] ), 0 );
188 Debug( LDAP_DEBUG_TRACE,
189 " backsql_modify_delete_all_values(): "
190 "arg%d=%s; executing \"%s\"\n",
191 pno + 2 - po, row.cols[ i ],
192 at->bam_delete_proc );
193 rc = SQLExecute( sth );
194 if ( rc != SQL_SUCCESS ) {
195 Debug( LDAP_DEBUG_TRACE,
196 " backsql_modify_delete_all_values(): "
198 "execution failed\n",
200 backsql_PrintErrors( bi->db_env,
203 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
204 SQLFreeStmt( sth, SQL_DROP );
205 rs->sr_text = "SQL-backend error";
206 return rs->sr_err = LDAP_OTHER;
209 SQLFreeStmt( sth, SQL_DROP );
212 backsql_FreeRow( &row );
213 SQLFreeStmt( asth, SQL_DROP );
219 backsql_modify_internal(
223 backsql_oc_map_rec *oc,
224 backsql_entryID *e_id,
225 Modifications *modlist )
227 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
232 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
233 "traversing modifications list\n", 0, 0, 0 );
235 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
236 AttributeDescription *ad;
238 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
242 /* NOTE: some time we'll have to pass
243 * the normalized values as well */
246 backsql_at_map_rec *at = NULL;
247 struct berval *at_val;
249 /* first parameter no, parameter order */
250 SQLUSMALLINT pno, po;
251 /* procedure return code */
254 ad = ml->sml_mod.sm_desc;
255 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
256 sm_values = ml->sml_mod.sm_values;
258 sm_nvalues = ml->sml_mod.sm_nvalues;
261 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
262 "modifying attribute \"%s\" (%s) according to "
263 "mappings for objectClass \"%s\"\n",
264 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
266 if ( backsql_attr_skip( ad, sm_values ) ) {
270 at = backsql_ad2at( oc, ad );
272 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
273 "attribute \"%s\" is not registered "
274 "in objectClass \"%s\"\n",
275 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
277 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
278 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
279 rs->sr_text = "operation not permitted "
280 "within namingContext";
288 case LDAP_MOD_REPLACE: {
289 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
290 "replacing values for attribute \"%s\"\n",
291 at->bam_ad->ad_cname.bv_val, 0, 0 );
293 if ( at->bam_add_proc == NULL ) {
294 Debug( LDAP_DEBUG_TRACE,
295 " backsql_modify_internal(): "
296 "add procedure is not defined "
297 "for attribute \"%s\" "
298 "- unable to perform replacements\n",
299 at->bam_ad->ad_cname.bv_val, 0, 0 );
301 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
302 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
303 rs->sr_text = "operation not permitted "
304 "within namingContext";
311 if ( at->bam_delete_proc == NULL ) {
312 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
313 Debug( LDAP_DEBUG_TRACE,
314 " backsql_modify_internal(): "
315 "delete procedure is not defined "
316 "for attribute \"%s\"\n",
317 at->bam_ad->ad_cname.bv_val, 0, 0 );
319 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
320 rs->sr_text = "operation not permitted "
321 "within namingContext";
325 Debug( LDAP_DEBUG_TRACE,
326 " backsql_modify_internal(): "
327 "delete procedure is not defined "
328 "for attribute \"%s\" "
330 at->bam_ad->ad_cname.bv_val, 0, 0 );
336 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
337 if ( rs->sr_err != LDAP_SUCCESS ) {
341 /* LDAP_MOD_DELETE gets here if all values must be deleted */
342 if ( sm_op == LDAP_MOD_DELETE ) {
348 * PASSTHROUGH - to add new attributes -- do NOT add break
351 /* case SLAP_MOD_SOFTADD: */
353 if ( at->bam_add_proc == NULL ) {
354 Debug( LDAP_DEBUG_TRACE,
355 " backsql_modify_internal(): "
356 "add procedure is not defined "
357 "for attribute \"%s\"\n",
358 at->bam_ad->ad_cname.bv_val, 0, 0 );
360 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
361 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
362 rs->sr_text = "operation not permitted "
363 "within namingContext";
370 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
371 "adding new values for attribute \"%s\"\n",
372 at->bam_ad->ad_cname.bv_val, 0, 0 );
373 for ( i = 0, at_val = sm_values;
374 !BER_BVISNULL( at_val );
377 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
378 if ( rc != SQL_SUCCESS ) {
379 Debug( LDAP_DEBUG_TRACE,
380 " backsql_modify_internal(): "
381 "error preparing add query\n",
383 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
385 rs->sr_err = LDAP_OTHER;
386 rs->sr_text = "SQL-backend error";
390 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
392 SQLBindParameter( sth, 1,
394 SQL_C_ULONG, SQL_INTEGER,
399 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
400 #ifdef BACKSQL_ARBITRARY_KEY
401 SQLBindParameter( sth, pno + 1 + po,
403 SQL_C_CHAR, SQL_VARCHAR,
404 0, 0, e_id->eid_keyval.bv_val, 0, 0 );
405 #else /* ! BACKSQL_ARBITRARY_KEY */
406 SQLBindParameter( sth, pno + 1 + po,
408 SQL_C_ULONG, SQL_INTEGER,
409 0, 0, &e_id->eid_keyval, 0, 0 );
410 #endif /* ! BACKSQL_ARBITRARY_KEY */
413 * check for syntax needed here
414 * maybe need binary bind?
416 SQLBindParameter( sth, pno + 2 - po,
418 SQL_C_CHAR, SQL_CHAR,
419 0, 0, at_val->bv_val,
422 Debug( LDAP_DEBUG_TRACE,
423 " backsql_modify_internal(): "
424 "executing \"%s\"\n",
425 at->bam_add_proc, 0, 0 );
426 rc = SQLExecute( sth );
427 if ( rc != SQL_SUCCESS ) {
428 Debug( LDAP_DEBUG_TRACE,
429 " backsql_modify_internal(): "
430 "add_proc execution failed\n",
432 backsql_PrintErrors( bi->db_env,
435 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
436 SQLFreeStmt( sth, SQL_DROP );
437 rs->sr_err = LDAP_OTHER;
438 rs->sr_text = "SQL-backend error";
442 SQLFreeStmt( sth, SQL_DROP );
446 case LDAP_MOD_DELETE:
447 if ( at->bam_delete_proc == NULL ) {
448 Debug( LDAP_DEBUG_TRACE,
449 " backsql_modify_internal(): "
450 "delete procedure is not defined "
451 "for attribute \"%s\"\n",
452 at->bam_ad->ad_cname.bv_val, 0, 0 );
454 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
455 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
456 rs->sr_text = "operation not permitted "
457 "within namingContext";
464 if ( sm_values == NULL ) {
465 Debug( LDAP_DEBUG_TRACE,
466 " backsql_modify_internal(): "
467 "no values given to delete "
468 "for attribute \"%s\" "
469 "-- deleting all values\n",
470 at->bam_ad->ad_cname.bv_val, 0, 0 );
474 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
475 "deleting values for attribute \"%s\"\n",
476 at->bam_ad->ad_cname.bv_val, 0, 0 );
478 for ( i = 0, at_val = sm_values;
479 !BER_BVISNULL( at_val );
482 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
483 if ( rc != SQL_SUCCESS ) {
484 Debug( LDAP_DEBUG_TRACE,
485 " backsql_modify_internal(): "
486 "error preparing delete query\n",
488 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
490 rs->sr_err = LDAP_OTHER;
491 rs->sr_text = "SQL-backend error";
495 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
497 SQLBindParameter( sth, 1,
499 SQL_C_ULONG, SQL_INTEGER,
504 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
505 #ifdef BACKSQL_ARBITRARY_KEY
506 SQLBindParameter( sth, pno + 1 + po,
508 SQL_C_CHAR, SQL_VARCHAR,
509 0, 0, e_id->eid_keyval.bv_val, 0, 0 );
510 #else /* ! BACKSQL_ARBITRARY_KEY */
511 SQLBindParameter( sth, pno + 1 + po,
513 SQL_C_ULONG, SQL_INTEGER,
514 0, 0, &e_id->eid_keyval, 0, 0 );
515 #endif /* ! BACKSQL_ARBITRARY_KEY */
518 * check for syntax needed here
519 * maybe need binary bind?
521 SQLBindParameter( sth, pno + 2 - po,
522 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
523 0, 0, at_val->bv_val,
526 Debug( LDAP_DEBUG_TRACE,
527 " backsql_modify_internal(): "
528 "executing \"%s\"\n",
529 at->bam_delete_proc, 0, 0 );
530 rc = SQLExecute( sth );
531 if ( rc != SQL_SUCCESS ) {
532 Debug( LDAP_DEBUG_TRACE,
533 " backsql_modify_internal(): "
534 "delete_proc execution "
535 "failed\n", 0, 0, 0 );
536 backsql_PrintErrors( bi->db_env,
539 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
540 SQLFreeStmt( sth, SQL_DROP );
541 rs->sr_err = LDAP_OTHER;
542 rs->sr_text = "SQL-backend error";
546 SQLFreeStmt( sth, SQL_DROP );
550 case LDAP_MOD_INCREMENT:
551 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
552 "increment not supported yet\n", 0, 0, 0 );
553 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
554 rs->sr_err = LDAP_OTHER;
555 rs->sr_text = "SQL-backend error";
563 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
565 rs->sr_text ? ": " : "",
566 rs->sr_text ? rs->sr_text : "" );
569 * FIXME: should fail in case one change fails?
579 backsql_oc_map_rec *oc,
581 unsigned long new_keyval )
583 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
584 backsql_at_map_rec *at_rec = NULL;
585 struct berval *at_val;
588 /* first parameter #, parameter order */
589 SQLUSMALLINT pno, po;
590 /* procedure return code */
592 SQLUSMALLINT currpos;
595 at_rec = backsql_ad2at( oc, at->a_desc );
597 if ( at_rec == NULL ) {
598 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
599 "attribute \"%s\" is not registered "
600 "in objectclass \"%s\"\n",
601 op->oq_add.rs_e->e_name.bv_val,
602 at->a_desc->ad_cname.bv_val,
603 BACKSQL_OC_NAME( oc ) );
605 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
606 rs->sr_text = "operation not permitted "
607 "within namingContext";
608 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
614 if ( at_rec->bam_add_proc == NULL ) {
615 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
616 "add procedure is not defined "
617 "for attribute \"%s\" "
618 "of structuralObjectClass \"%s\"\n",
619 op->oq_add.rs_e->e_name.bv_val,
620 at->a_desc->ad_cname.bv_val,
621 BACKSQL_OC_NAME( oc ) );
623 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
624 rs->sr_text = "operation not permitted "
625 "within namingContext";
626 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
632 for ( i = 0, at_val = &at->a_vals[ i ];
633 !BER_BVISNULL( at_val );
634 i++, at_val = &at->a_vals[ i ] )
636 char logbuf[] = "val[18446744073709551615UL], id=18446744073709551615UL";
639 * Do not deal with the objectClass that is used
642 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
643 if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) )
649 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
650 if ( rc != SQL_SUCCESS ) {
652 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
653 rs->sr_text = "SQL-backend error";
654 return rs->sr_err = LDAP_OTHER;
660 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
662 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
663 SQL_C_ULONG, SQL_INTEGER,
669 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
670 currpos = pno + 1 + po;
671 SQLBindParameter( sth, currpos,
672 SQL_PARAM_INPUT, SQL_C_ULONG,
673 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
674 currpos = pno + 2 - po;
677 * check for syntax needed here
678 * maybe need binary bind?
681 backsql_BindParamStr( sth, currpos,
682 at_val->bv_val, at_val->bv_len + 1 );
685 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
687 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
688 "executing \"%s\" %s\n",
689 op->oq_add.rs_e->e_name.bv_val,
690 at_rec->bam_add_proc, logbuf );
692 rc = SQLExecute( sth );
693 if ( rc != SQL_SUCCESS ) {
694 Debug( LDAP_DEBUG_TRACE,
695 " backsql_add_attr(\"%s\"): "
696 "add_proc execution failed\n",
697 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
698 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
700 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
701 SQLFreeStmt( sth, SQL_DROP );
702 rs->sr_text = "SQL-backend error";
703 return rs->sr_err = LDAP_OTHER;
706 SQLFreeStmt( sth, SQL_DROP );
713 backsql_add( Operation *op, SlapReply *rs )
715 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
718 unsigned long new_keyval = 0;
720 backsql_oc_map_rec *oc = NULL;
721 backsql_entryID parent_id = BACKSQL_ENTRYID_INIT;
724 *at_objectClass = NULL;
726 struct berval realdn = BER_BVNULL,
727 realpdn = BER_BVNULL;
729 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
730 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
733 if ( global_schemacheck ) {
734 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
736 rs->sr_err = entry_schema_check( op->o_bd, op->oq_add.rs_e,
738 &rs->sr_text, textbuf, sizeof( textbuf ) );
739 if ( rs->sr_err != LDAP_SUCCESS ) {
740 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
741 "entry failed schema check -- aborting\n",
742 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
747 /* search structural objectClass */
748 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
749 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
754 /* there must exist */
755 assert( at != NULL );
757 /* I guess we should play with sub/supertypes to find a suitable oc */
758 oc = backsql_name2oc( bi, &at->a_vals[0] );
761 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
762 "cannot map structuralObjectClass \"%s\" -- aborting\n",
763 op->oq_add.rs_e->e_name.bv_val,
764 at->a_vals[0].bv_val, 0 );
765 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
766 rs->sr_text = "operation not permitted within namingContext";
770 if ( oc->bom_create_proc == NULL ) {
771 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
772 "create procedure is not defined "
773 "for structuralObjectClass \"%s\" - aborting\n",
774 op->oq_add.rs_e->e_name.bv_val,
775 at->a_vals[0].bv_val, 0 );
776 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
777 rs->sr_text = "operation not permitted within namingContext";
780 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
781 && oc->bom_create_keyval == NULL ) {
782 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
783 "create procedure needs select procedure, "
784 "but none is defined for structuralObjectClass \"%s\" "
786 op->oq_add.rs_e->e_name.bv_val,
787 at->a_vals[0].bv_val, 0 );
788 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
789 rs->sr_text = "operation not permitted within namingContext";
793 rs->sr_err = backsql_get_db_conn( op, &dbh );
794 if ( rs->sr_err != LDAP_SUCCESS ) {
795 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
796 "could not get connection handle - exiting\n",
797 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
798 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
799 ? "SQL-backend error" : NULL;
804 * Check if entry exists
806 realdn = op->oq_add.rs_e->e_name;
807 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
808 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
809 "backsql_api_dn2odbc(\"%s\") failed\n",
810 op->oq_add.rs_e->e_name.bv_val,
811 op->oq_add.rs_e->e_name.bv_val, 0 );
812 rs->sr_err = LDAP_OTHER;
813 rs->sr_text = "SQL-backend error";
817 rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realdn );
818 if ( rs->sr_err == LDAP_SUCCESS ) {
819 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
821 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
822 rs->sr_err = LDAP_ALREADY_EXISTS;
827 * Get the parent dn and see if the corresponding entry exists.
829 if ( be_issuffix( op->o_bd, &op->oq_add.rs_e->e_nname ) ) {
833 dnParent( &op->oq_add.rs_e->e_nname, &pdn );
837 if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
838 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
839 "backsql_api_dn2odbc(\"%s\") failed\n",
840 op->oq_add.rs_e->e_name.bv_val, pdn.bv_val, 0 );
841 rs->sr_err = LDAP_OTHER;
842 rs->sr_text = "SQL-backend error";
846 rs->sr_err = backsql_dn2id( bi, &parent_id, dbh, &realpdn );
847 if ( rs->sr_err != LDAP_SUCCESS ) {
848 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
849 "could not lookup parent entry for new record \"%s\"\n",
850 op->oq_add.rs_e->e_name.bv_val, pdn.bv_val, 0 );
852 if ( rs->sr_err != LDAP_NO_SUCH_OBJECT ) {
858 * if not attempting to add entry at suffix or with parent ""
860 if ( ( ( !be_isroot( op ) && !be_shadow_update( op ) )
861 || !BER_BVISEMPTY( &pdn ) ) && !is_entry_glue( op->oq_add.rs_e ) )
863 Debug( LDAP_DEBUG_TRACE, " backsql_add: %s denied\n",
864 BER_BVISEMPTY( &pdn ) ? "suffix" : "entry at root",
871 char *matched = NULL;
873 if ( realpdn.bv_val != pdn.bv_val ) {
874 ch_free( realpdn.bv_val );
878 dnParent( &dn, &pdn );
881 * Empty DN ("") defaults to LDAP_SUCCESS
884 if ( backsql_api_dn2odbc( op, rs, &realpdn ) ) {
885 Debug( LDAP_DEBUG_TRACE,
886 " backsql_add(\"%s\"): "
887 "backsql_api_dn2odbc failed\n",
888 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
889 rs->sr_err = LDAP_OTHER;
890 rs->sr_text = "SQL-backend error";
894 rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realpdn );
895 switch ( rs->sr_err ) {
896 case LDAP_NO_SUCH_OBJECT:
897 if ( !BER_BVISEMPTY( &pdn ) ) {
900 /* fail over to next case */
903 matched = pdn.bv_val;
904 /* fail over to next case */
907 rs->sr_err = LDAP_NO_SUCH_OBJECT;
908 rs->sr_matched = matched;
914 #ifdef BACKSQL_ARBITRARY_KEY
915 ber_str2bv( "SUFFIX", 0, 1, &parent_id.eid_id );
916 #else /* ! BACKSQL_ARBITRARY_KEY */
917 parent_id.eid_id = 0;
918 #endif /* ! BACKSQL_ARBITRARY_KEY */
919 rs->sr_err = LDAP_SUCCESS;
923 /* check "children" pseudo-attribute access to parent */
926 dnParent( &op->oq_add.rs_e->e_nname, &p.e_nname );
927 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
928 NULL, ACL_WRITE, NULL ) ) {
929 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
934 * create_proc is executed; if expect_return is set, then
935 * an output parameter is bound, which should contain
936 * the id of the added row; otherwise the procedure
937 * is expected to return the id as the first column of a select
940 rc = SQLAllocStmt( dbh, &sth );
941 if ( rc != SQL_SUCCESS ) {
942 rs->sr_err = LDAP_OTHER;
943 rs->sr_text = "SQL-backend error";
947 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
948 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
949 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
952 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
953 op->oq_add.rs_e->e_name.bv_val, oc->bom_create_proc, 0 );
954 rc = SQLExecDirect( sth, oc->bom_create_proc, SQL_NTS );
955 if ( rc != SQL_SUCCESS ) {
956 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
957 "create_proc execution failed\n",
958 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
959 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
960 SQLFreeStmt( sth, SQL_DROP );
961 rs->sr_err = LDAP_OTHER;
962 rs->sr_text = "SQL-backend error";
967 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
970 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
972 SQLINTEGER value_len;
974 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
975 SQLFreeStmt( sth, SQL_DROP );
976 rc = SQLAllocStmt( dbh, &sth );
977 if ( rc != SQL_SUCCESS ) {
978 rs->sr_err = LDAP_OTHER;
979 rs->sr_text = "SQL-backend error";
983 rc = SQLExecDirect( sth, oc->bom_create_keyval, SQL_NTS );
984 if ( rc != SQL_SUCCESS ) {
985 rs->sr_err = LDAP_OTHER;
986 rs->sr_text = "SQL-backend error";
992 * the query to know the id of the inserted entry
993 * must be embedded in the create procedure
995 rc = SQLNumResultCols( sth, &ncols );
996 if ( rc != SQL_SUCCESS ) {
997 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
998 "create_proc result evaluation failed\n",
999 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1000 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1001 SQLFreeStmt( sth, SQL_DROP );
1002 rs->sr_err = LDAP_OTHER;
1003 rs->sr_text = "SQL-backend error";
1006 } else if ( ncols != 1 ) {
1007 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1008 "create_proc result is bogus (ncols=%d)\n",
1009 op->oq_add.rs_e->e_name.bv_val, ncols, 0 );
1010 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1011 SQLFreeStmt( sth, SQL_DROP );
1012 rs->sr_err = LDAP_OTHER;
1013 rs->sr_text = "SQL-backend error";
1019 SQLCHAR colname[ 64 ];
1020 SQLSMALLINT name_len, col_type, col_scale, col_null;
1024 * FIXME: check whether col_type is compatible,
1025 * if it can be null and so on ...
1027 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1029 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1030 &name_len, &col_type,
1031 &col_prec, &col_scale, &col_null );
1035 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1036 (SQLPOINTER)&new_keyval,
1037 (SQLINTEGER)sizeof( new_keyval ),
1040 rc = SQLFetch( sth );
1042 if ( value_len <= 0 ) {
1043 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1044 "create_proc result is empty?\n",
1045 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1046 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
1047 SQLFreeStmt( sth, SQL_DROP );
1048 rs->sr_err = LDAP_OTHER;
1049 rs->sr_text = "SQL-backend error";
1054 SQLFreeStmt( sth, SQL_DROP );
1056 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1057 "create_proc returned keyval=%ld\n",
1058 op->oq_add.rs_e->e_name.bv_val, new_keyval, 0 );
1060 for ( at = op->oq_add.rs_e->e_attrs; at != NULL; at = at->a_next ) {
1061 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1062 "adding attribute \"%s\"\n",
1063 at->a_desc->ad_cname.bv_val, 0, 0 );
1067 * - the first occurrence of objectClass, which is used
1068 * to determine how to build the SQL entry (FIXME ?!?)
1069 * - operational attributes
1070 * - empty attributes (FIXME ?!?)
1072 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1076 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1077 at_objectClass = at;
1081 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1082 if ( rs->sr_err != LDAP_SUCCESS ) {
1087 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1088 if ( rc != SQL_SUCCESS ) {
1089 rs->sr_err = LDAP_OTHER;
1090 rs->sr_text = "SQL-backend error";
1094 backsql_BindParamStr( sth, 1, realdn.bv_val, BACKSQL_MAX_DN_LEN );
1095 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1096 0, 0, &oc->bom_id, 0, 0 );
1097 #ifdef BACKSQL_ARBITRARY_KEY
1098 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
1099 0, 0, parent_id.eid_id.bv_val, 0, 0 );
1100 #else /* ! BACKSQL_ARBITRARY_KEY */
1101 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1102 0, 0, &parent_id.eid_id, 0, 0 );
1103 #endif /* ! BACKSQL_ARBITRARY_KEY */
1104 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1105 0, 0, &new_keyval, 0, 0 );
1107 Debug( LDAP_DEBUG_TRACE, " backsql_add(): executing \"%s\" for dn \"%s\"\n",
1108 bi->insentry_query, op->oq_add.rs_e->e_name.bv_val, 0 );
1109 #ifdef BACKSQL_ARBITRARY_KEY
1110 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1111 "parent_id=%s, keyval=%ld\n",
1112 oc->bom_id, parent_id.eid_id.bv_val, new_keyval );
1113 #else /* ! BACKSQL_ARBITRARY_KEY */
1114 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, "
1115 "parent_id=%ld, keyval=%ld\n",
1116 oc->bom_id, parent_id.eid_id, new_keyval );
1117 #endif /* ! BACKSQL_ARBITRARY_KEY */
1118 rc = SQLExecute( sth );
1119 if ( rc != SQL_SUCCESS ) {
1120 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1121 "could not insert ldap_entries record\n",
1122 op->oq_add.rs_e->e_name.bv_val, 0, 0 );
1123 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1126 * execute delete_proc to delete data added !!!
1128 SQLFreeStmt( sth, SQL_DROP );
1129 rs->sr_err = LDAP_OTHER;
1130 rs->sr_text = "SQL-backend error";
1134 /* FIXME: need ldap_entries.id of newly added entry */
1135 if ( at_objectClass ) {
1136 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at_objectClass, new_keyval );
1137 if ( rs->sr_err != LDAP_SUCCESS ) {
1142 SQLFreeStmt( sth, SQL_DROP );
1146 * Commit only if all operations succeed
1148 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1149 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
1152 SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK );
1156 * FIXME: NOOP does not work for add -- it works for all
1157 * the other operations, and I don't get the reason :(
1159 * hint: there might be some autocommit in Postgres
1160 * so that when the unique id of the key table is
1161 * automatically increased, there's no rollback.
1162 * We might implement a "rollback" procedure consisting
1163 * in deleting that row.
1166 send_ldap_result( op, rs );
1168 if ( !BER_BVISNULL( &realdn )
1169 && realdn.bv_val != op->oq_add.rs_e->e_name.bv_val )
1171 ch_free( realdn.bv_val );
1173 if ( !BER_BVISNULL( &realpdn ) && realpdn.bv_val != pdn.bv_val ) {
1174 ch_free( realpdn.bv_val );
1176 if ( !BER_BVISNULL( &parent_id.eid_dn ) ) {
1177 backsql_free_entryID( &parent_id, 0 );
1180 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1181 op->oq_add.rs_e->e_name.bv_val,
1183 rs->sr_text ? rs->sr_text : "" );
1185 return ( ( rs->sr_err == LDAP_SUCCESS ) ? op->o_noop : 1 );
1188 #endif /* SLAPD_SQL */