add.c 40.1 KB
Newer Older
1
2
3
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1999-2010 The OpenLDAP Foundation.
5
 * Portions Copyright 1999 Dmitry Kovalev.
6
 * Portions Copyright 2002 Pierangelo Masarati.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7
 * Portions Copyright 2004 Mark Adamson.
8
9
10
11
12
13
14
15
16
17
18
19
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by Dmitry Kovalev for inclusion
20
21
22
 * by OpenLDAP Software.  Additional significant contributors include
 * Pierangelo Masarati and Mark Adamson.

23
24
25
26
27
28
29
30
31
32
33
 */

#include "portable.h"

#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"

#include "slap.h"
#include "proto-sql.h"

34
35
36
37
#ifdef BACKSQL_SYNCPROV
#include <lutil.h>
#endif /* BACKSQL_SYNCPROV */

38
39
/*
 * Skip:
Pierangelo Masarati's avatar
Pierangelo Masarati committed
40
41
42
 * - null values (e.g. delete modification)
 * - single occurrence of objectClass, because it is already used
 *   to determine how to build the SQL entry
43
 * - operational attributes
Pierangelo Masarati's avatar
Pierangelo Masarati committed
44
 * - empty attributes
45
 */
46
47
#define backsql_opattr_skip(ad) \
	(is_at_operational( (ad)->ad_type ) && (ad) != slap_schema.si_ad_ref )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
48
#define	backsql_attr_skip(ad, vals) \
49
50
	( \
		( (ad) == slap_schema.si_ad_objectClass \
Pierangelo Masarati's avatar
Pierangelo Masarati committed
51
				&& (vals) && BER_BVISNULL( &((vals)[ 1 ]) ) ) \
52
		|| backsql_opattr_skip( (ad) ) \
53
		|| ( (vals) && BER_BVISNULL( &((vals)[ 0 ]) ) ) \
54
55
	)

56
57
58
59
60
61
62
63
64
65
int
backsql_modify_delete_all_values(
	Operation 		*op,
	SlapReply		*rs,
	SQLHDBC			dbh, 
	backsql_entryID		*e_id,
	backsql_at_map_rec	*at )
{
	backsql_info	*bi = (backsql_info *)op->o_bd->be_private;
	RETCODE		rc;
66
	SQLHSTMT	asth = SQL_NULL_HSTMT;
67
68
	BACKSQL_ROW_NTS	row;

69
	assert( at != NULL );
70
71
72
73
74
75
76
77
78
79
80
81
82
83
	if ( at->bam_delete_proc == NULL ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_modify_delete_all_values(): "
			"missing attribute value delete procedure "
			"for attr \"%s\"\n",
			at->bam_ad->ad_cname.bv_val, 0, 0 );
		if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
			rs->sr_text = "SQL-backend error";
			return rs->sr_err = LDAP_OTHER;
		}

		return LDAP_SUCCESS;
	}

84
85
86
87
	rc = backsql_Prepare( dbh, &asth, at->bam_query, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_modify_delete_all_values(): "
88
89
90
			"error preparing attribute value select query "
			"\"%s\"\n",
			at->bam_query, 0, 0 );
91
		backsql_PrintErrors( bi->sql_db_env, dbh, 
92
93
				asth, rc );

94
95
		rs->sr_text = "SQL-backend error";
		return rs->sr_err = LDAP_OTHER;
96
97
	}

98
	rc = backsql_BindParamID( asth, 1, SQL_PARAM_INPUT, &e_id->eid_keyval );
99
100
101
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_modify_delete_all_values(): "
102
103
			"error binding key value parameter "
			"to attribute value select query\n",
104
			0, 0, 0 );
105
		backsql_PrintErrors( bi->sql_db_env, dbh, 
106
107
108
				asth, rc );
		SQLFreeStmt( asth, SQL_DROP );

109
110
		rs->sr_text = "SQL-backend error";
		return rs->sr_err = LDAP_OTHER;
111
112
113
114
115
116
	}
			
	rc = SQLExecute( asth );
	if ( !BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE,
			"   backsql_modify_delete_all_values(): "
117
			"error executing attribute value select query\n",
118
			0, 0, 0 );
119
		backsql_PrintErrors( bi->sql_db_env, dbh, 
120
121
122
				asth, rc );
		SQLFreeStmt( asth, SQL_DROP );

123
124
		rs->sr_text = "SQL-backend error";
		return rs->sr_err = LDAP_OTHER;
125
126
	}

127
	backsql_BindRowAsStrings_x( asth, &row, op->o_tmpmemctx );
