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