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