128
129
130
131
	for ( rc = SQLFetch( asth );
			BACKSQL_SUCCESS( rc );
			rc = SQLFetch( asth ) )
	{
132
		int		i;
133
		/* first parameter no, parameter order */
134
		SQLUSMALLINT	pno = 0,
135
				po = 0;
136
		/* procedure return code */
137
		int		prc = LDAP_SUCCESS;
138
139
		
		for ( i = 0; i < row.ncols; i++ ) {
140
			SQLHSTMT	sth = SQL_NULL_HSTMT;
141
			ber_len_t	col_len;
142
143
144
145
146
			
			rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
			if ( rc != SQL_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_delete_all_values(): "
147
148
149
					"error preparing attribute value "
					"delete procedure "
					"\"%s\"\n",
150
					at->bam_delete_proc, 0, 0 );
151
				backsql_PrintErrors( bi->sql_db_env, dbh, 
152
153
						sth, rc );

154
				rs->sr_text = "SQL-backend error";
155
156
				rs->sr_err = LDAP_OTHER;
				goto done;
157
158
159
160
			}

	   		if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
				pno = 1;
161
162
163
164
165
166
167
				rc = backsql_BindParamInt( sth, 1,
						SQL_PARAM_OUTPUT, &prc );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_delete_all_values(): "
						"error binding output parameter for %s[%d]\n",
						at->bam_ad->ad_cname.bv_val, i, 0 );
168
					backsql_PrintErrors( bi->sql_db_env, dbh, 
169
170
171
						sth, rc );
					SQLFreeStmt( sth, SQL_DROP );

172
					rs->sr_text = "SQL-backend error";
173
174
					rs->sr_err = LDAP_OTHER;
					goto done;
175
				}
176
177
			}
			po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
178
179
180
181
182
183
184
			rc = backsql_BindParamID( sth, pno + 1 + po,
				SQL_PARAM_INPUT, &e_id->eid_keyval );
			if ( rc != SQL_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_delete_all_values(): "
					"error binding keyval parameter for %s[%d]\n",
					at->bam_ad->ad_cname.bv_val, i, 0 );
185
				backsql_PrintErrors( bi->sql_db_env, dbh, 
186
187
188
					sth, rc );
				SQLFreeStmt( sth, SQL_DROP );

189
				rs->sr_text = "SQL-backend error";
190
191
				rs->sr_err = LDAP_OTHER;
				goto done;
192
			}
193

194
			Debug( LDAP_DEBUG_TRACE,
195
				"   backsql_modify_delete_all_values() "
196
197
198
				"arg(%d)=" BACKSQL_IDFMT "\n",
				pno + 1 + po,
				BACKSQL_IDARG(e_id->eid_keyval), 0 );
199
200
201
202
203

			/*
			 * check for syntax needed here 
			 * maybe need binary bind?
			 */
204
			col_len = strlen( row.cols[ i ] );
205
206
207
208
209
210
211
			rc = backsql_BindParamStr( sth, pno + 2 - po,
				SQL_PARAM_INPUT, row.cols[ i ], col_len );
			if ( rc != SQL_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_delete_all_values(): "
					"error binding value parameter for %s[%d]\n",
					at->bam_ad->ad_cname.bv_val, i, 0 );
212
				backsql_PrintErrors( bi->sql_db_env, dbh, 
213
214
215
					sth, rc );
				SQLFreeStmt( sth, SQL_DROP );

216
				rs->sr_text = "SQL-backend error";
217
218
				rs->sr_err = LDAP_OTHER;
				goto done;
219
			}
220
221
222
	 
			Debug( LDAP_DEBUG_TRACE, 
				"   backsql_modify_delete_all_values(): "
223
				"arg(%d)=%s; executing \"%s\"\n",
224
225
226
				pno + 2 - po, row.cols[ i ],
				at->bam_delete_proc );
			rc = SQLExecute( sth );
227
228
229
230
			if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
				rs->sr_err = LDAP_SUCCESS;

			} else {
231
232
233
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_delete_all_values(): "
					"delete_proc "
234
235
236
237
238
239
240
241
242
243
					"execution failed (rc=%d, prc=%d)\n",
					rc, prc, 0 );
				if ( prc != LDAP_SUCCESS ) {
					/* SQL procedure executed fine 
					 * but returned an error */
					rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );

				} else {
					backsql_PrintErrors( bi->sql_db_env, dbh,
							sth, rc );
244
					rs->sr_err = LDAP_OTHER;
245
				}
246
				rs->sr_text = op->o_req_dn.bv_val;
247
				SQLFreeStmt( sth, SQL_DROP );
248
				goto done;
249
250
251
252
			}
			SQLFreeStmt( sth, SQL_DROP );
		}
	}
253
254
255
256
257

	rs->sr_err = LDAP_SUCCESS;

done:;
	backsql_FreeRow_x( &row, op->o_tmpmemctx );
258
259
	SQLFreeStmt( asth, SQL_DROP );

260
	return rs->sr_err;
261
262
}

263
264
265
266
267
268
269
270
271
int
backsql_modify_internal(
	Operation 		*op,
	SlapReply		*rs,
	SQLHDBC			dbh, 
	backsql_oc_map_rec	*oc,
	backsql_entryID		*e_id,
	Modifications		*modlist )
{
272
	backsql_info	*bi = (backsql_info *)op->o_bd->be_private;
273
274
275
276
277
278
279
280
	RETCODE		rc;
	Modifications	*ml;

	Debug( LDAP_DEBUG_TRACE, "==>backsql_modify_internal(): "
		"traversing modifications list\n", 0, 0, 0 );

	for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
		AttributeDescription	*ad;
281
282
283
284
285
		int			sm_op;
		static char		*sm_ops[] = { "add", "delete", "replace", "increment", NULL };

		BerVarray		sm_values;
#if 0
Pierangelo Masarati's avatar
Pierangelo Masarati committed
286
		/* NOTE: some day we'll have to pass 
287
		 * the normalized values as well */
288
		BerVarray		sm_nvalues;
289
#endif
290
291
292
		backsql_at_map_rec	*at = NULL;
		struct berval		*at_val;
		int			i;
293
		
294
295
296
297
298
299
		ad = ml->sml_mod.sm_desc;
		sm_op = ( ml->sml_mod.sm_op & LDAP_MOD_OP );
		sm_values = ml->sml_mod.sm_values;
#if 0
		sm_nvalues = ml->sml_mod.sm_nvalues;
#endif
300
301

		Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
302
			"modifying attribute \"%s\" (%s) according to "
303
			"mappings for objectClass \"%s\"\n",
304
			ad->ad_cname.bv_val, sm_ops[ sm_op ], BACKSQL_OC_NAME( oc ) );
