Back to index

openldap  2.4.31
entry-id.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1999-2012 The OpenLDAP Foundation.
00005  * Portions Copyright 1999 Dmitry Kovalev.
00006  * Portions Copyright 2002 Pierangelo Masarati.
00007  * Portions Copyright 2004 Mark Adamson.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* ACKNOWLEDGEMENTS:
00019  * This work was initially developed by Dmitry Kovalev for inclusion
00020  * by OpenLDAP Software.  Additional significant contributors include
00021  * Pierangelo Masarati and Mark Adamson.
00022  */
00023 
00024 #include "portable.h"
00025 
00026 #include <stdio.h>
00027 #include <sys/types.h>
00028 #include "ac/string.h"
00029 
00030 #include "lutil.h"
00031 #include "slap.h"
00032 #include "proto-sql.h"
00033 
00034 #ifdef BACKSQL_ARBITRARY_KEY
00035 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
00036 #endif /* BACKSQL_ARBITRARY_KEY */
00037 
00038 backsql_entryID *
00039 backsql_entryID_dup( backsql_entryID *src, void *ctx )
00040 {
00041        backsql_entryID      *dst;
00042 
00043        if ( src == NULL ) return NULL;
00044 
00045        dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
00046        ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
00047        if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
00048               dst->eid_dn = dst->eid_ndn;
00049        } else {
00050               ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
00051        }
00052 
00053 #ifdef BACKSQL_ARBITRARY_KEY
00054        ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
00055        ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
00056 #else /* ! BACKSQL_ARBITRARY_KEY */
00057        dst->eid_id = src->eid_id;
00058        dst->eid_keyval = src->eid_keyval;
00059 #endif /* ! BACKSQL_ARBITRARY_KEY */
00060 
00061        dst->eid_oc = src->eid_oc;
00062        dst->eid_oc_id = src->eid_oc_id;
00063 
00064        return dst;
00065 }
00066 
00067 backsql_entryID *
00068 backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
00069 {
00070        backsql_entryID      *next;
00071 
00072        assert( id != NULL );
00073 
00074        next = id->eid_next;
00075 
00076        if ( !BER_BVISNULL( &id->eid_ndn ) ) {
00077               if ( !BER_BVISNULL( &id->eid_dn )
00078                             && id->eid_dn.bv_val != id->eid_ndn.bv_val )
00079               {
00080                      slap_sl_free( id->eid_dn.bv_val, ctx );
00081                      BER_BVZERO( &id->eid_dn );
00082               }
00083 
00084               slap_sl_free( id->eid_ndn.bv_val, ctx );
00085               BER_BVZERO( &id->eid_ndn );
00086        }
00087 
00088 #ifdef BACKSQL_ARBITRARY_KEY
00089        if ( !BER_BVISNULL( &id->eid_id ) ) {
00090               slap_sl_free( id->eid_id.bv_val, ctx );
00091               BER_BVZERO( &id->eid_id );
00092        }
00093 
00094        if ( !BER_BVISNULL( &id->eid_keyval ) ) {
00095               slap_sl_free( id->eid_keyval.bv_val, ctx );
00096               BER_BVZERO( &id->eid_keyval );
00097        }
00098 #endif /* BACKSQL_ARBITRARY_KEY */
00099 
00100        if ( freeit ) {
00101               slap_sl_free( id, ctx );
00102        }
00103 
00104        return next;
00105 }
00106 
00107 /*
00108  * NOTE: the dn must be normalized
00109  */
00110 int
00111 backsql_dn2id(
00112        Operation            *op,
00113        SlapReply            *rs,
00114        SQLHDBC                     dbh,
00115        struct berval        *ndn,
00116        backsql_entryID             *id,
00117        int                  matched,
00118        int                  muck )
00119 {
00120        backsql_info         *bi = op->o_bd->be_private;
00121        SQLHSTMT             sth = SQL_NULL_HSTMT; 
00122        BACKSQL_ROW_NTS             row = { 0 };
00123        RETCODE              rc;
00124        int                  res;
00125        struct berval        realndn = BER_BVNULL;
00126 
00127        /* TimesTen */
00128        char                 upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
00129        struct berval        tbbDN;
00130        int                  i, j;
00131 
00132        /*
00133         * NOTE: id can be NULL; in this case, the function
00134         * simply checks whether the DN can be successfully 
00135         * turned into an ID, returning LDAP_SUCCESS for
00136         * positive cases, or the most appropriate error
00137         */
00138 
00139        Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", 
00140                      ndn->bv_val, id == NULL ? " (no ID expected)" : "",
00141                      matched ? " matched expected" : "" );
00142 
00143        if ( id ) {
00144               /* NOTE: trap inconsistencies */
00145               assert( BER_BVISNULL( &id->eid_ndn ) );
00146        }
00147 
00148        if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
00149               Debug( LDAP_DEBUG_TRACE, 
00150                      "   backsql_dn2id(\"%s\"): DN length=%ld "
00151                      "exceeds max DN length %d:\n",
00152                      ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
00153               return LDAP_OTHER;
00154        }
00155 
00156        /* return baseObject if available and matches */
00157        /* FIXME: if ndn is already mucked, we cannot check this */
00158        if ( bi->sql_baseObject != NULL &&
00159                      dn_match( ndn, &bi->sql_baseObject->e_nname ) )
00160        {
00161               if ( id != NULL ) {
00162 #ifdef BACKSQL_ARBITRARY_KEY
00163                      ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv,
00164                                    op->o_tmpmemctx );
00165                      ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv,
00166                                    op->o_tmpmemctx );
00167 #else /* ! BACKSQL_ARBITRARY_KEY */
00168                      id->eid_id = BACKSQL_BASEOBJECT_ID;
00169                      id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
00170 #endif /* ! BACKSQL_ARBITRARY_KEY */
00171                      id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
00172 
00173                      ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname,
00174                                    op->o_tmpmemctx );
00175                      ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name,
00176                                    op->o_tmpmemctx );
00177 
00178                      id->eid_next = NULL;
00179               }
00180 
00181               return LDAP_SUCCESS;
00182        }
00183        
00184        /* begin TimesTen */
00185        assert( bi->sql_id_query != NULL );
00186        Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): id_query \"%s\"\n",
00187                      ndn->bv_val, bi->sql_id_query, 0 );
00188        rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
00189        if ( rc != SQL_SUCCESS ) {
00190               Debug( LDAP_DEBUG_TRACE, 
00191                      "   backsql_dn2id(\"%s\"): "
00192                      "error preparing SQL:\n   %s", 
00193                      ndn->bv_val, bi->sql_id_query, 0 );
00194               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00195               res = LDAP_OTHER;
00196               goto done;
00197        }
00198 
00199        realndn = *ndn;
00200        if ( muck ) {
00201               if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
00202                      Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
00203                             "backsql_api_dn2odbc(\"%s\") failed\n", 
00204                             ndn->bv_val, realndn.bv_val, 0 );
00205                      res = LDAP_OTHER;
00206                      goto done;
00207               }
00208        }
00209 
00210        if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
00211               /*
00212                * Prepare an upper cased, byte reversed version 
00213                * that can be searched using indexes
00214                */
00215 
00216               for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
00217               {
00218                      upperdn[ i ] = realndn.bv_val[ j ];
00219               }
00220               upperdn[ i ] = '\0';
00221               ldap_pvt_str2upper( upperdn );
00222 
00223               Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
00224                             "upperdn=\"%s\"\n",
00225                             ndn->bv_val, upperdn, 0 );
00226               ber_str2bv( upperdn, 0, 0, &tbbDN );
00227 
00228        } else {
00229               if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
00230                      AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
00231                      ldap_pvt_str2upper( upperdn );
00232                      Debug( LDAP_DEBUG_TRACE,
00233                             "   backsql_dn2id(\"%s\"): "
00234                             "upperdn=\"%s\"\n",
00235                             ndn->bv_val, upperdn, 0 );
00236                      ber_str2bv( upperdn, 0, 0, &tbbDN );
00237 
00238               } else {
00239                      tbbDN = realndn;
00240               }
00241        }
00242 
00243        rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
00244        if ( rc != SQL_SUCCESS) {
00245               /* end TimesTen */ 
00246               Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
00247                      "error binding dn=\"%s\" parameter:\n", 
00248                      ndn->bv_val, tbbDN.bv_val, 0 );
00249               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00250               res = LDAP_OTHER;
00251               goto done;
00252        }
00253 
00254        rc = SQLExecute( sth );
00255        if ( rc != SQL_SUCCESS ) {
00256               Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
00257                      "error executing query (\"%s\", \"%s\"):\n", 
00258                      ndn->bv_val, bi->sql_id_query, tbbDN.bv_val );
00259               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00260               res = LDAP_OTHER;
00261               goto done;
00262        }
00263 
00264        backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
00265        rc = SQLFetch( sth );
00266        if ( BACKSQL_SUCCESS( rc ) ) {
00267               char   buf[ SLAP_TEXT_BUFLEN ];
00268 
00269 #ifdef LDAP_DEBUG
00270               snprintf( buf, sizeof(buf),
00271                      "id=%s keyval=%s oc_id=%s dn=%s",
00272                      row.cols[ 0 ], row.cols[ 1 ],
00273                      row.cols[ 2 ], row.cols[ 3 ] );
00274               Debug( LDAP_DEBUG_TRACE,
00275                      "   backsql_dn2id(\"%s\"): %s\n",
00276                      ndn->bv_val, buf, 0 );
00277 #endif /* LDAP_DEBUG */
00278 
00279               res = LDAP_SUCCESS;
00280               if ( id != NULL ) {
00281                      struct berval dn;
00282 
00283                      id->eid_next = NULL;
00284 
00285 #ifdef BACKSQL_ARBITRARY_KEY
00286                      ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id,
00287                                    op->o_tmpmemctx );
00288                      ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval,
00289                                    op->o_tmpmemctx );
00290 #else /* ! BACKSQL_ARBITRARY_KEY */
00291                      if ( BACKSQL_STR2ID( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) {
00292                             res = LDAP_OTHER;
00293                             goto done;
00294                      }
00295                      if ( BACKSQL_STR2ID( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) {
00296                             res = LDAP_OTHER;
00297                             goto done;
00298                      }
00299 #endif /* ! BACKSQL_ARBITRARY_KEY */
00300                      if ( BACKSQL_STR2ID( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) {
00301                             res = LDAP_OTHER;
00302                             goto done;
00303                      }
00304 
00305                      ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
00306 
00307                      if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
00308                             res = LDAP_OTHER;
00309                             goto done;
00310                      }
00311                      
00312                      res = dnPrettyNormal( NULL, &dn,
00313                                    &id->eid_dn, &id->eid_ndn,
00314                                    op->o_tmpmemctx );
00315                      if ( res != LDAP_SUCCESS ) {
00316                             Debug( LDAP_DEBUG_TRACE,
00317                                    "   backsql_dn2id(\"%s\"): "
00318                                    "dnPrettyNormal failed (%d: %s)\n",
00319                                    realndn.bv_val, res,
00320                                    ldap_err2string( res ) );
00321 
00322                             /* cleanup... */
00323                             (void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
00324                      }
00325 
00326                      if ( dn.bv_val != row.cols[ 3 ] ) {
00327                             free( dn.bv_val );
00328                      }
00329               }
00330 
00331        } else {
00332               res = LDAP_NO_SUCH_OBJECT;
00333               if ( matched ) {
00334                      struct berval pdn = *ndn;
00335 
00336                      /*
00337                       * Look for matched
00338                       */
00339                      rs->sr_matched = NULL;
00340                      while ( !be_issuffix( op->o_bd, &pdn ) ) {
00341                             char          *matchedDN = NULL;
00342        
00343                             dnParent( &pdn, &pdn );
00344        
00345                             /*
00346                              * Empty DN ("") defaults to LDAP_SUCCESS
00347                              */
00348                             rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 );
00349                             switch ( rs->sr_err ) {
00350                             case LDAP_NO_SUCH_OBJECT:
00351                                    /* try another one */
00352                                    break;
00353                                    
00354                             case LDAP_SUCCESS:
00355                                    matchedDN = pdn.bv_val;
00356                                    /* fail over to next case */
00357        
00358                             default:
00359                                    rs->sr_err = LDAP_NO_SUCH_OBJECT;
00360                                    rs->sr_matched = matchedDN;
00361                                    goto done;
00362                             } 
00363                      }
00364               }
00365        }
00366 
00367 done:;
00368        backsql_FreeRow_x( &row, op->o_tmpmemctx );
00369 
00370        Debug( LDAP_DEBUG_TRACE,
00371               "<==backsql_dn2id(\"%s\"): err=%d\n",
00372               ndn->bv_val, res, 0 );
00373        if ( sth != SQL_NULL_HSTMT ) {
00374               SQLFreeStmt( sth, SQL_DROP );
00375        }
00376 
00377        if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
00378               ch_free( realndn.bv_val );
00379        }
00380 
00381        return res;
00382 }
00383 
00384 int
00385 backsql_count_children(
00386        Operation            *op,
00387        SQLHDBC                     dbh,
00388        struct berval        *dn,
00389        unsigned long        *nchildren )
00390 {
00391        backsql_info         *bi = (backsql_info *)op->o_bd->be_private;
00392        SQLHSTMT             sth = SQL_NULL_HSTMT;
00393        BACKSQL_ROW_NTS             row;
00394        RETCODE              rc;
00395        int                  res = LDAP_SUCCESS;
00396 
00397        Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n", 
00398                      dn->bv_val, 0, 0 );
00399 
00400        if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
00401               Debug( LDAP_DEBUG_TRACE, 
00402                      "backsql_count_children(): DN \"%s\" (%ld bytes) "
00403                      "exceeds max DN length (%d):\n",
00404                      dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
00405               return LDAP_OTHER;
00406        }
00407        
00408        /* begin TimesTen */
00409        assert( bi->sql_has_children_query != NULL );
00410        Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n", 
00411                      bi->sql_has_children_query, 0, 0);
00412        rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
00413        if ( rc != SQL_SUCCESS ) {
00414               Debug( LDAP_DEBUG_TRACE, 
00415                      "backsql_count_children(): error preparing SQL:\n%s", 
00416                      bi->sql_has_children_query, 0, 0);
00417               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00418               SQLFreeStmt( sth, SQL_DROP );
00419               return LDAP_OTHER;
00420        }
00421 
00422        rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
00423        if ( rc != SQL_SUCCESS) {
00424               /* end TimesTen */ 
00425               Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
00426                      "error binding dn=\"%s\" parameter:\n", 
00427                      dn->bv_val, 0, 0 );
00428               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00429               SQLFreeStmt( sth, SQL_DROP );
00430               return LDAP_OTHER;
00431        }
00432 
00433        rc = SQLExecute( sth );
00434        if ( rc != SQL_SUCCESS ) {
00435               Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
00436                      "error executing query (\"%s\", \"%s\"):\n", 
00437                      bi->sql_has_children_query, dn->bv_val, 0 );
00438               backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
00439               SQLFreeStmt( sth, SQL_DROP );
00440               return LDAP_OTHER;
00441        }
00442 
00443        backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
00444        
00445        rc = SQLFetch( sth );
00446        if ( BACKSQL_SUCCESS( rc ) ) {
00447               char *end;
00448 
00449               *nchildren = strtol( row.cols[ 0 ], &end, 0 );
00450               if ( end == row.cols[ 0 ] ) {
00451                      res = LDAP_OTHER;
00452 
00453               } else {
00454                      switch ( end[ 0 ] ) {
00455                      case '\0':
00456                             break;
00457 
00458                      case '.': {
00459                             unsigned long ul;
00460 
00461                             /* FIXME: braindead RDBMSes return
00462                              * a fractional number from COUNT!
00463                              */
00464                             if ( lutil_atoul( &ul, end + 1 ) != 0 || ul != 0 ) {
00465                                    res = LDAP_OTHER;
00466                             }
00467                             } break;
00468 
00469                      default:
00470                             res = LDAP_OTHER;
00471                      }
00472               }
00473 
00474        } else {
00475               res = LDAP_OTHER;
00476        }
00477        backsql_FreeRow_x( &row, op->o_tmpmemctx );
00478 
00479        SQLFreeStmt( sth, SQL_DROP );
00480 
00481        Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
00482                      *nchildren, 0, 0 );
00483 
00484        return res;
00485 }
00486 
00487 int
00488 backsql_has_children(
00489        Operation            *op,
00490        SQLHDBC                     dbh,
00491        struct berval        *dn )
00492 {
00493        unsigned long nchildren;
00494        int           rc;
00495 
00496        rc = backsql_count_children( op, dbh, dn, &nchildren );
00497 
00498        if ( rc == LDAP_SUCCESS ) {
00499               return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
00500        }
00501 
00502        return rc;
00503 }
00504 
00505 static int
00506 backsql_get_attr_vals( void *v_at, void *v_bsi )
00507 {
00508        backsql_at_map_rec   *at = v_at;
00509        backsql_srch_info    *bsi = v_bsi;
00510        backsql_info         *bi;
00511        RETCODE                     rc;
00512        SQLHSTMT             sth = SQL_NULL_HSTMT;
00513        BACKSQL_ROW_NTS             row;
00514        unsigned long        i,
00515                             k = 0,
00516                             oldcount = 0,
00517                             res = 0;
00518 #ifdef BACKSQL_COUNTQUERY
00519        unsigned             count,
00520                             j,
00521                             append = 0;
00522        SQLLEN               countsize = sizeof( count );
00523        Attribute            *attr = NULL;
00524 
00525        slap_mr_normalize_func             *normfunc = NULL;
00526 #endif /* BACKSQL_COUNTQUERY */
00527 #ifdef BACKSQL_PRETTY_VALIDATE
00528        slap_syntax_validate_func   *validate = NULL;
00529        slap_syntax_transform_func  *pretty = NULL;
00530 #endif /* BACKSQL_PRETTY_VALIDATE */
00531 
00532        assert( at != NULL );
00533        assert( bsi != NULL );
00534        Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
00535               "oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n",
00536               BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
00537               BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) );
00538 
00539        bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
00540 
00541 #ifdef BACKSQL_PRETTY_VALIDATE
00542        validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
00543        pretty =  at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
00544 
00545        if ( validate == NULL && pretty == NULL ) {
00546               return 1;
00547        }
00548 #endif /* BACKSQL_PRETTY_VALIDATE */
00549 
00550 #ifdef BACKSQL_COUNTQUERY
00551        if ( at->bam_true_ad->ad_type->sat_equality ) {
00552               normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
00553        }
00554 
00555        /* Count how many rows will be returned. This avoids memory 
00556         * fragmentation that can result from loading the values in 
00557         * one by one and using realloc() 
00558         */
00559        rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 );
00560        if ( rc != SQL_SUCCESS ) {
00561               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00562                      "error preparing count query: %s\n",
00563                      at->bam_countquery, 0, 0 );
00564               backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
00565               return 1;
00566        }
00567 
00568        rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
00569                      &bsi->bsi_c_eid->eid_keyval );
00570        if ( rc != SQL_SUCCESS ) {
00571               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00572                      "error binding key value parameter\n", 0, 0, 0 );
00573               SQLFreeStmt( sth, SQL_DROP );
00574               return 1;
00575        }
00576 
00577        rc = SQLExecute( sth );
00578        if ( ! BACKSQL_SUCCESS( rc ) ) {
00579               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00580                      "error executing attribute count query '%s'\n",
00581                      at->bam_countquery, 0, 0 );
00582               backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
00583               SQLFreeStmt( sth, SQL_DROP );
00584               return 1;
00585        }
00586 
00587        SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG,
00588                      (SQLPOINTER)&count,
00589                      (SQLINTEGER)sizeof( count ),
00590                      &countsize );
00591 
00592        rc = SQLFetch( sth );
00593        if ( rc != SQL_SUCCESS ) {
00594               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00595                      "error fetch results of count query: %s\n",
00596                      at->bam_countquery, 0, 0 );
00597               backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
00598               SQLFreeStmt( sth, SQL_DROP );
00599               return 1;
00600        }
00601 
00602        Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00603               "number of values in query: %u\n", count, 0, 0 );
00604        SQLFreeStmt( sth, SQL_DROP );
00605        if ( count == 0 ) {
00606               return 1;
00607        }
00608 
00609        attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
00610        if ( attr != NULL ) {
00611               BerVarray     tmp;
00612 
00613               if ( attr->a_vals != NULL ) {
00614                      oldcount = attr->a_numvals;
00615               }
00616 
00617               tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
00618               if ( tmp == NULL ) {
00619                      return 1;
00620               }
00621               attr->a_vals = tmp;
00622               memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
00623 
00624               if ( normfunc ) {
00625                      tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
00626                      if ( tmp == NULL ) {
00627                             return 1;
00628                      }
00629                      attr->a_nvals = tmp;
00630                      memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
00631 
00632               } else {
00633                      attr->a_nvals = attr->a_vals;
00634               }
00635               attr->a_numvals += count;
00636 
00637        } else {
00638               append = 1;
00639 
00640               /* Make space for the array of values */
00641               attr = attr_alloc( at->bam_true_ad );
00642               attr->a_numvals = count;
00643               attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
00644               if ( attr->a_vals == NULL ) {
00645                      Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
00646                      ch_free( attr );
00647                      return 1;
00648               }
00649               if ( normfunc ) {
00650                      attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
00651                      if ( attr->a_nvals == NULL ) {
00652                             ch_free( attr->a_vals );
00653                             ch_free( attr );
00654                             return 1;
00655 
00656                      }
00657 
00658               } else {
00659                      attr->a_nvals = attr->a_vals;
00660               }
00661        }
00662 #endif /* BACKSQL_COUNTQUERY */
00663 
00664        rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
00665        if ( rc != SQL_SUCCESS ) {
00666               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00667                      "error preparing query: %s\n", at->bam_query, 0, 0 );
00668               backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
00669 #ifdef BACKSQL_COUNTQUERY
00670               if ( append ) {
00671                      attr_free( attr );
00672               }
00673 #endif /* BACKSQL_COUNTQUERY */
00674               return 1;
00675        }
00676 
00677        rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
00678                      &bsi->bsi_c_eid->eid_keyval );
00679        if ( rc != SQL_SUCCESS ) {
00680               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00681                      "error binding key value parameter\n", 0, 0, 0 );
00682 #ifdef BACKSQL_COUNTQUERY
00683               if ( append ) {
00684                      attr_free( attr );
00685               }
00686 #endif /* BACKSQL_COUNTQUERY */
00687               return 1;
00688        }
00689 
00690 #ifdef BACKSQL_TRACE
00691        Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00692               "query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query,
00693               BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval), 0 );
00694 #endif /* BACKSQL_TRACE */
00695 
00696        rc = SQLExecute( sth );
00697        if ( ! BACKSQL_SUCCESS( rc ) ) {
00698               Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
00699                      "error executing attribute query \"%s\"\n",
00700                      at->bam_query, 0, 0 );
00701               backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
00702               SQLFreeStmt( sth, SQL_DROP );
00703 #ifdef BACKSQL_COUNTQUERY
00704               if ( append ) {
00705                      attr_free( attr );
00706               }
00707 #endif /* BACKSQL_COUNTQUERY */
00708               return 1;
00709        }
00710 
00711        backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx );
00712 #ifdef BACKSQL_COUNTQUERY
00713        j = oldcount;
00714 #endif /* BACKSQL_COUNTQUERY */
00715        for ( rc = SQLFetch( sth ), k = 0;
00716                      BACKSQL_SUCCESS( rc );
00717                      rc = SQLFetch( sth ), k++ )
00718        {
00719               for ( i = 0; i < (unsigned long)row.ncols; i++ ) {
00720 
00721                      if ( row.value_len[ i ] > 0 ) {
00722                             struct berval        bv;
00723                             int                  retval;
00724 #ifdef BACKSQL_TRACE
00725                             AttributeDescription *ad = NULL;
00726                             const char           *text;
00727 
00728                             retval = slap_bv2ad( &row.col_names[ i ], &ad, &text );
00729                             if ( retval != LDAP_SUCCESS ) {
00730                                    Debug( LDAP_DEBUG_ANY,
00731                                           "==>backsql_get_attr_vals(\"%s\"): "
00732                                           "unable to find AttributeDescription %s "
00733                                           "in schema (%d)\n",
00734                                           bsi->bsi_e->e_name.bv_val,
00735                                           row.col_names[ i ].bv_val, retval );
00736                                    res = 1;
00737                                    goto done;
00738                             }
00739 
00740                             if ( ad != at->bam_ad ) {
00741                                    Debug( LDAP_DEBUG_ANY,
00742                                           "==>backsql_get_attr_vals(\"%s\"): "
00743                                           "column name %s differs from "
00744                                           "AttributeDescription %s\n",
00745                                           bsi->bsi_e->e_name.bv_val,
00746                                           ad->ad_cname.bv_val,
00747                                           at->bam_ad->ad_cname.bv_val );
00748                                    res = 1;
00749                                    goto done;
00750                             }
00751 #endif /* BACKSQL_TRACE */
00752 
00753                             /* ITS#3386, ITS#3113 - 20070308
00754                              * If a binary is fetched?
00755                              * must use the actual size read
00756                              * from the database.
00757                              */
00758                             if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
00759 #ifdef BACKSQL_TRACE
00760                                    Debug( LDAP_DEBUG_ANY,
00761                                           "==>backsql_get_attr_vals(\"%s\"): "
00762                                           "column name %s: data is binary; "
00763                                           "using database size %ld\n",
00764                                           bsi->bsi_e->e_name.bv_val,
00765                                           ad->ad_cname.bv_val,
00766                                           row.value_len[ i ] );
00767 #endif /* BACKSQL_TRACE */
00768                                    bv.bv_val = row.cols[ i ];
00769                                    bv.bv_len = row.value_len[ i ];
00770 
00771                             } else {
00772                                    ber_str2bv( row.cols[ i ], 0, 0, &bv );
00773                             }
00774 
00775 #ifdef BACKSQL_PRETTY_VALIDATE
00776                             if ( pretty ) {
00777                                    struct berval pbv;
00778 
00779                                    retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
00780                                           &bv, &pbv, bsi->bsi_op->o_tmpmemctx );
00781                                    bv = pbv;
00782 
00783                             } else {
00784                                    retval = validate( at->bam_true_ad->ad_type->sat_syntax,
00785                                           &bv );
00786                             }
00787 
00788                             if ( retval != LDAP_SUCCESS ) {
00789                                    char   buf[ SLAP_TEXT_BUFLEN ];
00790 
00791                                    /* FIXME: we're ignoring invalid values,
00792                                     * but we're accepting the attributes;
00793                                     * should we fail at all? */
00794                                    snprintf( buf, sizeof( buf ),
00795                                                  "unable to %s value #%lu "
00796                                                  "of AttributeDescription %s",
00797                                                  pretty ? "prettify" : "validate",
00798                                                  k - oldcount,
00799                                                  at->bam_ad->ad_cname.bv_val );
00800                                    Debug( LDAP_DEBUG_TRACE,
00801                                           "==>backsql_get_attr_vals(\"%s\"): "
00802                                           "%s (%d)\n",
00803                                           bsi->bsi_e->e_name.bv_val, buf, retval );
00804                                    continue;
00805                             }
00806 #endif /* BACKSQL_PRETTY_VALIDATE */
00807 
00808 #ifndef BACKSQL_COUNTQUERY
00809                             (void)backsql_entry_addattr( bsi->bsi_e, 
00810                                           at->bam_true_ad, &bv,
00811                                           bsi->bsi_op->o_tmpmemctx );
00812 
00813 #else /* BACKSQL_COUNTQUERY */
00814                             if ( normfunc ) {
00815                                    struct berval nbv;
00816 
00817                                    retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
00818                                           at->bam_true_ad->ad_type->sat_syntax,
00819                                           at->bam_true_ad->ad_type->sat_equality,
00820                                           &bv, &nbv,
00821                                           bsi->bsi_op->o_tmpmemctx );
00822 
00823                                    if ( retval != LDAP_SUCCESS ) {
00824                                           char   buf[ SLAP_TEXT_BUFLEN ];
00825 
00826                                           /* FIXME: we're ignoring invalid values,
00827                                            * but we're accepting the attributes;
00828                                            * should we fail at all? */
00829                                           snprintf( buf, sizeof( buf ),
00830                                                  "unable to normalize value #%lu "
00831                                                  "of AttributeDescription %s",
00832                                                  k - oldcount,
00833                                                  at->bam_ad->ad_cname.bv_val );
00834                                           Debug( LDAP_DEBUG_TRACE,
00835                                                  "==>backsql_get_attr_vals(\"%s\"): "
00836                                                  "%s (%d)\n",
00837                                                  bsi->bsi_e->e_name.bv_val, buf, retval );
00838 
00839 #ifdef BACKSQL_PRETTY_VALIDATE
00840                                           if ( pretty ) {
00841                                                  bsi->bsi_op->o_tmpfree( bv.bv_val,
00842                                                                bsi->bsi_op->o_tmpmemctx );
00843                                           }
00844 #endif /* BACKSQL_PRETTY_VALIDATE */
00845 
00846                                           continue;
00847                                    }
00848                                    ber_dupbv( &attr->a_nvals[ j ], &nbv );
00849                                    bsi->bsi_op->o_tmpfree( nbv.bv_val,
00850                                                  bsi->bsi_op->o_tmpmemctx );
00851                             }
00852 
00853                             ber_dupbv( &attr->a_vals[ j ], &bv );
00854 
00855                             assert( j < oldcount + count );
00856                             j++;
00857 #endif /* BACKSQL_COUNTQUERY */
00858 
00859 #ifdef BACKSQL_PRETTY_VALIDATE
00860                             if ( pretty ) {
00861                                    bsi->bsi_op->o_tmpfree( bv.bv_val,
00862                                                  bsi->bsi_op->o_tmpmemctx );
00863                             }
00864 #endif /* BACKSQL_PRETTY_VALIDATE */
00865 
00866 #ifdef BACKSQL_TRACE
00867                             Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
00868                                    (int)row.col_prec[ i ], 0, 0 );
00869 
00870                      } else {
00871                             Debug( LDAP_DEBUG_TRACE, "NULL value "
00872                                    "in this row for attribute \"%s\"\n",
00873                                    row.col_names[ i ].bv_val, 0, 0 );
00874 #endif /* BACKSQL_TRACE */
00875                      }
00876               }
00877        }
00878 
00879 #ifdef BACKSQL_COUNTQUERY
00880        if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) {
00881               /* don't leave around attributes with no values */
00882               attr_free( attr );
00883 
00884        } else if ( append ) {
00885               Attribute     **ap;
00886 
00887               for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next )
00888                      /* goto last */ ;
00889               *ap =  attr;
00890        }
00891 #endif /* BACKSQL_COUNTQUERY */
00892 
00893        SQLFreeStmt( sth, SQL_DROP );
00894        Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
00895 
00896        if ( at->bam_next ) {
00897               res = backsql_get_attr_vals( at->bam_next, v_bsi );
00898        } else {
00899               res = 1;
00900        }
00901 
00902 #ifdef BACKSQL_TRACE
00903 done:;
00904 #endif /* BACKSQL_TRACE */
00905        backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx );
00906 
00907        return res;
00908 }
00909 
00910 int
00911 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
00912 {
00913        Operation            *op = bsi->bsi_op;
00914        backsql_info         *bi = (backsql_info *)op->o_bd->be_private;
00915        int                  i;
00916        int                  rc;
00917 
00918        Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
00919 
00920        assert( bsi->bsi_e != NULL );
00921 
00922        memset( bsi->bsi_e, 0, sizeof( Entry ) );
00923 
00924        if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
00925               (void)entry_dup2( bsi->bsi_e, bi->sql_baseObject );
00926               goto done;
00927        }
00928 
00929        bsi->bsi_e->e_attrs = NULL;
00930        bsi->bsi_e->e_private = NULL;
00931 
00932        if ( eid->eid_oc == NULL ) {
00933               eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
00934                      eid->eid_oc_id );
00935               if ( eid->eid_oc == NULL ) {
00936                      Debug( LDAP_DEBUG_TRACE,
00937                             "backsql_id2entry(): unable to fetch objectClass with id=" BACKSQL_IDNUMFMT " for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n",
00938                             eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id),
00939                             eid->eid_dn.bv_val );
00940                      return LDAP_OTHER;
00941               }
00942        }
00943        bsi->bsi_oc = eid->eid_oc;
00944        bsi->bsi_c_eid = eid;
00945 
00946        ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
00947        ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );
00948 
00949 #ifndef BACKSQL_ARBITRARY_KEY      
00950        /* FIXME: unused */
00951        bsi->bsi_e->e_id = eid->eid_id;
00952 #endif /* ! BACKSQL_ARBITRARY_KEY */
00953  
00954        rc = attr_merge_normalize_one( bsi->bsi_e,
00955                      slap_schema.si_ad_objectClass,
00956                      &bsi->bsi_oc->bom_oc->soc_cname,
00957                      bsi->bsi_op->o_tmpmemctx );
00958        if ( rc != LDAP_SUCCESS ) {
00959               backsql_entry_clean( op, bsi->bsi_e );
00960               return rc;
00961        }
00962 
00963        if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
00964        {
00965               Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
00966                      "retrieving all attributes\n", 0, 0, 0 );
00967               avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
00968                             bsi, 0, AVL_INORDER );
00969 
00970        } else {
00971               Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
00972                      "custom attribute list\n", 0, 0, 0 );
00973               for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
00974                      backsql_at_map_rec   **vat;
00975                      AttributeName        *an = &bsi->bsi_attrs[ i ];
00976                      int                  j;
00977 
00978                      /* if one of the attributes listed here is
00979                       * a subtype of another, it must be ignored,
00980                       * because subtypes are already dealt with
00981                       * by backsql_supad2at()
00982                       */
00983                      for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
00984                             /* skip self */
00985                             if ( j == i ) {
00986                                    continue;
00987                             }
00988 
00989                             /* skip subtypes */
00990                             if ( is_at_subtype( an->an_desc->ad_type,
00991                                                  bsi->bsi_attrs[ j ].an_desc->ad_type ) )
00992                             {
00993                                    goto next;
00994                             }
00995                      }
00996 
00997                      rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
00998                      if ( rc != 0 || vat == NULL ) {
00999                             Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
01000                                           "attribute \"%s\" is not defined "
01001                                           "for objectlass \"%s\"\n",
01002                                           an->an_name.bv_val, 
01003                                           BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
01004                             continue;
01005                      }
01006 
01007                      for ( j = 0; vat[j]; j++ ) {
01008                             backsql_get_attr_vals( vat[j], bsi );
01009                      }
01010 
01011                      ch_free( vat );
01012 
01013 next:;
01014               }
01015        }
01016 
01017        if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
01018               Attribute     *a_entryUUID,
01019                             **ap;
01020 
01021               a_entryUUID = backsql_operational_entryUUID( bi, eid );
01022               if ( a_entryUUID != NULL ) {
01023                      for ( ap = &bsi->bsi_e->e_attrs; 
01024                                    *ap; 
01025                                    ap = &(*ap)->a_next );
01026 
01027                      *ap = a_entryUUID;
01028               }
01029        }
01030 
01031        if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
01032                      || an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs )
01033                      || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
01034        {
01035               ObjectClass   *soc = NULL;
01036 
01037               if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
01038                      Attribute     *a;
01039                      const char    *text = NULL;
01040                      char          textbuf[ 1024 ];
01041                      size_t        textlen = sizeof( textbuf );
01042                      struct berval bv[ 2 ],
01043                                    *nvals;
01044                      int           rc = LDAP_SUCCESS;
01045 
01046                      a = attr_find( bsi->bsi_e->e_attrs,
01047                                    slap_schema.si_ad_objectClass );
01048                      if ( a != NULL ) {
01049                             nvals = a->a_nvals;
01050 
01051                      } else {
01052                             bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
01053                             BER_BVZERO( &bv[ 1 ] );
01054                             nvals = bv;
01055                      }
01056 
01057                      rc = structural_class( nvals, &soc, NULL, 
01058                                    &text, textbuf, textlen, op->o_tmpmemctx );
01059                      if ( rc != LDAP_SUCCESS ) {
01060                             Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
01061                                    "structural_class() failed %d (%s)\n",
01062                                    bsi->bsi_e->e_name.bv_val,
01063                                    rc, text ? text : "" );
01064                             backsql_entry_clean( op, bsi->bsi_e );
01065                             return rc;
01066                      }
01067 
01068                      if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
01069                             if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
01070                                    Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
01071                                           "computed structuralObjectClass %s "
01072                                           "does not match objectClass %s associated "
01073                                           "to entry\n",
01074                                           bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
01075                                           bsi->bsi_oc->bom_oc->soc_cname.bv_val );
01076                                    backsql_entry_clean( op, bsi->bsi_e );
01077                                    return rc;
01078                             }
01079 
01080                             Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
01081                                    "computed structuralObjectClass %s "
01082                                    "is subclass of objectClass %s associated "
01083                                    "to entry\n",
01084                                    bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
01085                                    bsi->bsi_oc->bom_oc->soc_cname.bv_val );
01086                      }
01087 
01088               } else {
01089                      soc = bsi->bsi_oc->bom_oc;
01090               }
01091 
01092               rc = attr_merge_normalize_one( bsi->bsi_e,
01093                             slap_schema.si_ad_structuralObjectClass,
01094                             &soc->soc_cname,
01095                             bsi->bsi_op->o_tmpmemctx );
01096               if ( rc != LDAP_SUCCESS ) {
01097                      backsql_entry_clean( op, bsi->bsi_e );
01098                      return rc;
01099               }
01100        }
01101 
01102 done:;
01103        Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
01104 
01105        return LDAP_SUCCESS;
01106 }
01107