]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/entry-id.c
fix couple of bugs in recent 'disclose' commits; prepare for sending matchedDN when...
[openldap] / servers / slapd / back-sql / entry-id.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1999-2005 The OpenLDAP Foundation.
5  * Portions Copyright 1999 Dmitry Kovalev.
6  * Portions Copyright 2002 Pierangelo Masarati.
7  * Portions Copyright 2004 Mark Adamson.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by Dmitry Kovalev for inclusion
20  * by OpenLDAP Software.  Additional significant contributors include
21  * Pierangelo Masarati and Mark Adamson.
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include "ac/string.h"
29
30 #include "slap.h"
31 #include "proto-sql.h"
32
33 #ifdef BACKSQL_ARBITRARY_KEY
34 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
35 #endif /* BACKSQL_ARBITRARY_KEY */
36
37 backsql_entryID *
38 backsql_free_entryID( backsql_entryID *id, int freeit )
39 {
40         backsql_entryID         *next;
41
42         assert( id );
43
44         next = id->eid_next;
45
46         if ( !BER_BVISNULL( &id->eid_ndn ) ) {
47                 if ( !BER_BVISNULL( &id->eid_dn )
48                                 && id->eid_dn.bv_val != id->eid_ndn.bv_val )
49                 {
50                         free( id->eid_dn.bv_val );
51                         BER_BVZERO( &id->eid_dn );
52                 }
53
54                 free( id->eid_ndn.bv_val );
55                 BER_BVZERO( &id->eid_ndn );
56         }
57
58 #ifdef BACKSQL_ARBITRARY_KEY
59         if ( id->eid_id.bv_val ) {
60                 free( id->eid_id.bv_val );
61                 BER_BVZERO( &id->eid_id );
62         }
63
64         if ( id->eid_keyval.bv_val ) {
65                 free( id->eid_keyval.bv_val );
66                 BER_BVZERO( &id->eid_keyval );
67         }
68 #endif /* BACKSQL_ARBITRARY_KEY */
69
70         if ( freeit ) {
71                 free( id );
72         }
73
74         return next;
75 }
76
77 /*
78  * NOTE: the dn must be normalized
79  */
80 int
81 backsql_dn2id(
82         Operation               *op,
83         SlapReply               *rs,
84         SQLHDBC                 dbh,
85         struct berval           *ndn,
86         backsql_entryID         *id,
87         int                     matched,
88         int                     muck )
89 {
90         backsql_info            *bi = op->o_bd->be_private;
91         SQLHSTMT                sth = SQL_NULL_HSTMT; 
92         BACKSQL_ROW_NTS         row;
93         RETCODE                 rc;
94         int                     res;
95         struct berval           realndn = BER_BVNULL;
96
97         /* TimesTen */
98         char                    upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
99         struct berval           tbbDN;
100         int                     i, j;
101
102         /*
103          * NOTE: id can be NULL; in this case, the function
104          * simply checks whether the DN can be successfully 
105          * turned into an ID, returning LDAP_SUCCESS for
106          * positive cases, or the most appropriate error
107          */
108
109         Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", 
110                         ndn->bv_val, id == NULL ? " (no ID expected)" : "",
111                         matched ? " matched expected" : "" );
112
113         if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
114                 Debug( LDAP_DEBUG_TRACE, 
115                         "   backsql_dn2id(\"%s\"): DN length=%ld "
116                         "exceeds max DN length %d:\n",
117                         ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
118                 return LDAP_OTHER;
119         }
120
121         /* return baseObject if available and matches */
122         /* FIXME: if ndn is already mucked, we cannot check this */
123         if ( bi->sql_baseObject != NULL &&
124                         dn_match( ndn, &bi->sql_baseObject->e_nname ) )
125         {
126                 if ( id != NULL ) {
127 #ifdef BACKSQL_ARBITRARY_KEY
128                         ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
129                         ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
130 #else /* ! BACKSQL_ARBITRARY_KEY */
131                         id->eid_id = BACKSQL_BASEOBJECT_ID;
132                         id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
133 #endif /* ! BACKSQL_ARBITRARY_KEY */
134                         id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
135
136                         ber_dupbv( &id->eid_ndn, &bi->sql_baseObject->e_nname );
137                         ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_name );
138
139                         id->eid_next = NULL;
140                 }
141
142                 return LDAP_SUCCESS;
143         }
144         
145         /* begin TimesTen */
146         Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): id_query \"%s\"\n",
147                         ndn->bv_val, bi->sql_id_query, 0 );
148         assert( bi->sql_id_query );
149         rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
150         if ( rc != SQL_SUCCESS ) {
151                 Debug( LDAP_DEBUG_TRACE, 
152                         "   backsql_dn2id(\"%s\"): "
153                         "error preparing SQL:\n   %s", 
154                         ndn->bv_val, bi->sql_id_query, 0 );
155                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
156                 res = LDAP_OTHER;
157                 goto done;
158         }
159
160         realndn = *ndn;
161         if ( muck ) {
162                 if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
163                         Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
164                                 "backsql_api_dn2odbc(\"%s\") failed\n", 
165                                 ndn->bv_val, realndn.bv_val, 0 );
166                         res = LDAP_OTHER;
167                         goto done;
168                 }
169         }
170
171         if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
172                 /*
173                  * Prepare an upper cased, byte reversed version 
174                  * that can be searched using indexes
175                  */
176
177                 for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
178                 {
179                         upperdn[ i ] = realndn.bv_val[ j ];
180                 }
181                 upperdn[ i ] = '\0';
182                 ldap_pvt_str2upper( upperdn );
183
184                 Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
185                                 "upperdn=\"%s\"\n",
186                                 ndn->bv_val, upperdn, 0 );
187                 ber_str2bv( upperdn, 0, 0, &tbbDN );
188
189         } else {
190                 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
191                         AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
192                         ldap_pvt_str2upper( upperdn );
193                         Debug( LDAP_DEBUG_TRACE,
194                                 "   backsql_dn2id(\"%s\"): "
195                                 "upperdn=\"%s\"\n",
196                                 ndn->bv_val, upperdn, 0 );
197                         ber_str2bv( upperdn, 0, 0, &tbbDN );
198
199                 } else {
200                         tbbDN = realndn;
201                 }
202         }
203
204         rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
205         if ( rc != SQL_SUCCESS) {
206                 /* end TimesTen */ 
207                 Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
208                         "error binding dn=\"%s\" parameter:\n", 
209                         ndn->bv_val, tbbDN.bv_val, 0 );
210                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
211                 res = LDAP_OTHER;
212                 goto done;
213         }
214
215         rc = SQLExecute( sth );
216         if ( rc != SQL_SUCCESS ) {
217                 Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
218                         "error executing query (\"%s\", \"%s\"):\n", 
219                         ndn->bv_val, bi->sql_id_query, tbbDN.bv_val );
220                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
221                 res = LDAP_OTHER;
222                 goto done;
223         }
224
225         backsql_BindRowAsStrings( sth, &row );
226         rc = SQLFetch( sth );
227         if ( BACKSQL_SUCCESS( rc ) ) {
228                 char    buf[ SLAP_TEXT_BUFLEN ];
229
230 #ifdef LDAP_DEBUG
231                 snprintf( buf, sizeof(buf),
232                         "id=%s keyval=%s oc_id=%s dn=%s",
233                         row.cols[ 0 ], row.cols[ 1 ],
234                         row.cols[ 2 ], row.cols[ 3 ] );
235                 Debug( LDAP_DEBUG_TRACE,
236                         "   backsql_dn2id(\"%s\"): %s\n",
237                         ndn->bv_val, buf, 0 );
238 #endif /* LDAP_DEBUG */
239
240                 res = LDAP_SUCCESS;
241                 if ( id != NULL ) {
242                         struct berval   dn;
243
244 #ifdef BACKSQL_ARBITRARY_KEY
245                         ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
246                         ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
247 #else /* ! BACKSQL_ARBITRARY_KEY */
248                         id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
249                         id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
250 #endif /* ! BACKSQL_ARBITRARY_KEY */
251                         id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
252
253                         ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
254
255                         if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
256                                 res = LDAP_OTHER;
257
258                         } else {
259                                 res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, NULL );
260                                 if ( res != LDAP_SUCCESS ) {
261                                         Debug( LDAP_DEBUG_TRACE,
262                                                 "   backsql_dn2id(\"%s\"): "
263                                                 "dnPrettyNormal failed (%d: %s)\n",
264                                                 realndn.bv_val, res,
265                                                 ldap_err2string( res ) );
266
267                                         /* cleanup... */
268                                         (void)backsql_free_entryID( id, 0 );
269                                 }
270
271                                 if ( dn.bv_val != row.cols[ 3 ] ) {
272                                         free( dn.bv_val );
273                                 }
274                         }
275
276                         id->eid_next = NULL;
277                 }
278
279         } else {
280                 res = LDAP_NO_SUCH_OBJECT;
281         }
282         backsql_FreeRow( &row );
283
284 done:;
285         Debug( LDAP_DEBUG_TRACE,
286                 "<==backsql_dn2id(\"%s\"): err=%d\n",
287                 ndn->bv_val, res, 0 );
288         if ( sth != SQL_NULL_HSTMT ) {
289                 SQLFreeStmt( sth, SQL_DROP );
290         }
291
292         if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
293                 ch_free( realndn.bv_val );
294         }
295
296         return res;
297 }
298
299 int
300 backsql_count_children(
301         backsql_info            *bi,
302         SQLHDBC                 dbh,
303         struct berval           *dn,
304         unsigned long           *nchildren )
305 {
306         SQLHSTMT                sth = SQL_NULL_HSTMT;
307         BACKSQL_ROW_NTS         row;
308         RETCODE                 rc;
309         int                     res = LDAP_SUCCESS;
310
311         Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n", 
312                         dn->bv_val, 0, 0 );
313
314         if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
315                 Debug( LDAP_DEBUG_TRACE, 
316                         "backsql_count_children(): DN \"%s\" (%ld bytes) "
317                         "exceeds max DN length (%d):\n",
318                         dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
319                 return LDAP_OTHER;
320         }
321         
322         /* begin TimesTen */
323         Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n", 
324                         bi->sql_has_children_query, 0, 0);
325         assert( bi->sql_has_children_query );
326         rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
327         if ( rc != SQL_SUCCESS ) {
328                 Debug( LDAP_DEBUG_TRACE, 
329                         "backsql_count_children(): error preparing SQL:\n%s", 
330                         bi->sql_has_children_query, 0, 0);
331                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
332                 SQLFreeStmt( sth, SQL_DROP );
333                 return LDAP_OTHER;
334         }
335
336         rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
337         if ( rc != SQL_SUCCESS) {
338                 /* end TimesTen */ 
339                 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
340                         "error binding dn=\"%s\" parameter:\n", 
341                         dn->bv_val, 0, 0 );
342                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
343                 SQLFreeStmt( sth, SQL_DROP );
344                 return LDAP_OTHER;
345         }
346
347         rc = SQLExecute( sth );
348         if ( rc != SQL_SUCCESS ) {
349                 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
350                         "error executing query (\"%s\", \"%s\"):\n", 
351                         bi->sql_has_children_query, dn->bv_val, 0 );
352                 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
353                 SQLFreeStmt( sth, SQL_DROP );
354                 return LDAP_OTHER;
355         }
356
357         backsql_BindRowAsStrings( sth, &row );
358         
359         rc = SQLFetch( sth );
360         if ( BACKSQL_SUCCESS( rc ) ) {
361                 char *end;
362
363                 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
364                 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
365                         /* FIXME: braindead RDBMSes return
366                          * a fractional number from COUNT!
367                          */
368                         res = LDAP_OTHER;
369                 }
370
371         } else {
372                 res = LDAP_OTHER;
373         }
374         backsql_FreeRow( &row );
375
376         SQLFreeStmt( sth, SQL_DROP );
377
378         Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
379                         *nchildren, 0, 0 );
380
381         return res;
382 }
383
384 int
385 backsql_has_children(
386         backsql_info            *bi,
387         SQLHDBC                 dbh,
388         struct berval           *dn )
389 {
390         unsigned long   nchildren;
391         int             rc;
392
393         rc = backsql_count_children( bi, dbh, dn, &nchildren );
394
395         if ( rc == LDAP_SUCCESS ) {
396                 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
397         }
398
399         return rc;
400 }
401
402 static int
403 backsql_get_attr_vals( void *v_at, void *v_bsi )
404 {
405         backsql_at_map_rec      *at = v_at;
406         backsql_srch_info       *bsi = v_bsi;
407         backsql_info            *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
408         RETCODE                 rc;
409         SQLHSTMT                sth = SQL_NULL_HSTMT;
410         BACKSQL_ROW_NTS         row;
411         int                     i;
412
413         assert( at );
414         assert( bsi );
415
416 #ifdef BACKSQL_ARBITRARY_KEY
417         Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
418                 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
419                 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
420                 bsi->bsi_c_eid->eid_keyval.bv_val );
421 #else /* ! BACKSQL_ARBITRARY_KEY */
422         Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
423                 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
424                 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
425                 bsi->bsi_c_eid->eid_keyval );
426 #endif /* ! BACKSQL_ARBITRARY_KEY */
427
428         rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
429         if ( rc != SQL_SUCCESS ) {
430                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
431                         "error preparing query: %s\n", at->bam_query, 0, 0 );
432                 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
433                 return 1;
434         }
435
436         rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
437                         &bsi->bsi_c_eid->eid_keyval );
438         if ( rc != SQL_SUCCESS ) {
439                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
440                         "error binding key value parameter\n", 0, 0, 0 );
441                 return 1;
442         }
443
444 #ifdef BACKSQL_TRACE
445 #ifdef BACKSQL_ARBITRARY_KEY
446         Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
447                 "query=\"%s\" keyval=%s\n", at->bam_query,
448                 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
449 #else /* !BACKSQL_ARBITRARY_KEY */
450         Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
451                 "query=\"%s\" keyval=%d\n", at->bam_query,
452                 bsi->bsi_c_eid->eid_keyval, 0 );
453 #endif /* ! BACKSQL_ARBITRARY_KEY */
454 #endif /* BACKSQL_TRACE */
455
456         rc = SQLExecute( sth );
457         if ( ! BACKSQL_SUCCESS( rc ) ) {
458                 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
459                         "error executing attribute query \"%s\"\n",
460                         at->bam_query, 0, 0 );
461                 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
462                 SQLFreeStmt( sth, SQL_DROP );
463                 return 1;
464         }
465
466         backsql_BindRowAsStrings( sth, &row );
467
468         rc = SQLFetch( sth );
469         for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
470                 for ( i = 0; i < row.ncols; i++ ) {
471                         if ( row.value_len[ i ] > 0 ) {
472                                 struct berval   bv;
473
474                                 bv.bv_val = row.cols[ i ];
475 #if 0
476                                 bv.bv_len = row.col_prec[ i ];
477 #else
478                                 /*
479                                  * FIXME: what if a binary 
480                                  * is fetched?
481                                  */
482                                 bv.bv_len = strlen( row.cols[ i ] );
483 #endif
484                                 backsql_entry_addattr( bsi->bsi_e, 
485                                                 &row.col_names[ i ], &bv,
486                                                 bsi->bsi_op->o_tmpmemctx );
487
488 #ifdef BACKSQL_TRACE
489                                 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
490                                         (int)row.col_prec[ i ], 0, 0 );
491                         } else {
492                                 Debug( LDAP_DEBUG_TRACE, "NULL value "
493                                         "in this row for attribute \"%s\"\n",
494                                         row.col_names[ i ].bv_val, 0, 0 );
495 #endif /* BACKSQL_TRACE */
496                         }
497                 }
498         }
499
500         backsql_FreeRow( &row );
501         SQLFreeStmt( sth, SQL_DROP );
502         Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
503
504         if ( at->bam_next ) {
505                 return backsql_get_attr_vals( at->bam_next, v_bsi );
506         }
507
508         return 1;
509 }
510
511 int
512 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
513 {
514         backsql_info            *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
515         int                     i;
516         int                     rc;
517
518         Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
519
520         assert( bsi->bsi_e );
521
522         memset( bsi->bsi_e, 0, sizeof( Entry ) );
523
524         if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
525                 Entry   *e;
526
527                 e = entry_dup( bi->sql_baseObject );
528                 if ( e == NULL ) {
529                         return LDAP_NO_MEMORY;
530                 }
531                         
532                 *bsi->bsi_e = *e;
533                 free( e );
534                 goto done;
535         }
536
537         ber_dupbv( &bsi->bsi_e->e_name, &eid->eid_dn );
538         ber_dupbv( &bsi->bsi_e->e_nname, &eid->eid_ndn );
539
540         bsi->bsi_e->e_attrs = NULL;
541         bsi->bsi_e->e_private = NULL;
542
543         bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
544                         eid->eid_oc_id );
545         bsi->bsi_c_eid = eid;
546
547 #ifndef BACKSQL_ARBITRARY_KEY   
548         bsi->bsi_e->e_id = eid->eid_id;
549 #endif /* ! BACKSQL_ARBITRARY_KEY */
550  
551         rc = attr_merge_normalize_one( bsi->bsi_e,
552                         slap_schema.si_ad_objectClass,
553                         &bsi->bsi_oc->bom_oc->soc_cname,
554                         bsi->bsi_op->o_tmpmemctx );
555         if ( rc != LDAP_SUCCESS ) {
556                 entry_clean( bsi->bsi_e );
557                 return rc;
558         }
559
560         if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
561         {
562                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
563                         "retrieving all attributes\n", 0, 0, 0 );
564                 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
565                                 bsi, 0, AVL_INORDER );
566
567         } else {
568                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
569                         "custom attribute list\n", 0, 0, 0 );
570                 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
571                         backsql_at_map_rec      **vat;
572                         AttributeName           *an = &bsi->bsi_attrs[ i ];
573                         int                     j;
574
575                         /* if one of the attributes listed here is
576                          * a subtype of another, it must be ignored,
577                          * because subtypes are already dealt with
578                          * by backsql_supad2at()
579                          */
580                         for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
581                                 /* skip self */
582                                 if ( j == i ) {
583                                         continue;
584                                 }
585
586                                 /* skip subtypes */
587                                 if ( is_at_subtype( an->an_desc->ad_type,
588                                                         bsi->bsi_attrs[ j ].an_desc->ad_type ) )
589                                 {
590                                         goto next;
591                                 }
592                         }
593
594                         rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
595                         if ( rc != 0 || vat == NULL ) {
596                                 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
597                                                 "attribute \"%s\" is not defined "
598                                                 "for objectlass \"%s\"\n",
599                                                 an->an_name.bv_val, 
600                                                 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
601                                 continue;
602                         }
603
604                         for ( j = 0; vat[j]; j++ ) {
605                                 backsql_get_attr_vals( vat[j], bsi );
606                         }
607
608                         ch_free( vat );
609
610 next:;
611                 }
612         }
613
614         if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
615                 Attribute       *a_entryUUID,
616                                 **ap;
617
618                 a_entryUUID = backsql_operational_entryUUID( bi, eid );
619                 if ( a_entryUUID != NULL ) {
620                         for ( ap = &bsi->bsi_e->e_attrs; 
621                                         *ap; 
622                                         ap = &(*ap)->a_next );
623
624                         *ap = a_entryUUID;
625                 }
626         }
627
628         if ( global_schemacheck ) {
629                 const char      *text = NULL;
630                 char            textbuf[ 1024 ];
631                 size_t          textlen = sizeof( textbuf );
632                 struct berval   bv[ 2 ];
633                 struct berval   soc;
634                 int rc;
635
636                 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
637                 BER_BVZERO( &bv[ 1 ] );
638
639                 rc = structural_class( bv, &soc, NULL, 
640                                 &text, textbuf, textlen );
641                 if ( rc != LDAP_SUCCESS ) {
642                         Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
643                                 "structural_class() failed %d (%s)\n",
644                                 bsi->bsi_e->e_name.bv_val,
645                                 rc, text ? text : "" );
646                         entry_clean( bsi->bsi_e );
647                         return rc;
648                 }
649
650                 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
651                                 || an_find( bsi->bsi_attrs, &AllOper )
652                                 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
653                 {
654                         rc = attr_merge_normalize_one( bsi->bsi_e,
655                                         slap_schema.si_ad_structuralObjectClass,
656                                         &soc, bsi->bsi_op->o_tmpmemctx );
657                         if ( rc != LDAP_SUCCESS ) {
658                                 entry_clean( bsi->bsi_e );
659                                 return rc;
660                         }
661                 }
662         }
663
664 done:;
665         Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
666
667         return LDAP_SUCCESS;
668 }
669