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