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