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