305

306
		if ( backsql_attr_skip( ad, sm_values ) ) {
307
308
309
310
311
312
313
314
			continue;
		}

  		at = backsql_ad2at( oc, ad );
		if ( at == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
				"attribute \"%s\" is not registered "
				"in objectClass \"%s\"\n",
315
				ad->ad_cname.bv_val, BACKSQL_OC_NAME( oc ), 0 );
316
317
318
319
320
321
322
323
324
325
326

			if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
				rs->sr_text = "operation not permitted "
					"within namingContext";
				goto done;
			}

			continue;
		}
  
327
		switch ( sm_op ) {
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
		case LDAP_MOD_REPLACE: {
			Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
				"replacing values for attribute \"%s\"\n",
				at->bam_ad->ad_cname.bv_val, 0, 0 );

			if ( at->bam_add_proc == NULL ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"add procedure is not defined "
					"for attribute \"%s\" "
					"- unable to perform replacements\n",
					at->bam_ad->ad_cname.bv_val, 0, 0 );

				if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
					rs->sr_text = "operation not permitted "
						"within namingContext";
					goto done;
				}

				break;
			}

			if ( at->bam_delete_proc == NULL ) {
				if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"delete procedure is not defined "
						"for attribute \"%s\"\n",
						at->bam_ad->ad_cname.bv_val, 0, 0 );

					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
					rs->sr_text = "operation not permitted "
						"within namingContext";
					goto done;
				}

				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"delete procedure is not defined "
					"for attribute \"%s\" "
					"- adding only\n",
					at->bam_ad->ad_cname.bv_val, 0, 0 );

				goto add_only;
			}
374

375
del_all:
376
377
378
			rs->sr_err = backsql_modify_delete_all_values( op, rs, dbh, e_id, at );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				goto done;
379
			}
380
381

			/* LDAP_MOD_DELETE gets here if all values must be deleted */
382
			if ( sm_op == LDAP_MOD_DELETE ) {
383
384
				break;
			}
385
386
387
388
389
390
	       	}

		/*
		 * PASSTHROUGH - to add new attributes -- do NOT add break
		 */
		case LDAP_MOD_ADD:
391
		/* case SLAP_MOD_SOFTADD: */
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
add_only:;
			if ( at->bam_add_proc == NULL ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"add procedure is not defined "
					"for attribute \"%s\"\n",
					at->bam_ad->ad_cname.bv_val, 0, 0 );

				if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
					rs->sr_text = "operation not permitted "
						"within namingContext";
					goto done;
				}

				break;
			}
			
			Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
				"adding new values for attribute \"%s\"\n",
				at->bam_ad->ad_cname.bv_val, 0, 0 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
413
414
415
416

			/* can't add a NULL val array */
			assert( sm_values != NULL );
			
417
418
419
420
			for ( i = 0, at_val = sm_values;
					!BER_BVISNULL( at_val ); 
					i++, at_val++ )
			{
421
422
423
424
425
426
427
				SQLHSTMT	sth = SQL_NULL_HSTMT;
				/* first parameter position, parameter order */
				SQLUSMALLINT	pno = 0,
						po;
				/* procedure return code */
				int		prc = LDAP_SUCCESS;

428
429
430
431
432
433
				rc = backsql_Prepare( dbh, &sth, at->bam_add_proc, 0 );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error preparing add query\n", 
						0, 0, 0 );
434
					backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
435
436
437
438
439
440

					rs->sr_err = LDAP_OTHER;
					rs->sr_text = "SQL-backend error";
					goto done;
				}

441
442
				if ( BACKSQL_IS_ADD( at->bam_expect_return ) ) {
					pno = 1;
443
444
445
446
447
448
449
	      				rc = backsql_BindParamInt( sth, 1,
						SQL_PARAM_OUTPUT, &prc );
					if ( rc != SQL_SUCCESS ) {
						Debug( LDAP_DEBUG_TRACE,
							"   backsql_modify_internal(): "
							"error binding output parameter for %s[%d]\n",
							at->bam_ad->ad_cname.bv_val, i, 0 );
450
						backsql_PrintErrors( bi->sql_db_env, dbh, 
451
452
453
454
455
456
457
							sth, rc );
						SQLFreeStmt( sth, SQL_DROP );

						rs->sr_text = "SQL-backend error";
						rs->sr_err = LDAP_OTHER;
						goto done;
					}
458
459
				}
				po = ( BACKSQL_IS_ADD( at->bam_param_order ) ) > 0;
