add.c revision 1.1.1.6.6.1 1 /* $NetBSD: add.c,v 1.1.1.6.6.1 2019/08/10 06:17:20 martin Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2019 The OpenLDAP Foundation.
7 * Portions Copyright 1999 Dmitry Kovalev.
8 * Portions Copyright 2002 Pierangelo Masarati.
9 * Portions Copyright 2004 Mark Adamson.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted only as authorized by the OpenLDAP
14 * Public License.
15 *
16 * A copy of this license is available in the file LICENSE in the
17 * top-level directory of the distribution or, alternatively, at
18 * <http://www.OpenLDAP.org/license.html>.
19 */
20 /* ACKNOWLEDGEMENTS:
21 * This work was initially developed by Dmitry Kovalev for inclusion
22 * by OpenLDAP Software. Additional significant contributors include
23 * Pierangelo Masarati and Mark Adamson.
24
25 */
26
27 #include <sys/cdefs.h>
28 __RCSID("$NetBSD: add.c,v 1.1.1.6.6.1 2019/08/10 06:17:20 martin Exp $");
29
30 #include "portable.h"
31
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include "ac/string.h"
35
36 #include "slap.h"
37 #include "proto-sql.h"
38
39 #ifdef BACKSQL_SYNCPROV
40 #include <lutil.h>
41 #endif /* BACKSQL_SYNCPROV */
42
43 /*
44 * Skip:
45 * - null values (e.g. delete modification)
46 * - single occurrence of objectClass, because it is already used
47 * to determine how to build the SQL entry
48 * - operational attributes
49 * - empty attributes
50 */
51 #define backsql_opattr_skip(ad) \
52 (is_at_operational( (ad)->ad_type ) && (ad) != slap_schema.si_ad_ref )
53 #define backsql_attr_skip(ad, vals) \
54 ( \
55 ( (ad) == slap_schema.si_ad_objectClass \
56 && (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
57 || backsql_opattr_skip( (ad) ) \
58 || ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
59 )
60
61 int
62 backsql_modify_delete_all_values(
63 Operation *op,
64 SlapReply *rs,
65 SQLHDBC dbh,
66 backsql_entryID *e_id,
67 backsql_at_map_rec *at )
68 {
69 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
70 RETCODE rc;
71 SQLHSTMT asth = SQL_NULL_HSTMT;
72 BACKSQL_ROW_NTS row;
73
74 assert( at != NULL );
75 if ( at->bam_delete_proc == NULL ) {
76 Debug( LDAP_DEBUG_TRACE,
77 " backsql_modify_delete_all_values(): "
78 "missing attribute value delete procedure "
79 "for attr \"%s\"\n",
80 at->bam_ad->ad_cname.bv_val, 0, 0 );
81 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
82 rs->sr_text = "SQL-backend error";
83 return rs->sr_err = LDAP_OTHER;
84 }
85
86 return LDAP_SUCCESS;
87 }
88
89 rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
90 if ( rc != SQL_SUCCESS ) {
91 Debug( LDAP_DEBUG_TRACE,
92 " backsql_modify_delete_all_values(): "
93 "error preparing attribute value select query "
94 "\"%s\"\n",
95 at->bam_query, 0, 0 );
96 backsql_PrintErrors( bi->sql_db_env, dbh,
97 asth, rc );
98
99 rs->sr_text = "SQL-backend error";
100 return rs->sr_err = LDAP_OTHER;
101 }
102
103 rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
104 if ( rc != SQL_SUCCESS ) {
105 Debug( LDAP_DEBUG_TRACE,
106 " backsql_modify_delete_all_values(): "
107 "error binding key value parameter "
108 "to attribute value select query\n",
109 0, 0, 0 );
110 backsql_PrintErrors( bi->sql_db_env, dbh,
111 asth, rc );
112 SQLFreeStmt( asth, SQL_DROP );
113
114 rs->sr_text = "SQL-backend error";
115 return rs->sr_err = LDAP_OTHER;
116 }
117
118 rc = SQLExecute( asth );
119 if ( !BACKSQL_SUCCESS( rc ) ) {
120 Debug( LDAP_DEBUG_TRACE,
121 " backsql_modify_delete_all_values(): "
122 "error executing attribute value select query\n",
123 0, 0, 0 );
124 backsql_PrintErrors( bi->sql_db_env, dbh,
125 asth, rc );
126 SQLFreeStmt( asth, SQL_DROP );
127
128 rs->sr_text = "SQL-backend error";
129 return rs->sr_err = LDAP_OTHER;
130 }
131
132 backsql_BindRowAsStrings_x( asth, &row, op->o_tmpmemctx );
133 for ( rc = SQLFetch( asth );
134 BACKSQL_SUCCESS( rc );
135 rc = SQLFetch( asth ) )
136 {
137 int i;
138 /* first parameter no, parameter order */
139 SQLUSMALLINT pno = 0,
140 po = 0;
141 /* procedure return code */
142 int prc = LDAP_SUCCESS;
143
144 for ( i = 0; i < row.ncols; i++ ) {
145 SQLHSTMT sth = SQL_NULL_HSTMT;
146 ber_len_t col_len;
147
148 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
149 if ( rc != SQL_SUCCESS ) {
150 Debug( LDAP_DEBUG_TRACE,
151 " backsql_modify_delete_all_values(): "
152 "error preparing attribute value "
153 "delete procedure "
154 "\"%s\"\n",
155 at->bam_delete_proc, 0, 0 );
156 backsql_PrintErrors( bi->sql_db_env, dbh,
157 sth, rc );
158
159 rs->sr_text = "SQL-backend error";
160 rs->sr_err = LDAP_OTHER;
161 goto done;
162 }
163
164 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
165 pno = 1;
166 rc = backsql_BindParamInt( sth, 1,
167 SQL_PARAM_OUTPUT, &prc );
168 if ( rc != SQL_SUCCESS ) {
169 Debug( LDAP_DEBUG_TRACE,
170 " backsql_modify_delete_all_values(): "
171 "error binding output parameter for %s[%d]\n",
172 at->bam_ad->ad_cname.bv_val, i, 0 );
173 backsql_PrintErrors( bi->sql_db_env, dbh,
174 sth, rc );
175 SQLFreeStmt( sth, SQL_DROP );
176
177 rs->sr_text = "SQL-backend error";
178 rs->sr_err = LDAP_OTHER;
179 goto done;
180 }
181 }
182 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
183 rc = backsql_BindParamID( sth, pno + 1 + po,
184 SQL_PARAM_INPUT, &e_id->eid_keyval );
185 if ( rc != SQL_SUCCESS ) {
186 Debug( LDAP_DEBUG_TRACE,
187 " backsql_modify_delete_all_values(): "
188 "error binding keyval parameter for %s[%d]\n",
189 at->bam_ad->ad_cname.bv_val, i, 0 );
190 backsql_PrintErrors( bi->sql_db_env, dbh,
191 sth, rc );
192 SQLFreeStmt( sth, SQL_DROP );
193
194 rs->sr_text = "SQL-backend error";
195 rs->sr_err = LDAP_OTHER;
196 goto done;
197 }
198
199 Debug( LDAP_DEBUG_TRACE,
200 " backsql_modify_delete_all_values() "
201 "arg(%d)=" BACKSQL_IDFMT "\n",
202 pno + 1 + po,
203 BACKSQL_IDARG(e_id->eid_keyval), 0 );
204
205 /*
206 * check for syntax needed here
207 * maybe need binary bind?
208 */
209 col_len = strlen( row.cols[ i ] );
210 rc = backsql_BindParamStr( sth, pno + 2 - po,
211 SQL_PARAM_INPUT, row.cols[ i ], col_len );
212 if ( rc != SQL_SUCCESS ) {
213 Debug( LDAP_DEBUG_TRACE,
214 " backsql_modify_delete_all_values(): "
215 "error binding value parameter for %s[%d]\n",
216 at->bam_ad->ad_cname.bv_val, i, 0 );
217 backsql_PrintErrors( bi->sql_db_env, dbh,
218 sth, rc );
219 SQLFreeStmt( sth, SQL_DROP );
220
221 rs->sr_text = "SQL-backend error";
222 rs->sr_err = LDAP_OTHER;
223 goto done;
224 }
225
226 Debug( LDAP_DEBUG_TRACE,
227 " backsql_modify_delete_all_values(): "
228 "arg(%d)=%s; executing \"%s\"\n",
229 pno + 2 - po, row.cols[ i ],
230 at->bam_delete_proc );
231 rc = SQLExecute( sth );
232 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
233 rs->sr_err = LDAP_SUCCESS;
234
235 } else {
236 Debug( LDAP_DEBUG_TRACE,
237 " backsql_modify_delete_all_values(): "
238 "delete_proc "
239 "execution failed (rc=%d, prc=%d)\n",
240 rc, prc, 0 );
241 if ( prc != LDAP_SUCCESS ) {
242 /* SQL procedure executed fine
243 * but returned an error */
244 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
245
246 } else {
247 backsql_PrintErrors( bi->sql_db_env, dbh,
248 sth, rc );
249 rs->sr_err = LDAP_OTHER;
250 }
251 rs->sr_text = op->o_req_dn.bv_val;
252 SQLFreeStmt( sth, SQL_DROP );
253 goto done;
254 }
255 SQLFreeStmt( sth, SQL_DROP );
256 }
257 }
258
259 rs->sr_err = LDAP_SUCCESS;
260
261 done:;
262 backsql_FreeRow_x( &row, op->o_tmpmemctx );
263 SQLFreeStmt( asth, SQL_DROP );
264
265 return rs->sr_err;
266 }
267
268 int
269 backsql_modify_internal(
270 Operation *op,
271 SlapReply *rs,
272 SQLHDBC dbh,
273 backsql_oc_map_rec *oc,
274 backsql_entryID *e_id,
275 Modifications *modlist )
276 {
277 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
278 RETCODE rc;
279 Modifications *ml;
280
281 Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
282 "traversing modifications list\n", 0, 0, 0 );
283
284 for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
285 AttributeDescription *ad;
286 int sm_op;
287 static char *sm_ops[] = { "add", "delete", "replace", "increment", NULL };
288
289 BerVarray sm_values;
290 #if 0
291 /* NOTE: some day we'll have to pass
292 * the normalized values as well */
293 BerVarray sm_nvalues;
294 #endif
295 backsql_at_map_rec *at = NULL;
296 struct berval *at_val;
297 int i;
298
299 ad = ml->sml_mod.sm_desc;
300 sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
301 sm_values = ml->sml_mod.sm_values;
302 #if 0
303 sm_nvalues = ml->sml_mod.sm_nvalues;
304 #endif
305
306 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
307 "modifying attribute \"%s\" (%s) according to "
308 "mappings for objectClass \"%s\"\n",
309 ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
310
311 if ( backsql_attr_skip( ad, sm_values ) ) {
312 continue;
313 }
314
315 at = backsql_ad2at( oc, ad );
316 if ( at == NULL ) {
317 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
318 "attribute \"%s\" is not registered "
319 "in objectClass \"%s\"\n",
320 ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
321
322 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
323 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
324 rs->sr_text = "operation not permitted "
325 "within namingContext";
326 goto done;
327 }
328
329 continue;
330 }
331
332 switch ( sm_op ) {
333 case LDAP_MOD_REPLACE: {
334 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
335 "replacing values for attribute \"%s\"\n",
336 at->bam_ad->ad_cname.bv_val, 0, 0 );
337
338 if ( at->bam_add_proc == NULL ) {
339 Debug( LDAP_DEBUG_TRACE,
340 " backsql_modify_internal(): "
341 "add procedure is not defined "
342 "for attribute \"%s\" "
343 "- unable to perform replacements\n",
344 at->bam_ad->ad_cname.bv_val, 0, 0 );
345
346 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
347 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
348 rs->sr_text = "operation not permitted "
349 "within namingContext";
350 goto done;
351 }
352
353 break;
354 }
355
356 if ( at->bam_delete_proc == NULL ) {
357 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
358 Debug( LDAP_DEBUG_TRACE,
359 " backsql_modify_internal(): "
360 "delete procedure is not defined "
361 "for attribute \"%s\"\n",
362 at->bam_ad->ad_cname.bv_val, 0, 0 );
363
364 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
365 rs->sr_text = "operation not permitted "
366 "within namingContext";
367 goto done;
368 }
369
370 Debug( LDAP_DEBUG_TRACE,
371 " backsql_modify_internal(): "
372 "delete procedure is not defined "
373 "for attribute \"%s\" "
374 "- adding only\n",
375 at->bam_ad->ad_cname.bv_val, 0, 0 );
376
377 goto add_only;
378 }
379
380 del_all:
381 rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
382 if ( rs->sr_err != LDAP_SUCCESS ) {
383 goto done;
384 }
385
386 /* LDAP_MOD_DELETE gets here if all values must be deleted */
387 if ( sm_op == LDAP_MOD_DELETE ) {
388 break;
389 }
390 }
391
392 /*
393 * PASSTHROUGH - to add new attributes -- do NOT add break
394 */
395 case LDAP_MOD_ADD:
396 /* case SLAP_MOD_SOFTADD: */
397 /* case SLAP_MOD_ADD_IF_NOT_PRESENT: */
398 add_only:;
399 if ( at->bam_add_proc == NULL ) {
400 Debug( LDAP_DEBUG_TRACE,
401 " backsql_modify_internal(): "
402 "add procedure is not defined "
403 "for attribute \"%s\"\n",
404 at->bam_ad->ad_cname.bv_val, 0, 0 );
405
406 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
407 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
408 rs->sr_text = "operation not permitted "
409 "within namingContext";
410 goto done;
411 }
412
413 break;
414 }
415
416 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
417 "adding new values for attribute \"%s\"\n",
418 at->bam_ad->ad_cname.bv_val, 0, 0 );
419
420 /* can't add a NULL val array */
421 assert( sm_values != NULL );
422
423 for ( i = 0, at_val = sm_values;
424 !BER_BVISNULL( at_val );
425 i++, at_val++ )
426 {
427 SQLHSTMT sth = SQL_NULL_HSTMT;
428 /* first parameter position, parameter order */
429 SQLUSMALLINT pno = 0,
430 po;
431 /* procedure return code */
432 int prc = LDAP_SUCCESS;
433
434 rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
435 if ( rc != SQL_SUCCESS ) {
436 Debug( LDAP_DEBUG_TRACE,
437 " backsql_modify_internal(): "
438 "error preparing add query\n",
439 0, 0, 0 );
440 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
441
442 rs->sr_err = LDAP_OTHER;
443 rs->sr_text = "SQL-backend error";
444 goto done;
445 }
446
447 if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
448 pno = 1;
449 rc = backsql_BindParamInt( sth, 1,
450 SQL_PARAM_OUTPUT, &prc );
451 if ( rc != SQL_SUCCESS ) {
452 Debug( LDAP_DEBUG_TRACE,
453 " backsql_modify_internal(): "
454 "error binding output parameter for %s[%d]\n",
455 at->bam_ad->ad_cname.bv_val, i, 0 );
456 backsql_PrintErrors( bi->sql_db_env, dbh,
457 sth, rc );
458 SQLFreeStmt( sth, SQL_DROP );
459
460 rs->sr_text = "SQL-backend error";
461 rs->sr_err = LDAP_OTHER;
462 goto done;
463 }
464 }
465 po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
466 rc = backsql_BindParamID( sth, pno + 1 + po,
467 SQL_PARAM_INPUT, &e_id->eid_keyval );
468 if ( rc != SQL_SUCCESS ) {
469 Debug( LDAP_DEBUG_TRACE,
470 " backsql_modify_internal(): "
471 "error binding keyval parameter for %s[%d]\n",
472 at->bam_ad->ad_cname.bv_val, i, 0 );
473 backsql_PrintErrors( bi->sql_db_env, dbh,
474 sth, rc );
475 SQLFreeStmt( sth, SQL_DROP );
476
477 rs->sr_text = "SQL-backend error";
478 rs->sr_err = LDAP_OTHER;
479 goto done;
480 }
481
482 Debug( LDAP_DEBUG_TRACE,
483 " backsql_modify_internal(): "
484 "arg(%d)=" BACKSQL_IDFMT "\n",
485 pno + 1 + po,
486 BACKSQL_IDARG(e_id->eid_keyval), 0 );
487
488 /*
489 * check for syntax needed here
490 * maybe need binary bind?
491 */
492 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
493 SQL_PARAM_INPUT, at_val );
494 if ( rc != SQL_SUCCESS ) {
495 Debug( LDAP_DEBUG_TRACE,
496 " backsql_modify_internal(): "
497 "error binding value parameter for %s[%d]\n",
498 at->bam_ad->ad_cname.bv_val, i, 0 );
499 backsql_PrintErrors( bi->sql_db_env, dbh,
500 sth, rc );
501 SQLFreeStmt( sth, SQL_DROP );
502
503 rs->sr_text = "SQL-backend error";
504 rs->sr_err = LDAP_OTHER;
505 goto done;
506 }
507 Debug( LDAP_DEBUG_TRACE,
508 " backsql_modify_internal(): "
509 "arg(%d)=\"%s\"; executing \"%s\"\n",
510 pno + 2 - po, at_val->bv_val,
511 at->bam_add_proc );
512
513 rc = SQLExecute( sth );
514 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
515 rs->sr_err = LDAP_SUCCESS;
516
517 } else {
518 Debug( LDAP_DEBUG_TRACE,
519 " backsql_modify_internal(): "
520 "add_proc execution failed "
521 "(rc=%d, prc=%d)\n",
522 rc, prc, 0 );
523 if ( prc != LDAP_SUCCESS ) {
524 /* SQL procedure executed fine
525 * but returned an error */
526 SQLFreeStmt( sth, SQL_DROP );
527
528 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
529 rs->sr_text = at->bam_ad->ad_cname.bv_val;
530 return rs->sr_err;
531
532 } else {
533 backsql_PrintErrors( bi->sql_db_env, dbh,
534 sth, rc );
535 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) )
536 {
537 SQLFreeStmt( sth, SQL_DROP );
538
539 rs->sr_err = LDAP_OTHER;
540 rs->sr_text = "SQL-backend error";
541 goto done;
542 }
543 }
544 }
545 SQLFreeStmt( sth, SQL_DROP );
546 }
547 break;
548
549 case LDAP_MOD_DELETE:
550 /* case SLAP_MOD_SOFTDEL: */
551 if ( at->bam_delete_proc == NULL ) {
552 Debug( LDAP_DEBUG_TRACE,
553 " backsql_modify_internal(): "
554 "delete procedure is not defined "
555 "for attribute \"%s\"\n",
556 at->bam_ad->ad_cname.bv_val, 0, 0 );
557
558 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
559 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
560 rs->sr_text = "operation not permitted "
561 "within namingContext";
562 goto done;
563 }
564
565 break;
566 }
567
568 if ( sm_values == NULL ) {
569 Debug( LDAP_DEBUG_TRACE,
570 " backsql_modify_internal(): "
571 "no values given to delete "
572 "for attribute \"%s\" "
573 "-- deleting all values\n",
574 at->bam_ad->ad_cname.bv_val, 0, 0 );
575 goto del_all;
576 }
577
578 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
579 "deleting values for attribute \"%s\"\n",
580 at->bam_ad->ad_cname.bv_val, 0, 0 );
581
582 for ( i = 0, at_val = sm_values;
583 !BER_BVISNULL( at_val );
584 i++, at_val++ )
585 {
586 SQLHSTMT sth = SQL_NULL_HSTMT;
587 /* first parameter position, parameter order */
588 SQLUSMALLINT pno = 0,
589 po;
590 /* procedure return code */
591 int prc = LDAP_SUCCESS;
592
593 rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
594 if ( rc != SQL_SUCCESS ) {
595 Debug( LDAP_DEBUG_TRACE,
596 " backsql_modify_internal(): "
597 "error preparing delete query\n",
598 0, 0, 0 );
599 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
600
601 rs->sr_err = LDAP_OTHER;
602 rs->sr_text = "SQL-backend error";
603 goto done;
604 }
605
606 if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
607 pno = 1;
608 rc = backsql_BindParamInt( sth, 1,
609 SQL_PARAM_OUTPUT, &prc );
610 if ( rc != SQL_SUCCESS ) {
611 Debug( LDAP_DEBUG_TRACE,
612 " backsql_modify_internal(): "
613 "error binding output parameter for %s[%d]\n",
614 at->bam_ad->ad_cname.bv_val, i, 0 );
615 backsql_PrintErrors( bi->sql_db_env, dbh,
616 sth, rc );
617 SQLFreeStmt( sth, SQL_DROP );
618
619 rs->sr_text = "SQL-backend error";
620 rs->sr_err = LDAP_OTHER;
621 goto done;
622 }
623 }
624 po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
625 rc = backsql_BindParamID( sth, pno + 1 + po,
626 SQL_PARAM_INPUT, &e_id->eid_keyval );
627 if ( rc != SQL_SUCCESS ) {
628 Debug( LDAP_DEBUG_TRACE,
629 " backsql_modify_internal(): "
630 "error binding keyval parameter for %s[%d]\n",
631 at->bam_ad->ad_cname.bv_val, i, 0 );
632 backsql_PrintErrors( bi->sql_db_env, dbh,
633 sth, rc );
634 SQLFreeStmt( sth, SQL_DROP );
635
636 rs->sr_text = "SQL-backend error";
637 rs->sr_err = LDAP_OTHER;
638 goto done;
639 }
640
641 Debug( LDAP_DEBUG_TRACE,
642 " backsql_modify_internal(): "
643 "arg(%d)=" BACKSQL_IDFMT "\n",
644 pno + 1 + po,
645 BACKSQL_IDARG(e_id->eid_keyval), 0 );
646
647 /*
648 * check for syntax needed here
649 * maybe need binary bind?
650 */
651 rc = backsql_BindParamBerVal( sth, pno + 2 - po,
652 SQL_PARAM_INPUT, at_val );
653 if ( rc != SQL_SUCCESS ) {
654 Debug( LDAP_DEBUG_TRACE,
655 " backsql_modify_internal(): "
656 "error binding value parameter for %s[%d]\n",
657 at->bam_ad->ad_cname.bv_val, i, 0 );
658 backsql_PrintErrors( bi->sql_db_env, dbh,
659 sth, rc );
660 SQLFreeStmt( sth, SQL_DROP );
661
662 rs->sr_text = "SQL-backend error";
663 rs->sr_err = LDAP_OTHER;
664 goto done;
665 }
666
667 Debug( LDAP_DEBUG_TRACE,
668 " backsql_modify_internal(): "
669 "executing \"%s\"\n",
670 at->bam_delete_proc, 0, 0 );
671 rc = SQLExecute( sth );
672 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS )
673 {
674 rs->sr_err = LDAP_SUCCESS;
675
676 } else {
677 Debug( LDAP_DEBUG_TRACE,
678 " backsql_modify_internal(): "
679 "delete_proc execution "
680 "failed (rc=%d, prc=%d)\n",
681 rc, prc, 0 );
682
683 if ( prc != LDAP_SUCCESS ) {
684 /* SQL procedure executed fine
685 * but returned an error */
686 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
687 rs->sr_text = at->bam_ad->ad_cname.bv_val;
688 goto done;
689
690 } else {
691 backsql_PrintErrors( bi->sql_db_env,
692 dbh, sth, rc );
693 SQLFreeStmt( sth, SQL_DROP );
694 rs->sr_err = LDAP_OTHER;
695 rs->sr_text = at->bam_ad->ad_cname.bv_val;
696 goto done;
697 }
698 }
699 SQLFreeStmt( sth, SQL_DROP );
700 }
701 break;
702
703 case LDAP_MOD_INCREMENT:
704 Debug( LDAP_DEBUG_TRACE, " backsql_modify_internal(): "
705 "increment not supported yet\n", 0, 0, 0 );
706 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
707 rs->sr_err = LDAP_OTHER;
708 rs->sr_text = "SQL-backend error";
709 goto done;
710 }
711 break;
712 }
713 }
714
715 done:;
716 Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
717 rs->sr_err,
718 rs->sr_text ? ": " : "",
719 rs->sr_text ? rs->sr_text : "" );
720
721 /*
722 * FIXME: should fail in case one change fails?
723 */
724 return rs->sr_err;
725 }
726
727 static int
728 backsql_add_attr(
729 Operation *op,
730 SlapReply *rs,
731 SQLHDBC dbh,
732 backsql_oc_map_rec *oc,
733 Attribute *at,
734 backsql_key_t new_keyval )
735 {
736 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
737 backsql_at_map_rec *at_rec = NULL;
738 struct berval *at_val;
739 unsigned long i;
740 RETCODE rc;
741 SQLUSMALLINT currpos;
742 SQLHSTMT sth = SQL_NULL_HSTMT;
743
744 at_rec = backsql_ad2at( oc, at->a_desc );
745
746 if ( at_rec == NULL ) {
747 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
748 "attribute \"%s\" is not registered "
749 "in objectclass \"%s\"\n",
750 op->ora_e->e_name.bv_val,
751 at->a_desc->ad_cname.bv_val,
752 BACKSQL_OC_NAME( oc ) );
753
754 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
755 rs->sr_text = "operation not permitted "
756 "within namingContext";
757 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
758 }
759
760 return LDAP_SUCCESS;
761 }
762
763 if ( at_rec->bam_add_proc == NULL ) {
764 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
765 "add procedure is not defined "
766 "for attribute \"%s\" "
767 "of structuralObjectClass \"%s\"\n",
768 op->ora_e->e_name.bv_val,
769 at->a_desc->ad_cname.bv_val,
770 BACKSQL_OC_NAME( oc ) );
771
772 if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
773 rs->sr_text = "operation not permitted "
774 "within namingContext";
775 return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
776 }
777
778 return LDAP_SUCCESS;
779 }
780
781 for ( i = 0, at_val = &at->a_vals[ i ];
782 !BER_BVISNULL( at_val );
783 i++, at_val = &at->a_vals[ i ] )
784 {
785 /* procedure return code */
786 int prc = LDAP_SUCCESS;
787 /* first parameter #, parameter order */
788 SQLUSMALLINT pno, po;
789 char logbuf[ STRLENOF("val[], id=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long)];
790
791 /*
792 * Do not deal with the objectClass that is used
793 * to build the entry
794 */
795 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
796 if ( dn_match( at_val, &oc->bom_oc->soc_cname ) )
797 {
798 continue;
799 }
800 }
801
802 rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
803 if ( rc != SQL_SUCCESS ) {
804 rs->sr_text = "SQL-backend error";
805 return rs->sr_err = LDAP_OTHER;
806 }
807
808 if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
809 pno = 1;
810 rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
811 if ( rc != SQL_SUCCESS ) {
812 Debug( LDAP_DEBUG_TRACE,
813 " backsql_add_attr(): "
814 "error binding output parameter for %s[%lu]\n",
815 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
816 backsql_PrintErrors( bi->sql_db_env, dbh,
817 sth, rc );
818 SQLFreeStmt( sth, SQL_DROP );
819
820 rs->sr_text = "SQL-backend error";
821 return rs->sr_err = LDAP_OTHER;
822 }
823
824 } else {
825 pno = 0;
826 }
827
828 po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
829 currpos = pno + 1 + po;
830 rc = backsql_BindParamNumID( sth, currpos,
831 SQL_PARAM_INPUT, &new_keyval );
832 if ( rc != SQL_SUCCESS ) {
833 Debug( LDAP_DEBUG_TRACE,
834 " backsql_add_attr(): "
835 "error binding keyval parameter for %s[%lu]\n",
836 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
837 backsql_PrintErrors( bi->sql_db_env, dbh,
838 sth, rc );
839 SQLFreeStmt( sth, SQL_DROP );
840
841 rs->sr_text = "SQL-backend error";
842 return rs->sr_err = LDAP_OTHER;
843 }
844
845 currpos = pno + 2 - po;
846
847 /*
848 * check for syntax needed here
849 * maybe need binary bind?
850 */
851
852 rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
853 if ( rc != SQL_SUCCESS ) {
854 Debug( LDAP_DEBUG_TRACE,
855 " backsql_add_attr(): "
856 "error binding value parameter for %s[%lu]\n",
857 at_rec->bam_ad->ad_cname.bv_val, i, 0 );
858 backsql_PrintErrors( bi->sql_db_env, dbh,
859 sth, rc );
860 SQLFreeStmt( sth, SQL_DROP );
861
862 rs->sr_text = "SQL-backend error";
863 return rs->sr_err = LDAP_OTHER;
864 }
865
866 #ifdef LDAP_DEBUG
867 if ( LogTest( LDAP_DEBUG_TRACE ) ) {
868 snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=" BACKSQL_IDNUMFMT,
869 i, new_keyval );
870 Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(\"%s\"): "
871 "executing \"%s\" %s\n",
872 op->ora_e->e_name.bv_val,
873 at_rec->bam_add_proc, logbuf );
874 }
875 #endif
876 rc = SQLExecute( sth );
877 if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
878 rs->sr_err = LDAP_SUCCESS;
879
880 } else {
881 Debug( LDAP_DEBUG_TRACE,
882 " backsql_add_attr(\"%s\"): "
883 "add_proc execution failed (rc=%d, prc=%d)\n",
884 op->ora_e->e_name.bv_val, rc, prc );
885 if ( prc != LDAP_SUCCESS ) {
886 /* SQL procedure executed fine
887 * but returned an error */
888 rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
889 rs->sr_text = op->ora_e->e_name.bv_val;
890 SQLFreeStmt( sth, SQL_DROP );
891 return rs->sr_err;
892
893 } else {
894 backsql_PrintErrors( bi->sql_db_env, dbh,
895 sth, rc );
896 rs->sr_err = LDAP_OTHER;
897 rs->sr_text = op->ora_e->e_name.bv_val;
898 SQLFreeStmt( sth, SQL_DROP );
899 return rs->sr_err;
900 }
901 }
902 SQLFreeStmt( sth, SQL_DROP );
903 }
904
905 return LDAP_SUCCESS;
906 }
907
908 int
909 backsql_add( Operation *op, SlapReply *rs )
910 {
911 backsql_info *bi = (backsql_info*)op->o_bd->be_private;
912 SQLHDBC dbh = SQL_NULL_HDBC;
913 SQLHSTMT sth = SQL_NULL_HSTMT;
914 backsql_key_t new_keyval = 0;
915 RETCODE rc;
916 backsql_oc_map_rec *oc = NULL;
917 backsql_srch_info bsi = { 0 };
918 Entry p = { 0 }, *e = NULL;
919 Attribute *at,
920 *at_objectClass = NULL;
921 ObjectClass *soc = NULL;
922 struct berval scname = BER_BVNULL;
923 struct berval pdn;
924 struct berval realdn = BER_BVNULL;
925 int colnum;
926 slap_mask_t mask;
927
928 char textbuf[ SLAP_TEXT_BUFLEN ];
929 size_t textlen = sizeof( textbuf );
930
931 #ifdef BACKSQL_SYNCPROV
932 /*
933 * NOTE: fake successful result to force contextCSN to be bumped up
934 */
935 if ( op->o_sync ) {
936 char buf[ LDAP_PVT_CSNSTR_BUFSIZE ];
937 struct berval csn;
938
939 csn.bv_val = buf;
940 csn.bv_len = sizeof( buf );
941 slap_get_csn( op, &csn, 1 );
942
943 rs->sr_err = LDAP_SUCCESS;
944 send_ldap_result( op, rs );
945
946 slap_graduate_commit_csn( op );
947
948 return 0;
949 }
950 #endif /* BACKSQL_SYNCPROV */
951
952 Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
953 op->ora_e->e_name.bv_val, 0, 0 );
954
955 /* check schema */
956 if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
957 char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };
958
959 rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, NULL,
960 &rs->sr_text, textbuf, sizeof( textbuf ) );
961 if ( rs->sr_err != LDAP_SUCCESS ) {
962 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
963 "entry failed schema check -- aborting\n",
964 op->ora_e->e_name.bv_val, 0, 0 );
965 e = NULL;
966 goto done;
967 }
968 }
969
970 slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
971
972 if ( get_assert( op ) &&
973 ( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
974 {
975 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
976 "assertion control failed -- aborting\n",
977 op->ora_e->e_name.bv_val, 0, 0 );
978 e = NULL;
979 rs->sr_err = LDAP_ASSERTION_FAILED;
980 goto done;
981 }
982
983 /* search structuralObjectClass */
984 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
985 if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
986 break;
987 }
988 }
989
990 /* there must exist */
991 if ( at == NULL ) {
992 char buf[ SLAP_TEXT_BUFLEN ];
993 const char *text;
994
995 /* search structuralObjectClass */
996 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
997 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
998 break;
999 }
1000 }
1001
1002 if ( at == NULL ) {
1003 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1004 "no objectClass\n",
1005 op->ora_e->e_name.bv_val, 0, 0 );
1006 rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
1007 e = NULL;
1008 goto done;
1009 }
1010
1011 rs->sr_err = structural_class( at->a_vals, &soc, NULL,
1012 &text, buf, sizeof( buf ), op->o_tmpmemctx );
1013 if ( rs->sr_err != LDAP_SUCCESS ) {
1014 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1015 "%s (%d)\n",
1016 op->ora_e->e_name.bv_val, text, rs->sr_err );
1017 e = NULL;
1018 goto done;
1019 }
1020 scname = soc->soc_cname;
1021
1022 } else {
1023 scname = at->a_vals[0];
1024 }
1025
1026 /* I guess we should play with sub/supertypes to find a suitable oc */
1027 oc = backsql_name2oc( bi, &scname );
1028
1029 if ( oc == NULL ) {
1030 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1031 "cannot map structuralObjectClass \"%s\" -- aborting\n",
1032 op->ora_e->e_name.bv_val,
1033 scname.bv_val, 0 );
1034 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1035 rs->sr_text = "operation not permitted within namingContext";
1036 e = NULL;
1037 goto done;
1038 }
1039
1040 if ( oc->bom_create_proc == NULL ) {
1041 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1042 "create procedure is not defined "
1043 "for structuralObjectClass \"%s\" - aborting\n",
1044 op->ora_e->e_name.bv_val,
1045 scname.bv_val, 0 );
1046 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1047 rs->sr_text = "operation not permitted within namingContext";
1048 e = NULL;
1049 goto done;
1050
1051 } else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
1052 && oc->bom_create_keyval == NULL ) {
1053 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1054 "create procedure needs select procedure, "
1055 "but none is defined for structuralObjectClass \"%s\" "
1056 "- aborting\n",
1057 op->ora_e->e_name.bv_val,
1058 scname.bv_val, 0 );
1059 rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
1060 rs->sr_text = "operation not permitted within namingContext";
1061 e = NULL;
1062 goto done;
1063 }
1064
1065 /* check write access */
1066 if ( !access_allowed_mask( op, op->ora_e,
1067 slap_schema.si_ad_entry,
1068 NULL, ACL_WADD, NULL, &mask ) )
1069 {
1070 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1071 e = op->ora_e;
1072 goto done;
1073 }
1074
1075 rs->sr_err = backsql_get_db_conn( op, &dbh );
1076 if ( rs->sr_err != LDAP_SUCCESS ) {
1077 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1078 "could not get connection handle - exiting\n",
1079 op->ora_e->e_name.bv_val, 0, 0 );
1080 rs->sr_text = ( rs->sr_err == LDAP_OTHER )
1081 ? "SQL-backend error" : NULL;
1082 e = NULL;
1083 goto done;
1084 }
1085
1086 /*
1087 * Check if entry exists
1088 *
1089 * NOTE: backsql_api_dn2odbc() is called explicitly because
1090 * we need the mucked DN to pass it to the create procedure.
1091 */
1092 realdn = op->ora_e->e_name;
1093 if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
1094 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1095 "backsql_api_dn2odbc(\"%s\") failed\n",
1096 op->ora_e->e_name.bv_val, realdn.bv_val, 0 );
1097 rs->sr_err = LDAP_OTHER;
1098 rs->sr_text = "SQL-backend error";
1099 e = NULL;
1100 goto done;
1101 }
1102
1103 rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1104 if ( rs->sr_err == LDAP_SUCCESS ) {
1105 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1106 "entry exists\n",
1107 op->ora_e->e_name.bv_val, 0, 0 );
1108 rs->sr_err = LDAP_ALREADY_EXISTS;
1109 e = op->ora_e;
1110 goto done;
1111 }
1112
1113 /*
1114 * Get the parent dn and see if the corresponding entry exists.
1115 */
1116 if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
1117 pdn = slap_empty_bv;
1118
1119 } else {
1120 dnParent( &op->ora_e->e_nname, &pdn );
1121
1122 /*
1123 * Get the parent
1124 */
1125 bsi.bsi_e = &p;
1126 rs->sr_err = backsql_init_search( &bsi, &pdn,
1127 LDAP_SCOPE_BASE,
1128 (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
1129 ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
1130 if ( rs->sr_err != LDAP_SUCCESS ) {
1131 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1132 "could not retrieve addDN parent "
1133 "\"%s\" ID - %s matched=\"%s\"\n",
1134 pdn.bv_val,
1135 rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
1136 rs->sr_matched ? rs->sr_matched : "(null)" );
1137 e = &p;
1138 goto done;
1139 }
1140
1141 /* check "children" pseudo-attribute access to parent */
1142 if ( !access_allowed( op, &p, slap_schema.si_ad_children,
1143 NULL, ACL_WADD, NULL ) )
1144 {
1145 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
1146 e = &p;
1147 goto done;
1148 }
1149 }
1150
1151 /*
1152 * create_proc is executed; if expect_return is set, then
1153 * an output parameter is bound, which should contain
1154 * the id of the added row; otherwise the procedure
1155 * is expected to return the id as the first column of a select
1156 */
1157 rc = backsql_Prepare( dbh, &sth, oc->bom_create_proc, 0 );
1158 if ( rc != SQL_SUCCESS ) {
1159 rs->sr_err = LDAP_OTHER;
1160 rs->sr_text = "SQL-backend error";
1161 e = NULL;
1162 goto done;
1163 }
1164
1165 colnum = 1;
1166 if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1167 rc = backsql_BindParamNumID( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
1168 if ( rc != SQL_SUCCESS ) {
1169 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1170 "error binding keyval parameter "
1171 "for objectClass %s\n",
1172 op->ora_e->e_name.bv_val,
1173 oc->bom_oc->soc_cname.bv_val, 0 );
1174 backsql_PrintErrors( bi->sql_db_env, dbh,
1175 sth, rc );
1176 SQLFreeStmt( sth, SQL_DROP );
1177
1178 rs->sr_text = "SQL-backend error";
1179 rs->sr_err = LDAP_OTHER;
1180 e = NULL;
1181 goto done;
1182 }
1183 colnum++;
1184 }
1185
1186 if ( oc->bom_create_hint ) {
1187 at = attr_find( op->ora_e->e_attrs, oc->bom_create_hint );
1188 if ( at && at->a_vals ) {
1189 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1190 at->a_vals[0].bv_val,
1191 at->a_vals[0].bv_len );
1192 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1193 "create_proc hint: param = '%s'\n",
1194 at->a_vals[0].bv_val, 0, 0 );
1195
1196 } else {
1197 backsql_BindParamStr( sth, colnum, SQL_PARAM_INPUT,
1198 "", 0 );
1199 Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
1200 "create_proc hint (%s) not avalable\n",
1201 oc->bom_create_hint->ad_cname.bv_val,
1202 0, 0 );
1203 }
1204 colnum++;
1205 }
1206
1207 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): executing \"%s\"\n",
1208 op->ora_e->e_name.bv_val, oc->bom_create_proc, 0 );
1209 rc = SQLExecute( sth );
1210 if ( rc != SQL_SUCCESS ) {
1211 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1212 "create_proc execution failed\n",
1213 op->ora_e->e_name.bv_val, 0, 0 );
1214 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1215 SQLFreeStmt( sth, SQL_DROP );
1216 rs->sr_err = LDAP_OTHER;
1217 rs->sr_text = "SQL-backend error";
1218 e = NULL;
1219 goto done;
1220 }
1221
1222 /* FIXME: after SQLExecute(), the row is already inserted
1223 * (at least with PostgreSQL and unixODBC); needs investigation */
1224
1225 if ( !BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1226 SWORD ncols;
1227 SQLLEN value_len;
1228
1229 if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) {
1230 SQLFreeStmt( sth, SQL_DROP );
1231
1232 rc = backsql_Prepare( dbh, &sth, oc->bom_create_keyval, 0 );
1233 if ( rc != SQL_SUCCESS ) {
1234 rs->sr_err = LDAP_OTHER;
1235 rs->sr_text = "SQL-backend error";
1236 e = NULL;
1237 goto done;
1238 }
1239
1240 rc = SQLExecute( sth );
1241 if ( rc != SQL_SUCCESS ) {
1242 rs->sr_err = LDAP_OTHER;
1243 rs->sr_text = "SQL-backend error";
1244 e = NULL;
1245 goto done;
1246 }
1247 }
1248
1249 /*
1250 * the query to know the id of the inserted entry
1251 * must be embedded in the create procedure
1252 */
1253 rc = SQLNumResultCols( sth, &ncols );
1254 if ( rc != SQL_SUCCESS ) {
1255 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1256 "create_proc result evaluation failed\n",
1257 op->ora_e->e_name.bv_val, 0, 0 );
1258 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1259 SQLFreeStmt( sth, SQL_DROP );
1260 rs->sr_err = LDAP_OTHER;
1261 rs->sr_text = "SQL-backend error";
1262 e = NULL;
1263 goto done;
1264
1265 } else if ( ncols != 1 ) {
1266 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1267 "create_proc result is bogus (ncols=%d)\n",
1268 op->ora_e->e_name.bv_val, ncols, 0 );
1269 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1270 SQLFreeStmt( sth, SQL_DROP );
1271 rs->sr_err = LDAP_OTHER;
1272 rs->sr_text = "SQL-backend error";
1273 e = NULL;
1274 goto done;
1275 }
1276
1277 #if 0
1278 {
1279 SQLCHAR colname[ 64 ];
1280 SQLSMALLINT name_len, col_type, col_scale, col_null;
1281 UDWORD col_prec;
1282
1283 /*
1284 * FIXME: check whether col_type is compatible,
1285 * if it can be null and so on ...
1286 */
1287 rc = SQLDescribeCol( sth, (SQLUSMALLINT)1,
1288 &colname[ 0 ],
1289 (SQLUINTEGER)( sizeof( colname ) - 1 ),
1290 &name_len, &col_type,
1291 &col_prec, &col_scale, &col_null );
1292 }
1293 #endif
1294
1295 rc = SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_ULONG,
1296 (SQLPOINTER)&new_keyval,
1297 (SQLINTEGER)sizeof( new_keyval ),
1298 &value_len );
1299
1300 rc = SQLFetch( sth );
1301
1302 if ( value_len <= 0 ) {
1303 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1304 "create_proc result is empty?\n",
1305 op->ora_e->e_name.bv_val, 0, 0 );
1306 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc);
1307 SQLFreeStmt( sth, SQL_DROP );
1308 rs->sr_err = LDAP_OTHER;
1309 rs->sr_text = "SQL-backend error";
1310 e = NULL;
1311 goto done;
1312 }
1313 }
1314
1315 SQLFreeStmt( sth, SQL_DROP );
1316
1317 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1318 "create_proc returned keyval=" BACKSQL_IDNUMFMT "\n",
1319 op->ora_e->e_name.bv_val, new_keyval, 0 );
1320
1321 rc = backsql_Prepare( dbh, &sth, bi->sql_insentry_stmt, 0 );
1322 if ( rc != SQL_SUCCESS ) {
1323 rs->sr_err = LDAP_OTHER;
1324 rs->sr_text = "SQL-backend error";
1325 e = NULL;
1326 goto done;
1327 }
1328
1329 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realdn );
1330 if ( rc != SQL_SUCCESS ) {
1331 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1332 "error binding DN parameter for objectClass %s\n",
1333 op->ora_e->e_name.bv_val,
1334 oc->bom_oc->soc_cname.bv_val, 0 );
1335 backsql_PrintErrors( bi->sql_db_env, dbh,
1336 sth, rc );
1337 SQLFreeStmt( sth, SQL_DROP );
1338
1339 rs->sr_text = "SQL-backend error";
1340 rs->sr_err = LDAP_OTHER;
1341 e = NULL;
1342 goto done;
1343 }
1344
1345 rc = backsql_BindParamNumID( sth, 2, SQL_PARAM_INPUT, &oc->bom_id );
1346 if ( rc != SQL_SUCCESS ) {
1347 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1348 "error binding objectClass ID parameter "
1349 "for objectClass %s\n",
1350 op->ora_e->e_name.bv_val,
1351 oc->bom_oc->soc_cname.bv_val, 0 );
1352 backsql_PrintErrors( bi->sql_db_env, dbh,
1353 sth, rc );
1354 SQLFreeStmt( sth, SQL_DROP );
1355
1356 rs->sr_text = "SQL-backend error";
1357 rs->sr_err = LDAP_OTHER;
1358 e = NULL;
1359 goto done;
1360 }
1361
1362 rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &bsi.bsi_base_id.eid_id );
1363 if ( rc != SQL_SUCCESS ) {
1364 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1365 "error binding parent ID parameter "
1366 "for objectClass %s\n",
1367 op->ora_e->e_name.bv_val,
1368 oc->bom_oc->soc_cname.bv_val, 0 );
1369 backsql_PrintErrors( bi->sql_db_env, dbh,
1370 sth, rc );
1371 SQLFreeStmt( sth, SQL_DROP );
1372
1373 rs->sr_text = "SQL-backend error";
1374 rs->sr_err = LDAP_OTHER;
1375 e = NULL;
1376 goto done;
1377 }
1378
1379 rc = backsql_BindParamNumID( sth, 4, SQL_PARAM_INPUT, &new_keyval );
1380 if ( rc != SQL_SUCCESS ) {
1381 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1382 "error binding entry ID parameter "
1383 "for objectClass %s\n",
1384 op->ora_e->e_name.bv_val,
1385 oc->bom_oc->soc_cname.bv_val, 0 );
1386 backsql_PrintErrors( bi->sql_db_env, dbh,
1387 sth, rc );
1388 SQLFreeStmt( sth, SQL_DROP );
1389
1390 rs->sr_text = "SQL-backend error";
1391 rs->sr_err = LDAP_OTHER;
1392 e = NULL;
1393 goto done;
1394 }
1395
1396 if ( LogTest( LDAP_DEBUG_TRACE ) ) {
1397 char buf[ SLAP_TEXT_BUFLEN ];
1398
1399 snprintf( buf, sizeof(buf),
1400 "executing \"%s\" for dn=\"%s\" oc_map_id=" BACKSQL_IDNUMFMT " p_id=" BACKSQL_IDFMT " keyval=" BACKSQL_IDNUMFMT,
1401 bi->sql_insentry_stmt, op->ora_e->e_name.bv_val,
1402 oc->bom_id, BACKSQL_IDARG(bsi.bsi_base_id.eid_id),
1403 new_keyval );
1404 Debug( LDAP_DEBUG_TRACE, " backsql_add(): %s\n", buf, 0, 0 );
1405 }
1406
1407 rc = SQLExecute( sth );
1408 if ( rc != SQL_SUCCESS ) {
1409 Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): "
1410 "could not insert ldap_entries record\n",
1411 op->ora_e->e_name.bv_val, 0, 0 );
1412 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
1413
1414 /*
1415 * execute delete_proc to delete data added !!!
1416 */
1417 SQLFreeStmt( sth, SQL_DROP );
1418 rs->sr_err = LDAP_OTHER;
1419 rs->sr_text = "SQL-backend error";
1420 e = NULL;
1421 goto done;
1422 }
1423
1424 SQLFreeStmt( sth, SQL_DROP );
1425
1426 for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
1427 Debug( LDAP_DEBUG_TRACE, " backsql_add(): "
1428 "adding attribute \"%s\"\n",
1429 at->a_desc->ad_cname.bv_val, 0, 0 );
1430
1431 /*
1432 * Skip:
1433 * - the first occurrence of objectClass, which is used
1434 * to determine how to build the SQL entry (FIXME ?!?)
1435 * - operational attributes
1436 * - empty attributes (FIXME ?!?)
1437 */
1438 if ( backsql_attr_skip( at->a_desc, at->a_vals ) ) {
1439 continue;
1440 }
1441
1442 if ( at->a_desc == slap_schema.si_ad_objectClass ) {
1443 at_objectClass = at;
1444 continue;
1445 }
1446
1447 rs->sr_err = backsql_add_attr( op, rs, dbh, oc, at, new_keyval );
1448 if ( rs->sr_err != LDAP_SUCCESS ) {
1449 e = op->ora_e;
1450 goto done;
1451 }
1452 }
1453
1454 if ( at_objectClass ) {
1455 rs->sr_err = backsql_add_attr( op, rs, dbh, oc,
1456 at_objectClass, new_keyval );
1457 if ( rs->sr_err != LDAP_SUCCESS ) {
1458 e = op->ora_e;
1459 goto done;
1460 }
1461 }
1462
1463 done:;
1464 /*
1465 * Commit only if all operations succeed
1466 */
1467 if ( sth != SQL_NULL_HSTMT ) {
1468 SQLUSMALLINT CompletionType = SQL_ROLLBACK;
1469
1470 if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) {
1471 assert( e == NULL );
1472 CompletionType = SQL_COMMIT;
1473 }
1474
1475 SQLTransact( SQL_NULL_HENV, dbh, CompletionType );
1476 }
1477
1478 /*
1479 * FIXME: NOOP does not work for add -- it works for all
1480 * the other operations, and I don't get the reason :(
1481 *
1482 * hint: there might be some autocommit in Postgres
1483 * so that when the unique id of the key table is
1484 * automatically increased, there's no rollback.
1485 * We might implement a "rollback" procedure consisting
1486 * in deleting that row.
1487 */
1488
1489 if ( e != NULL ) {
1490 int disclose = 1;
1491
1492 if ( e == op->ora_e && !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
1493 /* mask already collected */
1494 disclose = 0;
1495
1496 } else if ( e == &p && !access_allowed( op, &p,
1497 slap_schema.si_ad_entry, NULL,
1498 ACL_DISCLOSE, NULL ) )
1499 {
1500 disclose = 0;
1501 }
1502
1503 if ( disclose == 0 ) {
1504 rs->sr_err = LDAP_NO_SUCH_OBJECT;
1505 rs->sr_text = NULL;
1506 rs->sr_matched = NULL;
1507 if ( rs->sr_ref ) {
1508 ber_bvarray_free( rs->sr_ref );
1509 rs->sr_ref = NULL;
1510 }
1511 }
1512 }
1513
1514 if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) {
1515 rs->sr_err = LDAP_X_NO_OPERATION;
1516 }
1517
1518 send_ldap_result( op, rs );
1519 slap_graduate_commit_csn( op );
1520
1521 if ( !BER_BVISNULL( &realdn )
1522 && realdn.bv_val != op->ora_e->e_name.bv_val )
1523 {
1524 ch_free( realdn.bv_val );
1525 }
1526
1527 if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) {
1528 (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx );
1529 }
1530
1531 if ( !BER_BVISNULL( &p.e_nname ) ) {
1532 backsql_entry_clean( op, &p );
1533 }
1534
1535 Debug( LDAP_DEBUG_TRACE, "<==backsql_add(\"%s\"): %d \"%s\"\n",
1536 op->ora_e->e_name.bv_val,
1537 rs->sr_err,
1538 rs->sr_text ? rs->sr_text : "" );
1539
1540 rs->sr_text = NULL;
1541 rs->sr_matched = NULL;
1542 if ( rs->sr_ref ) {
1543 ber_bvarray_free( rs->sr_ref );
1544 rs->sr_ref = NULL;
1545 }
1546
1547 return rs->sr_err;
1548 }
1549
1550