2 * Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
4 * Redistribution and use in source and binary forms are permitted only
5 * as authorized by the OpenLDAP Public License. A copy of this
6 * license is available at http://www.OpenLDAP.org/license.html or
7 * in file LICENSE in the top-level directory of the distribution.
15 #include <sys/types.h>
21 #include "schema-map.h"
26 * PostgreSQL doesn't work without :(
28 #define BACKSQL_REALLOC_STMT
31 backsql_modify_internal(
34 backsql_oc_map_rec *oc,
35 backsql_entryID *e_id,
36 Modifications *modlist )
42 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
43 "traversing modifications list\n", 0, 0, 0 );
44 #ifndef BACKSQL_REALLOC_STMT
45 SQLAllocStmt( dbh, &sth );
46 #endif /* BACKSQL_REALLOC_STMT */
47 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
48 AttributeDescription *ad;
49 backsql_at_map_rec *at = NULL;
50 struct berval *at_val;
53 /* first parameter no, parameter order */
55 /* procedure return code */
58 #ifdef BACKSQL_REALLOC_STMT
59 SQLAllocStmt( dbh, &sth );
60 #endif /* BACKSQL_REALLOC_STMT */
65 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): attribute '%s'\n",
66 ad->ad_cname.bv_val, 0, 0 );
67 at = backsql_ad2at( oc, ad );
69 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
70 "attribute provided is not registered "
71 "in objectclass '%s'\n",
72 ad->ad_cname.bv_val, 0, 0 );
76 switch( c_mod->sm_op ) {
77 case LDAP_MOD_REPLACE: {
81 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
82 "replacing values for attribute '%s'\n",
83 at->name.bv_val, 0, 0 );
85 if ( at->add_proc == NULL ) {
86 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
87 "add procedure is not defined "
89 "- unable to perform replacements\n",
90 at->name.bv_val, 0, 0 );
94 if ( at->delete_proc == NULL ) {
95 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
96 "delete procedure is not defined "
99 at->name.bv_val, 0, 0 );
104 rc = backsql_Prepare( dbh, &asth, at->query, 0 );
105 if ( rc != SQL_SUCCESS ) {
106 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
107 "error preparing query\n", 0, 0, 0 );
108 backsql_PrintErrors( bi->db_env, dbh,
113 rc = backsql_BindParamID( asth, 1, &e_id->keyval );
114 if ( rc != SQL_SUCCESS ) {
115 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
116 "error binding key value parameter\n",
118 backsql_PrintErrors( bi->db_env, dbh,
120 SQLFreeStmt( asth, SQL_DROP );
124 rc = SQLExecute( asth );
125 if ( !BACKSQL_SUCCESS( rc ) ) {
126 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
127 "error executing attribute query\n",
129 backsql_PrintErrors( bi->db_env, dbh,
131 SQLFreeStmt( asth, SQL_DROP );
135 backsql_BindRowAsStrings( asth, &row );
136 rc = SQLFetch( asth );
137 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( asth ) ) {
138 for ( i = 0; i < row.ncols; i++ ) {
139 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
141 SQLBindParameter(sth, 1,
149 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
150 SQLBindParameter( sth, pno + 1 + po,
152 SQL_C_ULONG, SQL_INTEGER,
153 0, 0, &e_id->keyval, 0, 0 );
156 * check for syntax needed here
157 * maybe need binary bind?
159 SQLBindParameter(sth, pno + 2 - po,
161 SQL_C_CHAR, SQL_CHAR,
163 strlen( row.cols[ i ] ), 0 );
165 Debug( LDAP_DEBUG_TRACE,
168 at->delete_proc, 0, 0 );
169 rc = SQLExecDirect( sth,
170 at->delete_proc, SQL_NTS );
171 if ( rc != SQL_SUCCESS ) {
172 Debug( LDAP_DEBUG_TRACE,
175 "execution failed\n",
177 backsql_PrintErrors( bi->db_env,
180 #ifdef BACKSQL_REALLOC_STMT
181 SQLFreeStmt( sth, SQL_DROP );
182 SQLAllocStmt( dbh, &sth );
183 #endif /* BACKSQL_REALLOC_STMT */
186 backsql_FreeRow( &row );
187 SQLFreeStmt( asth, SQL_DROP );
191 * PASSTHROUGH - to add new attributes -- do NOT add break
194 case SLAP_MOD_SOFTADD:
196 if ( at->add_proc == NULL ) {
197 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
198 "add procedure is not defined "
199 "for attribute '%s'\n",
200 at->name.bv_val, 0, 0 );
204 if ( c_mod->sm_bvalues == NULL ) {
205 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
206 "no values given to add "
207 "for attribute '%s'\n",
208 at->name.bv_val, 0, 0 );
212 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
213 "adding new values for attribute '%s'\n",
214 at->name.bv_val, 0, 0 );
215 for ( i = 0, at_val = c_mod->sm_bvalues;
216 at_val->bv_val != NULL;
218 if ( BACKSQL_IS_ADD( at->expect_return ) ) {
220 SQLBindParameter( sth, 1,
222 SQL_C_ULONG, SQL_INTEGER,
227 po = ( BACKSQL_IS_ADD( at->param_order ) ) > 0;
228 SQLBindParameter( sth, pno + 1 + po,
230 SQL_C_ULONG, SQL_INTEGER,
231 0, 0, &e_id->keyval, 0, 0 );
234 * check for syntax needed here
235 * maybe need binary bind?
237 SQLBindParameter( sth, pno + 2 - po,
239 SQL_C_CHAR, SQL_CHAR,
240 0, 0, at_val->bv_val,
243 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
245 at->add_proc, 0, 0 );
246 rc = SQLExecDirect( sth, at->add_proc,
248 if ( rc != SQL_SUCCESS ) {
249 Debug( LDAP_DEBUG_TRACE,
251 "add_proc execution failed\n",
253 backsql_PrintErrors( bi->db_env,
256 #ifdef BACKSQL_REALLOC_STMT
257 SQLFreeStmt( sth, SQL_DROP );
258 SQLAllocStmt( dbh, &sth );
259 #endif /* BACKSQL_REALLOC_STMT */
263 case LDAP_MOD_DELETE:
264 if ( at->delete_proc == NULL ) {
265 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
266 "delete procedure is not defined "
267 "for attribute '%s'\n",
268 at->name.bv_val, 0, 0 );
272 if ( c_mod->sm_bvalues == NULL ) {
273 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
274 "no values given to delete "
275 "for attribute '%s' "
276 "-- deleting all values\n",
277 at->name.bv_val, 0, 0 );
281 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
282 "deleting values for attribute '%s'\n",
283 at->name.bv_val, 0, 0 );
284 for ( i = 0, at_val = c_mod->sm_bvalues;
285 at_val->bv_val != NULL;
287 if ( BACKSQL_IS_DEL( at->expect_return ) ) {
289 SQLBindParameter( sth, 1,
291 SQL_C_ULONG, SQL_INTEGER,
296 po = ( BACKSQL_IS_DEL( at->param_order ) ) > 0;
297 SQLBindParameter( sth, pno + 1 + po,
299 SQL_C_ULONG, SQL_INTEGER,
300 0, 0, &e_id->keyval, 0, 0 );
303 * check for syntax needed here
304 * maybe need binary bind?
306 SQLBindParameter( sth, pno + 2 - po,
307 SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR,
308 0, 0, at_val->bv_val,
311 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
313 at->delete_proc, 0, 0 );
314 rc = SQLExecDirect( sth, at->delete_proc,
316 if ( rc != SQL_SUCCESS ) {
317 Debug( LDAP_DEBUG_TRACE,
319 "delete_proc execution "
320 "failed\n", 0, 0, 0 );
321 backsql_PrintErrors( bi->db_env,
324 #ifdef BACKSQL_REALLOC_STMT
325 SQLFreeStmt( sth, SQL_DROP );
326 SQLAllocStmt( dbh, &sth );
327 #endif /* BACKSQL_REALLOC_STMT */
331 #ifndef BACKSQL_REALLOC_STMT
332 SQLFreeStmt( sth, SQL_RESET_PARAMS );
333 #else /* BACKSQL_REALLOC_STMT */
334 SQLFreeStmt( sth, SQL_DROP );
335 #endif /* BACKSQL_REALLOC_STMT */
338 #ifndef BACKSQL_REALLOC_STMT
339 SQLFreeStmt( sth, SQL_DROP );
340 #endif /* BACKSQL_REALLOC_STMT */
343 * FIXME: should fail in case one change fails?
355 Modifications *modlist )
357 backsql_info *bi = (backsql_info*)be->be_private;
359 backsql_oc_map_rec *oc = NULL;
360 backsql_entryID e_id;
364 * FIXME: in case part of the operation cannot be performed
365 * (missing mapping, SQL write fails or so) the entire operation
366 * should be rolled-back
369 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): changing entry '%s'\n",
371 res = backsql_get_db_conn( be, conn, &dbh );
372 if ( res != LDAP_SUCCESS ) {
373 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
374 "could not get connection handle - exiting\n",
377 * FIXME: we don't want to send back
378 * excessively detailed messages
380 send_ldap_result( conn, op, res, "",
381 res == LDAP_OTHER ? "SQL-backend error" : "",
386 res = backsql_dn2id( bi, &e_id, dbh, ndn );
387 if ( res != LDAP_SUCCESS ) {
388 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
389 "could not lookup entry id\n", 0, 0, 0 );
390 send_ldap_result( conn, op, res , "",
391 res == LDAP_OTHER ? "SQL-backend error" : "",
396 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
397 "modifying entry '%s' (id=%ld)\n",
398 e_id.dn.bv_val, e_id.id, 0 );
400 oc = backsql_id2oc( bi, e_id.oc_id );
402 Debug( LDAP_DEBUG_TRACE, "backsql_modify(): "
403 "cannot determine objectclass of entry -- aborting\n",
406 * FIXME: should never occur, since the entry was built!!!
410 * FIXME: we don't want to send back
411 * excessively detailed messages
413 send_ldap_result( conn, op, LDAP_OTHER, "",
414 "SQL-backend error", NULL, NULL );
418 res = backsql_modify_internal( bi, dbh, oc, &e_id, modlist );
419 if ( res == LDAP_SUCCESS ) {
421 * Commit only if all operations succeed
423 * FIXME: backsql_modify_internal() does not fail
424 * if add/delete operations are not available, or
425 * if a multiple value add actually results in a replace,
426 * or if a single operation on an attribute fails
429 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
431 send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
432 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
444 struct berval *newrdn,
445 struct berval *nnewrdn,
447 struct berval *newSuperior,
448 struct berval *nnewSuperior )
450 backsql_info *bi = (backsql_info*)be->be_private;
454 backsql_entryID e_id, pe_id, new_pid;
455 backsql_oc_map_rec *oc = NULL;
457 struct berval p_dn, p_ndn,
458 *new_pdn = NULL, *new_npdn = NULL,
460 const char *text = NULL;
461 LDAPRDN *new_rdn = NULL;
462 LDAPRDN *old_rdn = NULL;
465 Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry '%s', "
466 "newrdn='%s', newSuperior='%s'\n",
467 dn->bv_val, newrdn->bv_val,
468 newSuperior ? newSuperior->bv_val : "(NULL)" );
469 res = backsql_get_db_conn( be, conn, &dbh );
470 if ( res != LDAP_SUCCESS ) {
471 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
472 "could not get connection handle - exiting\n",
474 send_ldap_result( conn, op, res, "",
475 res == LDAP_OTHER ? "SQL-backend error" : "",
480 res = backsql_dn2id( bi, &e_id, dbh, ndn );
481 if ( res != LDAP_SUCCESS ) {
482 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
483 "could not lookup entry id\n", 0, 0, 0 );
484 send_ldap_result( conn, op, res, "",
485 res == LDAP_OTHER ? "SQL-backend error" : "",
491 * FIXME: check whether entry has children
494 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): entry id is %ld\n",
497 dnParent( dn, &p_dn );
498 dnParent( ndn, &p_ndn );
502 * namingContext "" is not supported
504 if ( newSuperior->bv_len == 0 ) {
505 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
506 "newSuperior is \"\" - aborting\n", 0, 0, 0 );
507 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
508 "", "not allowed within namingContext",
513 new_pdn = newSuperior;
514 new_npdn = nnewSuperior;
521 if ( newSuperior && dn_match( &p_ndn, new_npdn ) ) {
522 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
523 "newSuperior is equal to old parent - ignored\n",
528 if ( newSuperior && dn_match( ndn, new_npdn ) ) {
529 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
530 "newSuperior is equal to entry being moved "
531 "- aborting\n", 0, 0, 0 );
532 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
537 build_new_dn( &new_dn, new_pdn, newrdn );
538 if ( dnNormalize2( NULL, &new_dn, &new_ndn ) != LDAP_SUCCESS ) {
539 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
540 "new dn is invalid ('%s') - aborting\n",
541 new_dn.bv_val, 0, 0 );
542 send_ldap_result( conn, op, LDAP_INVALID_DN_SYNTAX, "",
547 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): new entry dn is '%s'\n",
548 new_dn.bv_val, 0, 0 );
550 res = backsql_dn2id( bi, &pe_id, dbh, &p_ndn );
551 if ( res != LDAP_SUCCESS ) {
552 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
553 "could not lookup old parent entry id\n", 0, 0, 0 );
554 send_ldap_result( conn, op, res, "",
555 res == LDAP_OTHER ? "SQL-backend error" : "",
560 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
561 "old parent entry id is %ld\n", pe_id.id, 0, 0 );
563 res = backsql_dn2id( bi, &new_pid, dbh, new_npdn );
564 if ( res != LDAP_SUCCESS ) {
565 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
566 "could not lookup new parent entry id\n", 0, 0, 0 );
567 send_ldap_result( conn, op, res, "",
568 res == LDAP_OTHER ? "SQL-backend error" : "",
573 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
574 "new parent entry id is %ld\n", new_pid.id, 0, 0 );
577 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
578 "executing delentry_query\n", 0, 0, 0 );
579 SQLAllocStmt( dbh, &sth );
580 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
581 0, 0, &e_id.id, 0, 0 );
582 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
583 if ( rc != SQL_SUCCESS ) {
584 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
585 "failed to delete record from ldap_entries\n",
587 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
588 send_ldap_result( conn, op, LDAP_OTHER, "",
589 "SQL-backend error", NULL, NULL );
593 SQLFreeStmt( sth, SQL_RESET_PARAMS );
595 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
596 "executing insentry_query\n", 0, 0, 0 );
597 backsql_BindParamStr( sth, 1, new_dn.bv_val, BACKSQL_MAX_DN_LEN );
598 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
599 0, 0, &e_id.oc_id, 0, 0 );
600 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
601 0, 0, &new_pid.id, 0, 0 );
602 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
603 0, 0, &e_id.keyval, 0, 0 );
604 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
605 if ( rc != SQL_SUCCESS ) {
606 Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): "
607 "could not insert ldap_entries record\n", 0, 0, 0 );
608 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
609 send_ldap_result( conn, op, LDAP_OTHER, "",
610 "SQL-backend error", NULL, NULL );
614 /* Get attribute type and attribute value of our new rdn, we will
615 * need to add that to our new entry
617 if ( ldap_bv2rdn( newrdn, &new_rdn, (char **)&text,
618 LDAP_DN_FORMAT_LDAP ) ) {
620 LDAP_LOG ( OPERATION, ERR,
621 "backsql_modrdn: can't figure out "
622 "type(s)/values(s) of newrdn\n",
625 Debug( LDAP_DEBUG_TRACE,
626 "backsql_modrdn: can't figure out "
627 "type(s)/values(s) of newrdn\n",
630 rc = LDAP_INVALID_DN_SYNTAX;
635 LDAP_LOG ( OPERATION, RESULTS,
636 "backsql_modrdn: new_rdn_type=\"%s\", "
637 "new_rdn_val=\"%s\"\n",
638 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
639 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
641 Debug( LDAP_DEBUG_TRACE,
642 "backsql_modrdn: new_rdn_type=\"%s\", "
643 "new_rdn_val=\"%s\"\n",
644 new_rdn[ 0 ][ 0 ]->la_attr.bv_val,
645 new_rdn[ 0 ][ 0 ]->la_value.bv_val, 0 );
648 if ( deleteoldrdn ) {
649 if ( ldap_bv2rdn( dn, &old_rdn, (char **)&text,
650 LDAP_DN_FORMAT_LDAP ) ) {
652 LDAP_LOG ( OPERATION, ERR,
653 "backsql_modrdn: can't figure out "
654 "type(s)/values(s) of old_rdn\n",
657 Debug( LDAP_DEBUG_TRACE,
658 "backsql_modrdn: can't figure out "
659 "the old_rdn type(s)/value(s)\n",
667 res = slap_modrdn2mods( NULL, NULL, NULL, NULL, old_rdn, new_rdn,
668 deleteoldrdn, &mod );
669 if ( res != LDAP_SUCCESS ) {
673 oc = backsql_id2oc( bi, e_id.oc_id );
674 res = backsql_modify_internal( bi, dbh, oc, &e_id, mod );
676 if ( res != LDAP_SUCCESS ) {
681 * Commit only if all operations succeed
683 * FIXME: backsql_modify_internal() does not fail
684 * if add/delete operations are not available, or
685 * if a multiple value add actually results in a replace,
686 * or if a single operation on an attribute fails for any
689 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
692 SQLFreeStmt( sth, SQL_DROP );
694 if ( new_dn.bv_val ) {
695 ch_free( new_dn.bv_val );
698 if ( new_ndn.bv_val ) {
699 ch_free( new_ndn.bv_val );
702 /* LDAP v2 supporting correct attribute handling. */
703 if ( new_rdn != NULL ) {
704 ldap_rdnfree( new_rdn );
706 if ( old_rdn != NULL ) {
707 ldap_rdnfree( old_rdn );
711 for (; mod; mod=tmp ) {
717 send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
719 Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 );
730 backsql_info *bi = (backsql_info*)be->be_private;
733 unsigned long new_keyval = 0;
736 backsql_oc_map_rec *oc = NULL;
737 backsql_at_map_rec *at_rec = NULL;
738 backsql_entryID e_id, parent_id;
741 struct berval *at_val;
743 /* first parameter no, parameter order */
744 SQLUSMALLINT pno, po;
745 /* procedure return code */
748 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(): adding entry '%s'\n",
751 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
752 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
754 * FIXME: only the objectClass provided first
755 * is considered when creating a new entry
757 oc = backsql_name2oc( bi, &at->a_vals[ 0 ] );
763 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
764 "cannot determine objectclass of entry -- aborting\n",
766 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
767 "operation not permitted within namingContext",
772 if ( oc->create_proc == NULL ) {
773 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
774 "create procedure is not defined for this objectclass "
775 "- aborting\n", 0, 0, 0 );
776 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
777 "operation not permitted within namingContext",
782 prc = backsql_get_db_conn( be, conn, &dbh );
783 if ( prc != LDAP_SUCCESS ) {
784 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
785 "could not get connection handle - exiting\n",
787 send_ldap_result( conn, op, prc, "",
788 prc == LDAP_OTHER ? "SQL-backend error" : "",
794 * Check if entry exists
796 res = backsql_dn2id( bi, &e_id, dbh, &e->e_name );
797 if ( res == LDAP_SUCCESS ) {
798 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
799 "entry '%s' exists\n",
800 e->e_name.bv_val, 0, 0 );
801 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "",
807 * Check if parent exists
809 dnParent( &e->e_name, &pdn );
810 res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
811 if ( res != LDAP_SUCCESS ) {
814 * NO SUCH OBJECT seems more appropriate
816 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
817 "could not lookup parent entry for new record '%s'\n",
820 if ( res != LDAP_NO_SUCH_OBJECT ) {
821 send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
833 dnParent( &dn, &pdn );
836 * Empty DN ("") defaults to LDAP_SUCCESS
838 res = backsql_dn2id( bi, &parent_id, dbh, &pdn );
840 case LDAP_NO_SUCH_OBJECT:
841 if ( pdn.bv_len > 0 ) {
844 /* fail over to next case */
847 matched = pdn.bv_val;
848 /* fail over to next case */
851 send_ldap_result( conn, op, res, matched,
859 * create_proc is executed; if expect_return is set, then
860 * an output parameter is bound, which should contain
861 * the id of the added row; otherwise the procedure
862 * is expected to return the id as the first column of a select
865 #ifndef BACKSQL_REALLOC_STMT
866 rc = SQLAllocStmt( dbh, &sth );
867 #else /* BACKSQL_REALLOC_STMT */
868 rc = backsql_Prepare( dbh, &sth, oc->create_proc, 0 );
869 #endif /* BACKSQL_REALLOC_STMT */
870 if ( rc != SQL_SUCCESS ) {
871 send_ldap_result( conn, op, LDAP_OTHER, "",
872 "SQL-backend error", NULL, NULL );
876 if ( BACKSQL_IS_ADD( oc->expect_return ) ) {
877 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
878 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
881 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s'\n",
882 oc->create_proc, 0, 0 );
883 #ifndef BACKSQL_REALLOC_STMT
884 rc = SQLExecDirect( sth, oc->create_proc, SQL_NTS );
885 #else /* BACKSQL_REALLOC_STMT */
886 rc = SQLExecute( sth );
887 #endif /* BACKSQL_REALLOC_STMT */
888 if ( rc != SQL_SUCCESS ) {
889 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
890 "create_proc execution failed\n", 0, 0, 0 );
891 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
892 SQLFreeStmt( sth, SQL_DROP );
893 send_ldap_result( conn, op, LDAP_OTHER, "",
894 "SQL-backend error", NULL, NULL );
898 if ( !BACKSQL_IS_ADD( oc->expect_return ) ) {
903 * the query to know the id of the inserted entry
904 * must be embedded in the create procedure
906 rc = SQLNumResultCols( sth, &ncols );
907 if ( rc != SQL_SUCCESS ) {
908 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
909 "create_proc result evaluation failed\n",
911 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
912 SQLFreeStmt( sth, SQL_DROP );
913 send_ldap_result( conn, op, LDAP_OTHER, "",
914 "SQL-backend error", NULL, NULL );
917 } else if ( ncols != 1 ) {
918 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
919 "create_proc result is bogus\n",
921 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
922 SQLFreeStmt( sth, SQL_DROP );
923 send_ldap_result( conn, op, LDAP_OTHER, "",
924 "SQL-backend error", NULL, NULL );
930 SQLCHAR colname[ 64 ];
931 SQLSMALLINT name_len, col_type, col_scale, col_null;
935 * FIXME: check whether col_type is compatible,
936 * if it can be null and so on ...
938 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
940 (SQLUINTEGER)( sizeof( colname ) - 1 ),
941 &name_len, &col_type,
942 &col_prec, &col_scale, &col_null );
946 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
947 (SQLPOINTER)&new_keyval,
948 (SQLINTEGER)sizeof( new_keyval ),
951 rc = SQLFetch( sth );
955 * FIXME: what does is_null mean?
958 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
959 "create_proc result is null\n",
961 backsql_PrintErrors( bi->db_env, dbh, sth, rc);
962 SQLFreeStmt( sth, SQL_DROP );
963 send_ldap_result( conn, op, LDAP_OTHER, "",
964 "SQL-backend error", NULL, NULL );
970 #ifndef BACKSQL_REALLOC_STMT
971 SQLFreeStmt( sth, SQL_RESET_PARAMS );
972 #else /* BACKSQL_REALLOC_STMT */
973 SQLFreeStmt( sth, SQL_DROP );
974 #endif /* BACKSQL_REALLOC_STMT */
976 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
977 "create_proc returned keyval=%ld\n", new_keyval, 0, 0 );
979 for ( at = e->e_attrs; at != NULL; at = at->a_next ) {
980 SQLUSMALLINT currpos;
982 if ( at->a_vals[ 0 ].bv_val == NULL ) {
986 at_rec = backsql_ad2at( oc, at->a_desc );
988 if ( at_rec == NULL ) {
989 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
990 "attribute '%s' is not registered "
991 "in objectclass '%s'\n",
992 at->a_desc->ad_cname.bv_val,
993 oc->name.bv_val, 0 );
997 if ( at_rec->add_proc == NULL ) {
998 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
999 "add procedure is not defined "
1000 "for attribute '%s'\n",
1001 at->a_desc->ad_cname.bv_val, 0, 0 );
1005 #ifdef BACKSQL_REALLOC_STMT
1006 rc = backsql_Prepare( dbh, &sth, at_rec->add_proc, 0 );
1007 if ( rc != SQL_SUCCESS ) {
1010 #endif /* BACKSQL_REALLOC_STMT */
1012 if ( BACKSQL_IS_ADD( at_rec->expect_return ) ) {
1014 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT,
1015 SQL_C_ULONG, SQL_INTEGER,
1021 po = ( BACKSQL_IS_ADD( at_rec->param_order ) ) > 0;
1022 currpos = pno + 1 + po;
1023 SQLBindParameter( sth, currpos,
1024 SQL_PARAM_INPUT, SQL_C_ULONG,
1025 SQL_INTEGER, 0, 0, &new_keyval, 0, 0 );
1026 currpos = pno + 2 - po;
1028 for ( i = 0, at_val = &at->a_vals[ 0 ];
1029 at_val->bv_val != NULL;
1030 i++, at_val = &at->a_vals[ i ] ) {
1033 * check for syntax needed here
1034 * maybe need binary bind?
1037 backsql_BindParamStr( sth, currpos,
1038 at_val->bv_val, at_val->bv_len + 1 );
1039 #ifdef SECURITY_PARANOID
1040 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1041 "executing '%s', id=%ld\n",
1042 at_rec->add_proc, new_keyval, 0 );
1044 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1045 "executing '%s' with val='%s', id=%ld\n",
1046 at_rec->add_proc, at_val->bv_val, new_keyval );
1048 #ifndef BACKSQL_REALLOC_STMT
1049 rc = SQLExecDirect( sth, at_rec->add_proc, SQL_NTS );
1050 #else /* BACKSQL_REALLOC_STMT */
1051 rc = SQLExecute( sth );
1052 #endif /* BACKSQL_REALLOC_STMT */
1053 if ( rc != SQL_SUCCESS ) {
1054 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1055 "add_proc execution failed\n",
1057 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1060 #ifndef BACKSQL_REALLOC_STMT
1061 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1062 #else /* BACKSQL_REALLOC_STMT */
1063 SQLFreeStmt( sth, SQL_DROP );
1064 #endif /* BACKSQL_REALLOC_STMT */
1067 #ifdef BACKSQL_REALLOC_STMT
1068 rc = backsql_Prepare( dbh, &sth, bi->insentry_query, 0 );
1069 if ( rc != SQL_SUCCESS ) {
1070 send_ldap_result( conn, op, LDAP_OTHER, "",
1071 "SQL-backend error", NULL, NULL );
1074 #endif /* BACKSQL_REALLOC_STMT */
1075 backsql_BindParamStr( sth, 1, e->e_name.bv_val, BACKSQL_MAX_DN_LEN );
1076 SQLBindParameter( sth, 2, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1077 0, 0, &oc->id, 0, 0 );
1078 SQLBindParameter( sth, 3, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1079 0, 0, &parent_id.id, 0, 0 );
1080 SQLBindParameter( sth, 4, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER,
1081 0, 0, &new_keyval, 0, 0 );
1083 Debug( LDAP_DEBUG_TRACE, "backsql_add(): executing '%s' for dn '%s'\n",
1084 bi->insentry_query, e->e_name.bv_val, 0 );
1085 Debug( LDAP_DEBUG_TRACE, " for oc_map_id=%ld, parent_id=%ld, "
1086 "keyval=%ld\n", oc->id, parent_id.id, new_keyval );
1087 #ifndef BACKSQL_REALLOC_STMT
1088 rc = SQLExecDirect( sth, bi->insentry_query, SQL_NTS );
1089 #else /* BACKSQL_REALLOC_STMT */
1090 rc = SQLExecute( sth );
1091 #endif /* BACKSQL_REALLOC_STMT */
1092 if ( rc != SQL_SUCCESS ) {
1093 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1094 "could not insert ldap_entries record\n", 0, 0, 0 );
1095 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1098 * execute delete_proc to delete data added !!!
1100 SQLFreeStmt( sth, SQL_DROP );
1101 send_ldap_result( conn, op, LDAP_OTHER, "",
1102 "SQL-backend error", NULL, NULL );
1106 SQLFreeStmt( sth, SQL_DROP );
1109 * Commit only if all operations succeed
1111 * FIXME: backsql_add() does not fail if add operations
1112 * are not available for some attributes, or if
1113 * a multiple value add actually results in a replace,
1114 * or if a single operation on an attribute fails
1117 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
1119 send_ldap_result( conn, op, LDAP_SUCCESS, "",
1130 struct berval *ndn )
1132 backsql_info *bi = (backsql_info*)be->be_private;
1136 backsql_oc_map_rec *oc = NULL;
1137 backsql_entryID e_id;
1139 /* first parameter no */
1142 Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry '%s'\n",
1143 ndn->bv_val, 0, 0 );
1144 res = backsql_get_db_conn( be, conn, &dbh );
1145 if ( res != LDAP_SUCCESS ) {
1146 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1147 "could not get connection handle - exiting\n",
1149 send_ldap_result( conn, op, res, "",
1150 res == LDAP_OTHER ? "SQL-backend error" : "",
1155 res = backsql_dn2id( bi, &e_id, dbh, ndn );
1156 if ( res != LDAP_SUCCESS ) {
1157 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1158 "could not lookup entry id\n", 0, 0, 0 );
1159 send_ldap_result( conn, op, res, "", NULL, NULL, NULL );
1163 oc = backsql_id2oc( bi, e_id.oc_id );
1165 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1166 "cannot determine objectclass of entry "
1167 "-- aborting\n", 0, 0, 0 );
1168 send_ldap_result( conn, op, LDAP_OTHER, "",
1169 "SQL-backend error", NULL, NULL );
1173 if ( oc->delete_proc == NULL ) {
1174 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1175 "delete procedure is not defined "
1176 "for this objectclass - aborting\n", 0, 0, 0 );
1177 send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, "",
1178 "operation not supported for required DN",
1183 SQLAllocStmt( dbh, &sth );
1184 if ( BACKSQL_IS_DEL( oc->expect_return ) ) {
1186 SQLBindParameter( sth, 1, SQL_PARAM_OUTPUT, SQL_C_ULONG,
1187 SQL_INTEGER, 0, 0, &rc, 0, 0 );
1192 SQLBindParameter( sth, pno + 1, SQL_PARAM_INPUT,
1193 SQL_C_ULONG, SQL_INTEGER, 0, 0, &e_id.keyval, 0, 0 );
1195 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): executing '%s'\n",
1196 oc->delete_proc, 0, 0 );
1197 rc = SQLExecDirect( sth, oc->delete_proc, SQL_NTS );
1198 if ( rc != SQL_SUCCESS ) {
1199 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1200 "delete_proc execution failed\n", 0, 0, 0 );
1201 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1202 SQLFreeStmt( sth, SQL_DROP );
1203 send_ldap_result( conn, op, LDAP_OTHER, "",
1204 "SQL-backend error", NULL, NULL );
1207 #ifndef BACKSQL_REALLOC_STMT
1208 SQLFreeStmt( sth, SQL_RESET_PARAMS );
1209 #else /* BACKSQL_REALLOC_STMT */
1210 SQLFreeStmt( sth, SQL_DROP );
1211 SQLAllocStmt( dbh, &sth );
1212 #endif /* BACKSQL_REALLOC_STMT */
1214 SQLBindParameter( sth, 1, SQL_PARAM_INPUT, SQL_C_ULONG, SQL_INTEGER,
1215 0, 0, &e_id.id, 0, 0 );
1216 rc = SQLExecDirect( sth, bi->delentry_query, SQL_NTS );
1217 if ( rc != SQL_SUCCESS ) {
1218 Debug( LDAP_DEBUG_TRACE, "backsql_delete(): "
1219 "failed to delete record from ldap_entries\n",
1221 backsql_PrintErrors( bi->db_env, dbh, sth, rc );
1222 SQLFreeStmt( sth, SQL_DROP );
1223 send_ldap_result( conn, op, LDAP_OTHER, "",
1224 "SQL-backend error", NULL, NULL );
1228 SQLFreeStmt( sth, SQL_DROP );
1231 * Commit only if all operations succeed
1233 * FIXME: backsql_add() does not fail if add operations
1234 * are not available for some attributes, or if
1235 * a multiple value add actually results in a replace,
1236 * or if a single operation on an attribute fails
1239 SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
1241 send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
1242 Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );
1246 #endif /* SLAPD_SQL */