460
461
462
463
464
465
466
				rc = backsql_BindParamID( sth, pno + 1 + po,
					SQL_PARAM_INPUT, &e_id->eid_keyval );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error binding keyval parameter for %s[%d]\n",
						at->bam_ad->ad_cname.bv_val, i, 0 );
467
					backsql_PrintErrors( bi->sql_db_env, dbh, 
468
469
470
471
472
473
474
						sth, rc );
					SQLFreeStmt( sth, SQL_DROP );

					rs->sr_text = "SQL-backend error";
					rs->sr_err = LDAP_OTHER;
					goto done;
				}
475

476
477
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
478
479
480
					"arg(%d)=" BACKSQL_IDFMT "\n", 
					pno + 1 + po,
					BACKSQL_IDARG(e_id->eid_keyval), 0 );
481
482
483
484
485

				/*
				 * check for syntax needed here
				 * maybe need binary bind?
				 */
486
487
488
489
490
491
492
				rc = backsql_BindParamBerVal( sth, pno + 2 - po,
					SQL_PARAM_INPUT, at_val );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error binding value parameter for %s[%d]\n",
						at->bam_ad->ad_cname.bv_val, i, 0 );
493
					backsql_PrintErrors( bi->sql_db_env, dbh, 
494
495
496
497
498
499
500
						sth, rc );
					SQLFreeStmt( sth, SQL_DROP );

					rs->sr_text = "SQL-backend error";
					rs->sr_err = LDAP_OTHER;
					goto done;
				}
501
502
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
503
					"arg(%d)=\"%s\"; executing \"%s\"\n", 
504
505
506
					pno + 2 - po, at_val->bv_val,
					at->bam_add_proc );

507
				rc = SQLExecute( sth );
508
509
510
511
				if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
					rs->sr_err = LDAP_SUCCESS;

				} else {
512
513
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
514
515
516
517
518
519
520
						"add_proc execution failed "
						"(rc=%d, prc=%d)\n",
						rc, prc, 0 );
					if ( prc != LDAP_SUCCESS ) {
						/* SQL procedure executed fine 
						 * but returned an error */
						SQLFreeStmt( sth, SQL_DROP );
521

522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
						rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
						rs->sr_text = at->bam_ad->ad_cname.bv_val;
						return rs->sr_err;
					
					} else {
						backsql_PrintErrors( bi->sql_db_env, dbh,
								sth, rc );
						if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) 
						{
							SQLFreeStmt( sth, SQL_DROP );

							rs->sr_err = LDAP_OTHER;
							rs->sr_text = "SQL-backend error";
							goto done;
						}
					}
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
				}
				SQLFreeStmt( sth, SQL_DROP );
			}
			break;
			
	      	case LDAP_MOD_DELETE:
			if ( at->bam_delete_proc == NULL ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"delete procedure is not defined "
					"for attribute \"%s\"\n",
					at->bam_ad->ad_cname.bv_val, 0, 0 );

				if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
					rs->sr_text = "operation not permitted "
						"within namingContext";
					goto done;
				}

				break;
			}

561
			if ( sm_values == NULL ) {
562
563
564
565
566
567
568
569
570
571
572
573
574
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"no values given to delete "
					"for attribute \"%s\" "
					"-- deleting all values\n",
					at->bam_ad->ad_cname.bv_val, 0, 0 );
				goto del_all;
			}

			Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
				"deleting values for attribute \"%s\"\n",
				at->bam_ad->ad_cname.bv_val, 0, 0 );

575
576
577
578
			for ( i = 0, at_val = sm_values;
					!BER_BVISNULL( at_val );
					i++, at_val++ )
			{
579
580
581
582
583
584
585
				SQLHSTMT	sth = SQL_NULL_HSTMT;
				/* first parameter position, parameter order */
				SQLUSMALLINT	pno = 0,
						po;
				/* procedure return code */
				int		prc = LDAP_SUCCESS;

586
587
588
589
590
591
				rc = backsql_Prepare( dbh, &sth, at->bam_delete_proc, 0 );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error preparing delete query\n", 
						0, 0, 0 );
592
					backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
593
594
595
596
597
598

					rs->sr_err = LDAP_OTHER;
					rs->sr_text = "SQL-backend error";
					goto done;
				}

599
600
				if ( BACKSQL_IS_DEL( at->bam_expect_return ) ) {
					pno = 1;
601
602
603
604
605
606
607
					rc = backsql_BindParamInt( sth, 1,
						SQL_PARAM_OUTPUT, &prc );
					if ( rc != SQL_SUCCESS ) {
						Debug( LDAP_DEBUG_TRACE,
							"   backsql_modify_internal(): "
							"error binding output parameter for %s[%d]\n",
							at->bam_ad->ad_cname.bv_val, i, 0 );
608
						backsql_PrintErrors( bi->sql_db_env, dbh, 
609
610
611
612
613
614
615
							sth, rc );
						SQLFreeStmt( sth, SQL_DROP );

						rs->sr_text = "SQL-backend error";
						rs->sr_err = LDAP_OTHER;
						goto done;
					}
616
617
				}
				po = ( BACKSQL_IS_DEL( at->bam_param_order ) ) > 0;
