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