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