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