618
619
620
621
622
623
624
				rc = backsql_BindParamID( sth, pno + 1 + po,
					SQL_PARAM_INPUT, &e_id->eid_keyval );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error binding keyval parameter for %s[%d]\n",
						at->bam_ad->ad_cname.bv_val, i, 0 );
625
					backsql_PrintErrors( bi->sql_db_env, dbh, 
626
627
628
629
630
631
632
						sth, rc );
					SQLFreeStmt( sth, SQL_DROP );

					rs->sr_text = "SQL-backend error";
					rs->sr_err = LDAP_OTHER;
					goto done;
				}
633

634
635
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
636
637
638
					"arg(%d)=" BACKSQL_IDFMT "\n", 
					pno + 1 + po,
					BACKSQL_IDARG(e_id->eid_keyval), 0 );
639
640
641
642
643

				/*
				 * check for syntax needed here 
				 * maybe need binary bind?
				 */
644
645
646
647
648
649
650
				rc = backsql_BindParamBerVal( sth, pno + 2 - po,
					SQL_PARAM_INPUT, at_val );
				if ( rc != SQL_SUCCESS ) {
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"error binding value parameter for %s[%d]\n",
						at->bam_ad->ad_cname.bv_val, i, 0 );
651
					backsql_PrintErrors( bi->sql_db_env, dbh, 
652
653
654
						sth, rc );
					SQLFreeStmt( sth, SQL_DROP );

655
656
657
					rs->sr_text = "SQL-backend error";
					rs->sr_err = LDAP_OTHER;
					goto done;
658
				}
659
660
661
662
663

				Debug( LDAP_DEBUG_TRACE,
					"   backsql_modify_internal(): "
					"executing \"%s\"\n", 
					at->bam_delete_proc, 0, 0 );
664
				rc = SQLExecute( sth );
665
666
667
668
669
				if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS )
				{
					rs->sr_err = LDAP_SUCCESS;
					
				} else {
670
671
672
					Debug( LDAP_DEBUG_TRACE,
						"   backsql_modify_internal(): "
						"delete_proc execution "
673
674
675
676
677
678
679
680
						"failed (rc=%d, prc=%d)\n",
						rc, prc, 0 );

					if ( prc != LDAP_SUCCESS ) {
						/* SQL procedure executed fine
						 * but returned an error */
						rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
						rs->sr_text = at->bam_ad->ad_cname.bv_val;
681
						goto done;
682
683
684
685
						
					} else {
						backsql_PrintErrors( bi->sql_db_env,
								dbh, sth, rc );
686
687
688
689
						SQLFreeStmt( sth, SQL_DROP );
						rs->sr_err = LDAP_OTHER;
						rs->sr_text = at->bam_ad->ad_cname.bv_val;
						goto done;
690
691
692
					}
				}
				SQLFreeStmt( sth, SQL_DROP );
693
694
695
696
697
698
699
700
701
702
			}
			break;

	      	case LDAP_MOD_INCREMENT:
			Debug( LDAP_DEBUG_TRACE, "   backsql_modify_internal(): "
				"increment not supported yet\n", 0, 0, 0 );
			if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = "SQL-backend error";
				goto done;
703
704
705
706
707
708
			}
			break;
		}
	}

done:;
709
710
711
	Debug( LDAP_DEBUG_TRACE, "<==backsql_modify_internal(): %d%s%s\n",
		rs->sr_err,
		rs->sr_text ? ": " : "",
712
713
714
715
716
717
718
719
		rs->sr_text ? rs->sr_text : "" );

	/*
	 * FIXME: should fail in case one change fails?
	 */
	return rs->sr_err;
}

