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