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