720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
static int
backsql_add_attr(
	Operation		*op,
	SlapReply		*rs,
	SQLHDBC 		dbh,
	backsql_oc_map_rec 	*oc,
	Attribute		*at,
	unsigned long		new_keyval )
{
	backsql_info		*bi = (backsql_info*)op->o_bd->be_private;
	backsql_at_map_rec	*at_rec = NULL;
	struct berval		*at_val;
	unsigned long		i;
	RETCODE			rc;
	SQLUSMALLINT		currpos;
735
	SQLHSTMT 		sth = SQL_NULL_HSTMT;
736
737
738
739

	at_rec = backsql_ad2at( oc, at->a_desc ); 
  
	if ( at_rec == NULL ) {
740
		Debug( LDAP_DEBUG_TRACE, "   backsql_add_attr(\"%s\"): "
741
742
			"attribute \"%s\" is not registered "
			"in objectclass \"%s\"\n",
743
			op->ora_e->e_name.bv_val,
744
745
746
747
748
749
750
751
752
753
754
755
756
			at->a_desc->ad_cname.bv_val,
			BACKSQL_OC_NAME( oc ) );

		if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
			rs->sr_text = "operation not permitted "
				"within namingContext";
			return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		}

		return LDAP_SUCCESS;
	}
	
	if ( at_rec->bam_add_proc == NULL ) {
757
		Debug( LDAP_DEBUG_TRACE, "   backsql_add_attr(\"%s\"): "
758
759
760
			"add procedure is not defined "
			"for attribute \"%s\" "
			"of structuralObjectClass \"%s\"\n",
761
			op->ora_e->e_name.bv_val,
762
763
764
765
766
767
768
769
770
771
772
773
774
			at->a_desc->ad_cname.bv_val,
			BACKSQL_OC_NAME( oc ) );

		if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
			rs->sr_text = "operation not permitted "
				"within namingContext";
			return rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		}

		return LDAP_SUCCESS;
	}

	for ( i = 0, at_val = &at->a_vals[ i ];
775
		       	!BER_BVISNULL( at_val );
776
777
			i++, at_val = &at->a_vals[ i ] )
	{
778
779
780
781
		/* procedure return code */
		int		prc = LDAP_SUCCESS;
		/* first parameter #, parameter order */
		SQLUSMALLINT	pno, po;
782
		char		logbuf[ STRLENOF("val[], id=") + 2*LDAP_PVT_INTTYPE_CHARS(unsigned long)];
783
784
785
786
787
788
		
		/*
		 * Do not deal with the objectClass that is used
		 * to build the entry
		 */
		if ( at->a_desc == slap_schema.si_ad_objectClass ) {
789
			if ( dn_match( at_val, &oc->bom_oc->soc_cname ) )
790
791
792
793
794
			{
				continue;
			}
		}

795
		rc = backsql_Prepare( dbh, &sth, at_rec->bam_add_proc, 0 );
796
		if ( rc != SQL_SUCCESS ) {
797
798
			rs->sr_text = "SQL-backend error";
			return rs->sr_err = LDAP_OTHER;
799
800
801
802
		}

		if ( BACKSQL_IS_ADD( at_rec->bam_expect_return ) ) {
			pno = 1;
803
804
805
806
			rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &prc );
			if ( rc != SQL_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_add_attr(): "
807
					"error binding output parameter for %s[%lu]\n",
808
					at_rec->bam_ad->ad_cname.bv_val, i, 0 );
809
				backsql_PrintErrors( bi->sql_db_env, dbh, 
810
811
812
					sth, rc );
				SQLFreeStmt( sth, SQL_DROP );

813
814
				rs->sr_text = "SQL-backend error";
				return rs->sr_err = LDAP_OTHER;
815
816
			}

817
818
819
820
821
822
		} else {
			pno = 0;
		}

		po = ( BACKSQL_IS_ADD( at_rec->bam_param_order ) ) > 0;
		currpos = pno + 1 + po;
823
824
825
826
827
		rc = backsql_BindParamInt( sth, currpos,
				SQL_PARAM_INPUT, &new_keyval );
		if ( rc != SQL_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE,
				"   backsql_add_attr(): "
828
				"error binding keyval parameter for %s[%lu]\n",
829
				at_rec->bam_ad->ad_cname.bv_val, i, 0 );
830
			backsql_PrintErrors( bi->sql_db_env, dbh, 
831
832
833
				sth, rc );
			SQLFreeStmt( sth, SQL_DROP );

834
835
			rs->sr_text = "SQL-backend error";
			return rs->sr_err = LDAP_OTHER;
836
837
		}

838
839
840
841
842
843
844
		currpos = pno + 2 - po;

		/*
		 * check for syntax needed here 
		 * maybe need binary bind?
		 */

845
846
847
848
		rc = backsql_BindParamBerVal( sth, currpos, SQL_PARAM_INPUT, at_val );
		if ( rc != SQL_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE,
				"   backsql_add_attr(): "
849
				"error binding value parameter for %s[%lu]\n",
850
				at_rec->bam_ad->ad_cname.bv_val, i, 0 );
851
			backsql_PrintErrors( bi->sql_db_env, dbh, 
852
853
854
				sth, rc );
			SQLFreeStmt( sth, SQL_DROP );

855
856
			rs->sr_text = "SQL-backend error";
			return rs->sr_err = LDAP_OTHER;
857
		}
858
859

#ifdef LDAP_DEBUG
860
		snprintf( logbuf, sizeof( logbuf ), "val[%lu], id=%lu",
861
				i, new_keyval );
862
		Debug( LDAP_DEBUG_TRACE, "   backsql_add_attr(\"%s\"): "
863
			"executing \"%s\" %s\n", 
864
			op->ora_e->e_name.bv_val,
865
866
			at_rec->bam_add_proc, logbuf );
#endif
867
		rc = SQLExecute( sth );
868
869
870
871
		if ( rc == SQL_SUCCESS && prc == LDAP_SUCCESS ) {
			rs->sr_err = LDAP_SUCCESS;

		} else {
872
			Debug( LDAP_DEBUG_TRACE,
873
				"   backsql_add_attr(\"%s\"): "
874
				"add_proc execution failed (rc=%d, prc=%d)\n", 
875
				op->ora_e->e_name.bv_val, rc, prc );
876
877
878
879
			if ( prc != LDAP_SUCCESS ) {
				/* SQL procedure executed fine
				 * but returned an error */
				rs->sr_err = BACKSQL_SANITIZE_ERROR( prc );
880
				rs->sr_text = op->ora_e->e_name.bv_val;
881
				SQLFreeStmt( sth, SQL_DROP );
882
883
884
885
886
				return rs->sr_err;

			} else {
				backsql_PrintErrors( bi->sql_db_env, dbh,
						sth, rc );
887
888
889
890
				rs->sr_err = LDAP_OTHER;
				rs->sr_text = op->ora_e->e_name.bv_val;
				SQLFreeStmt( sth, SQL_DROP );
				return rs->sr_err;
891
892
			}
		}
893
		SQLFreeStmt( sth, SQL_DROP );
894
895
896
897
898
	}

	return LDAP_SUCCESS;
}

899
900
901
902
int
backsql_add( Operation *op, SlapReply *rs )
{
	backsql_info		*bi = (backsql_info*)op->o_bd->be_private;
903
904
	SQLHDBC 		dbh = SQL_NULL_HDBC;
	SQLHSTMT 		sth = SQL_NULL_HSTMT;
905
906
907
	unsigned long		new_keyval = 0;
	RETCODE			rc;
	backsql_oc_map_rec 	*oc = NULL;
908
	backsql_srch_info	bsi = { 0 };
909
	Entry			p = { 0 }, *e = NULL;
910
911
	Attribute		*at,
				*at_objectClass = NULL;
912
	ObjectClass		*soc = NULL;
913
	struct berval		scname = BER_BVNULL;
914
	struct berval		pdn;
915
	struct berval		realdn = BER_BVNULL;
916
	int			colnum;
917
	slap_mask_t		mask;
918

919
920
921
	char			textbuf[ SLAP_TEXT_BUFLEN ];
	size_t			textlen = sizeof( textbuf );

922
923
924
925
926
#ifdef BACKSQL_SYNCPROV
	/*
	 * NOTE: fake successful result to force contextCSN to be bumped up
	 */
	if ( op->o_sync ) {
927
		char		buf[ LDAP_PVT_CSNSTR_BUFSIZE ];
Howard Chu's avatar
Howard Chu committed
928
		struct berval	csn;
929

Howard Chu's avatar
Howard Chu committed
930
931
932
		csn.bv_val = buf;
		csn.bv_len = sizeof( buf );
		slap_get_csn( op, &csn, 1 );
933
934
935
936
937
938
939
940
941
942

		rs->sr_err = LDAP_SUCCESS;
		send_ldap_result( op, rs );

		slap_graduate_commit_csn( op );

		return 0;
	}
#endif /* BACKSQL_SYNCPROV */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
943
	Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n",
944
			op->ora_e->e_name.bv_val, 0, 0 );
945
946

	/* check schema */
947
	if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
948
949
		char		textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' };

950
		rs->sr_err = entry_schema_check( op, op->ora_e, NULL, 0, 1, NULL,
951
			&rs->sr_text, textbuf, sizeof( textbuf ) );
952
		if ( rs->sr_err != LDAP_SUCCESS ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
953
			Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
954
				"entry failed schema check -- aborting\n",
955
956
				op->ora_e->e_name.bv_val, 0, 0 );
			e = NULL;
957
958
959
960
			goto done;
		}
	}

961
962
	slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );

963
964
965
966
967
968
969
970
971
972
973
	if ( get_assert( op ) &&
		( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE ))
	{
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
			"assertion control failed -- aborting\n",
			op->ora_e->e_name.bv_val, 0, 0 );
		e = NULL;
		rs->sr_err = LDAP_ASSERTION_FAILED;
		goto done;
	}

974
	/* search structuralObjectClass */
975
	for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
976
977
978
979
980
981
		if ( at->a_desc == slap_schema.si_ad_structuralObjectClass ) {
			break;
		}
	}

	/* there must exist */
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
	if ( at == NULL ) {
		char		buf[ SLAP_TEXT_BUFLEN ];
		const char	*text;

		/* search structuralObjectClass */
		for ( at = op->ora_e->e_attrs; at != NULL; at = at->a_next ) {
			if ( at->a_desc == slap_schema.si_ad_objectClass ) {
				break;
			}
		}

		if ( at == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
				"no objectClass\n",
				op->ora_e->e_name.bv_val, 0, 0 );
			rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION;
			e = NULL;
			goto done;
		}

1002
		rs->sr_err = structural_class( at->a_vals, &soc, NULL,
1003
				&text, buf, sizeof( buf ), op->o_tmpmemctx );
1004
1005
1006
1007
1008
1009
1010
		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
				"%s (%d)\n",
				op->ora_e->e_name.bv_val, text, rs->sr_err );
			e = NULL;
			goto done;
		}
1011
		scname = soc->soc_cname;
1012
1013
1014
1015

	} else {
		scname = at->a_vals[0];
	}
1016
1017

	/* I guess we should play with sub/supertypes to find a suitable oc */
1018
	oc = backsql_name2oc( bi, &scname );
1019
1020

	if ( oc == NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1021
1022
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
			"cannot map structuralObjectClass \"%s\" -- aborting\n",
1023
			op->ora_e->e_name.bv_val,
1024
			scname.bv_val, 0 );
1025
1026
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		rs->sr_text = "operation not permitted within namingContext";
1027
		e = NULL;
1028
1029
1030
1031
		goto done;
	}

	if ( oc->bom_create_proc == NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1032
1033
1034
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
			"create procedure is not defined "
			"for structuralObjectClass \"%s\" - aborting\n",
1035
			op->ora_e->e_name.bv_val,
1036
			scname.bv_val, 0 );
1037
1038
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		rs->sr_text = "operation not permitted within namingContext";
1039
		e = NULL;
1040
1041
1042
1043
		goto done;

	} else if ( BACKSQL_CREATE_NEEDS_SELECT( bi )
			&& oc->bom_create_keyval == NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1044
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
1045
			"create procedure needs select procedure, "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1046
1047
			"but none is defined for structuralObjectClass \"%s\" "
			"- aborting\n",
1048
			op->ora_e->e_name.bv_val,
1049
			scname.bv_val, 0 );
1050
1051
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		rs->sr_text = "operation not permitted within namingContext";
1052
		e = NULL;
1053
1054
1055
		goto done;
	}

1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
	/* check write access */
	if ( !access_allowed_mask( op, op->ora_e,
				slap_schema.si_ad_entry,
				NULL, ACL_WADD, NULL, &mask ) )
	{
		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
		e = op->ora_e;
		goto done;
	}

1066
1067
	rs->sr_err = backsql_get_db_conn( op, &dbh );
	if ( rs->sr_err != LDAP_SUCCESS ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1068
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
1069
			"could not get connection handle - exiting\n", 
1070
			op->ora_e->e_name.bv_val, 0, 0 );
1071
1072
		rs->sr_text = ( rs->sr_err == LDAP_OTHER )
			?  "SQL-backend error" : NULL;
1073
		e = NULL;
1074
1075
1076
1077
1078
		goto done;
	}

	/*
	 * Check if entry exists
1079
	 *
1080
1081
	 * NOTE: backsql_api_dn2odbc() is called explicitly because
	 * we need the mucked DN to pass it to the create procedure.
1082
	 */
1083
	realdn = op->ora_e->e_name;
1084
	if ( backsql_api_dn2odbc( op, rs, &realdn ) ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1085
1086
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
			"backsql_api_dn2odbc(\"%s\") failed\n", 
1087
			op->ora_e->e_name.bv_val, realdn.bv_val, 0 );
1088
1089
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "SQL-backend error";
1090
		e = NULL;
1091
1092
1093
		goto done;
	}

1094
	rs->sr_err = backsql_dn2id( op, rs, dbh, &realdn, NULL, 0, 0 );
1095
	if ( rs->sr_err == LDAP_SUCCESS ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
1096
1097
		Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
			"entry exists\n",
1098
			op->ora_e->e_name.bv_val, 0, 0 );
1099
		rs->sr_err = LDAP_ALREADY_EXISTS;
1100
		e = op->ora_e;
1101
1102
1103
1104
		goto done;
	}

	/*
1105
	 * Get the parent dn and see if the corresponding entry exists.
1106
	 */
1107
	if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) {
1108
		pdn = slap_empty_bv;
1109

1110
	} else {
1111
		dnParent( &op->ora_e->e_nname, &pdn );
1112

1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
		/*
		 * Get the parent
		 */
		bsi.bsi_e = &p;
		rs->sr_err = backsql_init_search( &bsi, &pdn,
				LDAP_SCOPE_BASE, 
				(time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs,
				( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_TRACE, "backsql_add(): "
				"could not retrieve addDN parent "
				"\"%s\" ID - %s matched=\"%s\"\n", 
				pdn.bv_val,
				rs->sr_err == LDAP_REFERRAL ? "referral" : "no such entry",
				rs->sr_matched ? rs->sr_matched : "(null)" );
			e = &p;
			goto done;
		}
1131

1132
1133
1134
1135
1136
1137
1138
1139
		/* check "children" pseudo-attribute access to parent */
		if ( !access_allowed( op, &p, slap_schema.si_ad_children,
					NULL, ACL_WADD, NULL ) )
		{
			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
			e = &p;
			goto done;
		}
1140
1141
	}

1142
1143
1144
1145
1146
1147
	/*
	 * create_proc is executed; if expect_return is set, then
	 * an output parameter is bound, which should contain 
	 * the id of the added row; otherwise the procedure
	 * is expected to return the id as the first column of a select
	 */
1148
	rc = backsql_Prepare( dbh, &sth, oc->bom_create_proc, 0 );
1149
1150
1151
	if ( rc != SQL_SUCCESS ) {
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "SQL-backend error";
1152
		e = NULL;
1153
1154
1155
		goto done;
	}

1156
	colnum = 1;
1157
	if ( BACKSQL_IS_ADD( oc->bom_expect_return ) ) {
1158
1159
		rc = backsql_BindParamInt( sth, 1, SQL_PARAM_OUTPUT, &new_keyval );
		if ( rc != SQL_SUCCESS ) {
1160
1161
1162
1163
1164
			Debug( LDAP_DEBUG_TRACE, "   backsql_add(\"%s\"): "
				"error binding keyval parameter "
				"for objectClass %s\n",
				op->ora_e->e_name.bv_val,
				oc->bom_oc->soc_cname.bv_val, 0 );
1165
			backsql_PrintErrors( bi->sql_db_env, dbh, 
1166
1167
1168
1169
1170
				sth, rc );
			SQLFreeStmt( sth, SQL_DROP );

			rs->sr_text = "SQL-backend error";
			rs->sr_err = LDAP_OTHER;
1171
			e = NULL;
1172
1173
			goto done;
		}
1174
1175
1176
1177
		colnum++;
	}

	if ( oc->bom_create_hint ) {
1178
		<