Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / openldap / dist / servers / slapd / back-sql / entry-id.c
blob2c02cd8ac7a98bb0cf1b90d4612ecc493f223409
1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-sql/entry-id.c,v 1.67.2.6 2008/02/11 23:26:48 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2008 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * Portions Copyright 2004 Mark Adamson.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
18 /* ACKNOWLEDGEMENTS:
19 * This work was initially developed by Dmitry Kovalev for inclusion
20 * by OpenLDAP Software. Additional significant contributors include
21 * Pierangelo Masarati and Mark Adamson.
24 #include "portable.h"
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include "ac/string.h"
30 #include "lutil.h"
31 #include "slap.h"
32 #include "proto-sql.h"
34 #ifdef BACKSQL_ARBITRARY_KEY
35 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
36 #endif /* BACKSQL_ARBITRARY_KEY */
38 backsql_entryID *
39 backsql_entryID_dup( backsql_entryID *src, void *ctx )
41 backsql_entryID *dst;
43 if ( src == NULL ) return NULL;
45 dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
46 ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
47 if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
48 dst->eid_dn = dst->eid_ndn;
49 } else {
50 ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
53 #ifdef BACKSQL_ARBITRARY_KEY
54 ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
55 ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
56 #else /* ! BACKSQL_ARBITRARY_KEY */
57 dst->eid_id = src->eid_id;
58 dst->eid_keyval = src->eid_keyval;
59 #endif /* ! BACKSQL_ARBITRARY_KEY */
61 dst->eid_oc = src->eid_oc;
62 dst->eid_oc_id = src->eid_oc_id;
64 return dst;
67 backsql_entryID *
68 backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
70 backsql_entryID *next;
72 assert( id != NULL );
74 next = id->eid_next;
76 if ( !BER_BVISNULL( &id->eid_ndn ) ) {
77 if ( !BER_BVISNULL( &id->eid_dn )
78 && id->eid_dn.bv_val != id->eid_ndn.bv_val )
80 slap_sl_free( id->eid_dn.bv_val, ctx );
81 BER_BVZERO( &id->eid_dn );
84 slap_sl_free( id->eid_ndn.bv_val, ctx );
85 BER_BVZERO( &id->eid_ndn );
88 #ifdef BACKSQL_ARBITRARY_KEY
89 if ( !BER_BVISNULL( &id->eid_id ) ) {
90 slap_sl_free( id->eid_id.bv_val, ctx );
91 BER_BVZERO( &id->eid_id );
94 if ( !BER_BVISNULL( &id->eid_keyval ) ) {
95 slap_sl_free( id->eid_keyval.bv_val, ctx );
96 BER_BVZERO( &id->eid_keyval );
98 #endif /* BACKSQL_ARBITRARY_KEY */
100 if ( freeit ) {
101 slap_sl_free( id, ctx );
104 return next;
108 * NOTE: the dn must be normalized
111 backsql_dn2id(
112 Operation *op,
113 SlapReply *rs,
114 SQLHDBC dbh,
115 struct berval *ndn,
116 backsql_entryID *id,
117 int matched,
118 int muck )
120 backsql_info *bi = op->o_bd->be_private;
121 SQLHSTMT sth = SQL_NULL_HSTMT;
122 BACKSQL_ROW_NTS row = { 0 };
123 RETCODE rc;
124 int res;
125 struct berval realndn = BER_BVNULL;
127 /* TimesTen */
128 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
129 struct berval tbbDN;
130 int i, j;
133 * NOTE: id can be NULL; in this case, the function
134 * simply checks whether the DN can be successfully
135 * turned into an ID, returning LDAP_SUCCESS for
136 * positive cases, or the most appropriate error
139 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n",
140 ndn->bv_val, id == NULL ? " (no ID expected)" : "",
141 matched ? " matched expected" : "" );
143 if ( id ) {
144 /* NOTE: trap inconsistencies */
145 assert( BER_BVISNULL( &id->eid_ndn ) );
148 if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
149 Debug( LDAP_DEBUG_TRACE,
150 " backsql_dn2id(\"%s\"): DN length=%ld "
151 "exceeds max DN length %d:\n",
152 ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
153 return LDAP_OTHER;
156 /* return baseObject if available and matches */
157 /* FIXME: if ndn is already mucked, we cannot check this */
158 if ( bi->sql_baseObject != NULL &&
159 dn_match( ndn, &bi->sql_baseObject->e_nname ) )
161 if ( id != NULL ) {
162 #ifdef BACKSQL_ARBITRARY_KEY
163 ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv,
164 op->o_tmpmemctx );
165 ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv,
166 op->o_tmpmemctx );
167 #else /* ! BACKSQL_ARBITRARY_KEY */
168 id->eid_id = BACKSQL_BASEOBJECT_ID;
169 id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
170 #endif /* ! BACKSQL_ARBITRARY_KEY */
171 id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
173 ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname,
174 op->o_tmpmemctx );
175 ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name,
176 op->o_tmpmemctx );
178 id->eid_next = NULL;
181 return LDAP_SUCCESS;
184 /* begin TimesTen */
185 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): id_query \"%s\"\n",
186 ndn->bv_val, bi->sql_id_query, 0 );
187 assert( bi->sql_id_query != NULL );
188 rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
189 if ( rc != SQL_SUCCESS ) {
190 Debug( LDAP_DEBUG_TRACE,
191 " backsql_dn2id(\"%s\"): "
192 "error preparing SQL:\n %s",
193 ndn->bv_val, bi->sql_id_query, 0 );
194 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
195 res = LDAP_OTHER;
196 goto done;
199 realndn = *ndn;
200 if ( muck ) {
201 if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
202 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
203 "backsql_api_dn2odbc(\"%s\") failed\n",
204 ndn->bv_val, realndn.bv_val, 0 );
205 res = LDAP_OTHER;
206 goto done;
210 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
212 * Prepare an upper cased, byte reversed version
213 * that can be searched using indexes
216 for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
218 upperdn[ i ] = realndn.bv_val[ j ];
220 upperdn[ i ] = '\0';
221 ldap_pvt_str2upper( upperdn );
223 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
224 "upperdn=\"%s\"\n",
225 ndn->bv_val, upperdn, 0 );
226 ber_str2bv( upperdn, 0, 0, &tbbDN );
228 } else {
229 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
230 AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
231 ldap_pvt_str2upper( upperdn );
232 Debug( LDAP_DEBUG_TRACE,
233 " backsql_dn2id(\"%s\"): "
234 "upperdn=\"%s\"\n",
235 ndn->bv_val, upperdn, 0 );
236 ber_str2bv( upperdn, 0, 0, &tbbDN );
238 } else {
239 tbbDN = realndn;
243 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
244 if ( rc != SQL_SUCCESS) {
245 /* end TimesTen */
246 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
247 "error binding dn=\"%s\" parameter:\n",
248 ndn->bv_val, tbbDN.bv_val, 0 );
249 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
250 res = LDAP_OTHER;
251 goto done;
254 rc = SQLExecute( sth );
255 if ( rc != SQL_SUCCESS ) {
256 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
257 "error executing query (\"%s\", \"%s\"):\n",
258 ndn->bv_val, bi->sql_id_query, tbbDN.bv_val );
259 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
260 res = LDAP_OTHER;
261 goto done;
264 backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
265 rc = SQLFetch( sth );
266 if ( BACKSQL_SUCCESS( rc ) ) {
267 char buf[ SLAP_TEXT_BUFLEN ];
269 #ifdef LDAP_DEBUG
270 snprintf( buf, sizeof(buf),
271 "id=%s keyval=%s oc_id=%s dn=%s",
272 row.cols[ 0 ], row.cols[ 1 ],
273 row.cols[ 2 ], row.cols[ 3 ] );
274 Debug( LDAP_DEBUG_TRACE,
275 " backsql_dn2id(\"%s\"): %s\n",
276 ndn->bv_val, buf, 0 );
277 #endif /* LDAP_DEBUG */
279 res = LDAP_SUCCESS;
280 if ( id != NULL ) {
281 struct berval dn;
283 id->eid_next = NULL;
285 #ifdef BACKSQL_ARBITRARY_KEY
286 ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id,
287 op->o_tmpmemctx );
288 ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval,
289 op->o_tmpmemctx );
290 #else /* ! BACKSQL_ARBITRARY_KEY */
291 if ( lutil_atoulx( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) {
292 res = LDAP_OTHER;
293 goto done;
295 if ( lutil_atoulx( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) {
296 res = LDAP_OTHER;
297 goto done;
299 #endif /* ! BACKSQL_ARBITRARY_KEY */
300 if ( lutil_atoulx( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) {
301 res = LDAP_OTHER;
302 goto done;
305 ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
307 if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
308 res = LDAP_OTHER;
309 goto done;
312 res = dnPrettyNormal( NULL, &dn,
313 &id->eid_dn, &id->eid_ndn,
314 op->o_tmpmemctx );
315 if ( res != LDAP_SUCCESS ) {
316 Debug( LDAP_DEBUG_TRACE,
317 " backsql_dn2id(\"%s\"): "
318 "dnPrettyNormal failed (%d: %s)\n",
319 realndn.bv_val, res,
320 ldap_err2string( res ) );
322 /* cleanup... */
323 (void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
326 if ( dn.bv_val != row.cols[ 3 ] ) {
327 free( dn.bv_val );
331 } else {
332 res = LDAP_NO_SUCH_OBJECT;
333 if ( matched ) {
334 struct berval pdn = *ndn;
337 * Look for matched
339 rs->sr_matched = NULL;
340 while ( !be_issuffix( op->o_bd, &pdn ) ) {
341 char *matchedDN = NULL;
343 dnParent( &pdn, &pdn );
346 * Empty DN ("") defaults to LDAP_SUCCESS
348 rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 );
349 switch ( rs->sr_err ) {
350 case LDAP_NO_SUCH_OBJECT:
351 /* try another one */
352 break;
354 case LDAP_SUCCESS:
355 matchedDN = pdn.bv_val;
356 /* fail over to next case */
358 default:
359 rs->sr_err = LDAP_NO_SUCH_OBJECT;
360 rs->sr_matched = matchedDN;
361 goto done;
367 done:;
368 backsql_FreeRow_x( &row, op->o_tmpmemctx );
370 Debug( LDAP_DEBUG_TRACE,
371 "<==backsql_dn2id(\"%s\"): err=%d\n",
372 ndn->bv_val, res, 0 );
373 if ( sth != SQL_NULL_HSTMT ) {
374 SQLFreeStmt( sth, SQL_DROP );
377 if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
378 ch_free( realndn.bv_val );
381 return res;
385 backsql_count_children(
386 Operation *op,
387 SQLHDBC dbh,
388 struct berval *dn,
389 unsigned long *nchildren )
391 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
392 SQLHSTMT sth = SQL_NULL_HSTMT;
393 BACKSQL_ROW_NTS row;
394 RETCODE rc;
395 int res = LDAP_SUCCESS;
397 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
398 dn->bv_val, 0, 0 );
400 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
401 Debug( LDAP_DEBUG_TRACE,
402 "backsql_count_children(): DN \"%s\" (%ld bytes) "
403 "exceeds max DN length (%d):\n",
404 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
405 return LDAP_OTHER;
408 /* begin TimesTen */
409 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
410 bi->sql_has_children_query, 0, 0);
411 assert( bi->sql_has_children_query != NULL );
412 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
413 if ( rc != SQL_SUCCESS ) {
414 Debug( LDAP_DEBUG_TRACE,
415 "backsql_count_children(): error preparing SQL:\n%s",
416 bi->sql_has_children_query, 0, 0);
417 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
418 SQLFreeStmt( sth, SQL_DROP );
419 return LDAP_OTHER;
422 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
423 if ( rc != SQL_SUCCESS) {
424 /* end TimesTen */
425 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
426 "error binding dn=\"%s\" parameter:\n",
427 dn->bv_val, 0, 0 );
428 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
429 SQLFreeStmt( sth, SQL_DROP );
430 return LDAP_OTHER;
433 rc = SQLExecute( sth );
434 if ( rc != SQL_SUCCESS ) {
435 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
436 "error executing query (\"%s\", \"%s\"):\n",
437 bi->sql_has_children_query, dn->bv_val, 0 );
438 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
439 SQLFreeStmt( sth, SQL_DROP );
440 return LDAP_OTHER;
443 backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
445 rc = SQLFetch( sth );
446 if ( BACKSQL_SUCCESS( rc ) ) {
447 char *end;
449 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
450 if ( end == row.cols[ 0 ] ) {
451 res = LDAP_OTHER;
453 } else {
454 switch ( end[ 0 ] ) {
455 case '\0':
456 break;
458 case '.': {
459 unsigned long ul;
461 /* FIXME: braindead RDBMSes return
462 * a fractional number from COUNT!
464 if ( lutil_atoul( &ul, end + 1 ) != 0 || ul != 0 ) {
465 res = LDAP_OTHER;
467 } break;
469 default:
470 res = LDAP_OTHER;
474 } else {
475 res = LDAP_OTHER;
477 backsql_FreeRow_x( &row, op->o_tmpmemctx );
479 SQLFreeStmt( sth, SQL_DROP );
481 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
482 *nchildren, 0, 0 );
484 return res;
488 backsql_has_children(
489 Operation *op,
490 SQLHDBC dbh,
491 struct berval *dn )
493 unsigned long nchildren;
494 int rc;
496 rc = backsql_count_children( op, dbh, dn, &nchildren );
498 if ( rc == LDAP_SUCCESS ) {
499 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
502 return rc;
505 static int
506 backsql_get_attr_vals( void *v_at, void *v_bsi )
508 backsql_at_map_rec *at = v_at;
509 backsql_srch_info *bsi = v_bsi;
510 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
511 RETCODE rc;
512 SQLHSTMT sth = SQL_NULL_HSTMT;
513 BACKSQL_ROW_NTS row;
514 unsigned long i,
515 k = 0,
516 oldcount = 0,
517 res = 0;
518 #ifdef BACKSQL_COUNTQUERY
519 unsigned count,
521 append = 0;
522 SQLLEN countsize = sizeof( count );
523 Attribute *attr = NULL;
525 slap_mr_normalize_func *normfunc = NULL;
526 #endif /* BACKSQL_COUNTQUERY */
527 #ifdef BACKSQL_PRETTY_VALIDATE
528 slap_syntax_validate_func *validate = NULL;
529 slap_syntax_transform_func *pretty = NULL;
530 #endif /* BACKSQL_PRETTY_VALIDATE */
532 assert( at != NULL );
533 assert( bsi != NULL );
535 #ifdef BACKSQL_ARBITRARY_KEY
536 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
537 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
538 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
539 bsi->bsi_c_eid->eid_keyval.bv_val );
540 #else /* ! BACKSQL_ARBITRARY_KEY */
541 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
542 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
543 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
544 bsi->bsi_c_eid->eid_keyval );
545 #endif /* ! BACKSQL_ARBITRARY_KEY */
547 #ifdef BACKSQL_PRETTY_VALIDATE
548 validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
549 pretty = at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
551 if ( validate == NULL && pretty == NULL ) {
552 return 1;
554 #endif /* BACKSQL_PRETTY_VALIDATE */
556 #ifdef BACKSQL_COUNTQUERY
557 if ( at->bam_true_ad->ad_type->sat_equality ) {
558 normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
561 /* Count how many rows will be returned. This avoids memory
562 * fragmentation that can result from loading the values in
563 * one by one and using realloc()
565 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 );
566 if ( rc != SQL_SUCCESS ) {
567 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
568 "error preparing count query: %s\n",
569 at->bam_countquery, 0, 0 );
570 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
571 return 1;
574 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
575 &bsi->bsi_c_eid->eid_keyval );
576 if ( rc != SQL_SUCCESS ) {
577 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
578 "error binding key value parameter\n", 0, 0, 0 );
579 SQLFreeStmt( sth, SQL_DROP );
580 return 1;
583 rc = SQLExecute( sth );
584 if ( ! BACKSQL_SUCCESS( rc ) ) {
585 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
586 "error executing attribute count query '%s'\n",
587 at->bam_countquery, 0, 0 );
588 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
589 SQLFreeStmt( sth, SQL_DROP );
590 return 1;
593 SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG,
594 (SQLPOINTER)&count,
595 (SQLINTEGER)sizeof( count ),
596 &countsize );
598 rc = SQLFetch( sth );
599 if ( rc != SQL_SUCCESS ) {
600 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
601 "error fetch results of count query: %s\n",
602 at->bam_countquery, 0, 0 );
603 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
604 SQLFreeStmt( sth, SQL_DROP );
605 return 1;
608 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
609 "number of values in query: %u\n", count, 0, 0 );
610 SQLFreeStmt( sth, SQL_DROP );
611 if ( count == 0 ) {
612 return 1;
615 attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
616 if ( attr != NULL ) {
617 BerVarray tmp;
619 if ( attr->a_vals != NULL ) {
620 oldcount = attr->a_numvals;
623 tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
624 if ( tmp == NULL ) {
625 return 1;
627 attr->a_vals = tmp;
628 memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
630 if ( normfunc ) {
631 tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
632 if ( tmp == NULL ) {
633 return 1;
635 attr->a_nvals = tmp;
636 memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );
638 } else {
639 attr->a_nvals = attr->a_vals;
641 attr->a_numvals += count;
643 } else {
644 append = 1;
646 /* Make space for the array of values */
647 attr = attr_alloc( at->bam_true_ad );
648 attr->a_numvals = count;
649 attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
650 if ( attr->a_vals == NULL ) {
651 Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
652 ch_free( attr );
653 return 1;
655 if ( normfunc ) {
656 attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
657 if ( attr->a_nvals == NULL ) {
658 ch_free( attr->a_vals );
659 ch_free( attr );
660 return 1;
664 } else {
665 attr->a_nvals = attr->a_vals;
668 #endif /* BACKSQL_COUNTQUERY */
670 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
671 if ( rc != SQL_SUCCESS ) {
672 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
673 "error preparing query: %s\n", at->bam_query, 0, 0 );
674 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
675 #ifdef BACKSQL_COUNTQUERY
676 if ( append ) {
677 attr_free( attr );
679 #endif /* BACKSQL_COUNTQUERY */
680 return 1;
683 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
684 &bsi->bsi_c_eid->eid_keyval );
685 if ( rc != SQL_SUCCESS ) {
686 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
687 "error binding key value parameter\n", 0, 0, 0 );
688 #ifdef BACKSQL_COUNTQUERY
689 if ( append ) {
690 attr_free( attr );
692 #endif /* BACKSQL_COUNTQUERY */
693 return 1;
696 #ifdef BACKSQL_TRACE
697 #ifdef BACKSQL_ARBITRARY_KEY
698 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
699 "query=\"%s\" keyval=%s\n", at->bam_query,
700 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
701 #else /* !BACKSQL_ARBITRARY_KEY */
702 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
703 "query=\"%s\" keyval=%d\n", at->bam_query,
704 bsi->bsi_c_eid->eid_keyval, 0 );
705 #endif /* ! BACKSQL_ARBITRARY_KEY */
706 #endif /* BACKSQL_TRACE */
708 rc = SQLExecute( sth );
709 if ( ! BACKSQL_SUCCESS( rc ) ) {
710 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
711 "error executing attribute query \"%s\"\n",
712 at->bam_query, 0, 0 );
713 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
714 SQLFreeStmt( sth, SQL_DROP );
715 #ifdef BACKSQL_COUNTQUERY
716 if ( append ) {
717 attr_free( attr );
719 #endif /* BACKSQL_COUNTQUERY */
720 return 1;
723 backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx );
724 #ifdef BACKSQL_COUNTQUERY
725 j = oldcount;
726 #endif /* BACKSQL_COUNTQUERY */
727 for ( rc = SQLFetch( sth ), k = 0;
728 BACKSQL_SUCCESS( rc );
729 rc = SQLFetch( sth ), k++ )
731 for ( i = 0; i < (unsigned long)row.ncols; i++ ) {
733 if ( row.value_len[ i ] > 0 ) {
734 struct berval bv;
735 int retval;
736 #ifdef BACKSQL_TRACE
737 AttributeDescription *ad = NULL;
738 const char *text;
740 retval = slap_bv2ad( &row.col_names[ i ], &ad, &text );
741 if ( retval != LDAP_SUCCESS ) {
742 Debug( LDAP_DEBUG_ANY,
743 "==>backsql_get_attr_vals(\"%s\"): "
744 "unable to find AttributeDescription %s "
745 "in schema (%d)\n",
746 bsi->bsi_e->e_name.bv_val,
747 row.col_names[ i ].bv_val, retval );
748 res = 1;
749 goto done;
752 if ( ad != at->bam_ad ) {
753 Debug( LDAP_DEBUG_ANY,
754 "==>backsql_get_attr_vals(\"%s\"): "
755 "column name %s differs from "
756 "AttributeDescription %s\n",
757 bsi->bsi_e->e_name.bv_val,
758 ad->ad_cname.bv_val,
759 at->bam_ad->ad_cname.bv_val );
760 res = 1;
761 goto done;
763 #endif /* BACKSQL_TRACE */
765 /* ITS#3386, ITS#3113 - 20070308
766 * If a binary is fetched?
767 * must use the actual size read
768 * from the database.
770 if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
771 #ifdef BACKSQL_TRACE
772 Debug( LDAP_DEBUG_ANY,
773 "==>backsql_get_attr_vals(\"%s\"): "
774 "column name %s: data is binary; "
775 "using database size %ld\n",
776 bsi->bsi_e->e_name.bv_val,
777 ad->ad_cname.bv_val,
778 row.value_len[ i ] );
779 #endif /* BACKSQL_TRACE */
780 bv.bv_val = row.cols[ i ];
781 bv.bv_len = row.value_len[ i ];
783 } else {
784 ber_str2bv( row.cols[ i ], 0, 0, &bv );
787 #ifdef BACKSQL_PRETTY_VALIDATE
788 if ( pretty ) {
789 struct berval pbv;
791 retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
792 &bv, &pbv, bsi->bsi_op->o_tmpmemctx );
793 bv = pbv;
795 } else {
796 retval = validate( at->bam_true_ad->ad_type->sat_syntax,
797 &bv );
800 if ( retval != LDAP_SUCCESS ) {
801 char buf[ SLAP_TEXT_BUFLEN ];
803 /* FIXME: we're ignoring invalid values,
804 * but we're accepting the attributes;
805 * should we fail at all? */
806 snprintf( buf, sizeof( buf ),
807 "unable to %s value #%lu "
808 "of AttributeDescription %s",
809 pretty ? "prettify" : "validate",
810 k - oldcount,
811 at->bam_ad->ad_cname.bv_val );
812 Debug( LDAP_DEBUG_TRACE,
813 "==>backsql_get_attr_vals(\"%s\"): "
814 "%s (%d)\n",
815 bsi->bsi_e->e_name.bv_val, buf, retval );
816 continue;
818 #endif /* BACKSQL_PRETTY_VALIDATE */
820 #ifndef BACKSQL_COUNTQUERY
821 (void)backsql_entry_addattr( bsi->bsi_e,
822 at->bam_true_ad, &bv,
823 bsi->bsi_op->o_tmpmemctx );
825 #else /* BACKSQL_COUNTQUERY */
826 if ( normfunc ) {
827 struct berval nbv;
829 retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
830 at->bam_true_ad->ad_type->sat_syntax,
831 at->bam_true_ad->ad_type->sat_equality,
832 &bv, &nbv,
833 bsi->bsi_op->o_tmpmemctx );
835 if ( retval != LDAP_SUCCESS ) {
836 char buf[ SLAP_TEXT_BUFLEN ];
838 /* FIXME: we're ignoring invalid values,
839 * but we're accepting the attributes;
840 * should we fail at all? */
841 snprintf( buf, sizeof( buf ),
842 "unable to normalize value #%lu "
843 "of AttributeDescription %s",
844 k - oldcount,
845 at->bam_ad->ad_cname.bv_val );
846 Debug( LDAP_DEBUG_TRACE,
847 "==>backsql_get_attr_vals(\"%s\"): "
848 "%s (%d)\n",
849 bsi->bsi_e->e_name.bv_val, buf, retval );
851 #ifdef BACKSQL_PRETTY_VALIDATE
852 if ( pretty ) {
853 bsi->bsi_op->o_tmpfree( bv.bv_val,
854 bsi->bsi_op->o_tmpmemctx );
856 #endif /* BACKSQL_PRETTY_VALIDATE */
858 continue;
860 ber_dupbv( &attr->a_nvals[ j ], &nbv );
861 bsi->bsi_op->o_tmpfree( nbv.bv_val,
862 bsi->bsi_op->o_tmpmemctx );
865 ber_dupbv( &attr->a_vals[ j ], &bv );
867 assert( j < oldcount + count );
868 j++;
869 #endif /* BACKSQL_COUNTQUERY */
871 #ifdef BACKSQL_PRETTY_VALIDATE
872 if ( pretty ) {
873 bsi->bsi_op->o_tmpfree( bv.bv_val,
874 bsi->bsi_op->o_tmpmemctx );
876 #endif /* BACKSQL_PRETTY_VALIDATE */
878 #ifdef BACKSQL_TRACE
879 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
880 (int)row.col_prec[ i ], 0, 0 );
882 } else {
883 Debug( LDAP_DEBUG_TRACE, "NULL value "
884 "in this row for attribute \"%s\"\n",
885 row.col_names[ i ].bv_val, 0, 0 );
886 #endif /* BACKSQL_TRACE */
891 #ifdef BACKSQL_COUNTQUERY
892 if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) {
893 /* don't leave around attributes with no values */
894 attr_free( attr );
896 } else if ( append ) {
897 Attribute **ap;
899 for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next )
900 /* goto last */ ;
901 *ap = attr;
903 #endif /* BACKSQL_COUNTQUERY */
905 SQLFreeStmt( sth, SQL_DROP );
906 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
908 if ( at->bam_next ) {
909 res = backsql_get_attr_vals( at->bam_next, v_bsi );
910 } else {
911 res = 1;
914 #ifdef BACKSQL_TRACE
915 done:;
916 #endif /* BACKSQL_TRACE */
917 backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx );
919 return res;
923 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
925 Operation *op = bsi->bsi_op;
926 backsql_info *bi = (backsql_info *)op->o_bd->be_private;
927 int i;
928 int rc;
930 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
932 assert( bsi->bsi_e != NULL );
934 memset( bsi->bsi_e, 0, sizeof( Entry ) );
936 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
937 Entry *e;
939 e = entry_dup( bi->sql_baseObject );
940 if ( e == NULL ) {
941 return LDAP_NO_MEMORY;
944 *bsi->bsi_e = *e;
945 free( e );
946 goto done;
949 ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
950 ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );
952 bsi->bsi_e->e_attrs = NULL;
953 bsi->bsi_e->e_private = NULL;
955 if ( eid->eid_oc == NULL ) {
956 eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
957 eid->eid_oc_id );
959 bsi->bsi_oc = eid->eid_oc;
960 bsi->bsi_c_eid = eid;
962 #ifndef BACKSQL_ARBITRARY_KEY
963 /* FIXME: unused */
964 bsi->bsi_e->e_id = eid->eid_id;
965 #endif /* ! BACKSQL_ARBITRARY_KEY */
967 rc = attr_merge_normalize_one( bsi->bsi_e,
968 slap_schema.si_ad_objectClass,
969 &bsi->bsi_oc->bom_oc->soc_cname,
970 bsi->bsi_op->o_tmpmemctx );
971 if ( rc != LDAP_SUCCESS ) {
972 backsql_entry_clean( op, bsi->bsi_e );
973 return rc;
976 if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
978 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
979 "retrieving all attributes\n", 0, 0, 0 );
980 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
981 bsi, 0, AVL_INORDER );
983 } else {
984 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
985 "custom attribute list\n", 0, 0, 0 );
986 for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
987 backsql_at_map_rec **vat;
988 AttributeName *an = &bsi->bsi_attrs[ i ];
989 int j;
991 /* if one of the attributes listed here is
992 * a subtype of another, it must be ignored,
993 * because subtypes are already dealt with
994 * by backsql_supad2at()
996 for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
997 /* skip self */
998 if ( j == i ) {
999 continue;
1002 /* skip subtypes */
1003 if ( is_at_subtype( an->an_desc->ad_type,
1004 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
1006 goto next;
1010 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
1011 if ( rc != 0 || vat == NULL ) {
1012 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
1013 "attribute \"%s\" is not defined "
1014 "for objectlass \"%s\"\n",
1015 an->an_name.bv_val,
1016 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
1017 continue;
1020 for ( j = 0; vat[j]; j++ ) {
1021 backsql_get_attr_vals( vat[j], bsi );
1024 ch_free( vat );
1026 next:;
1030 if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
1031 Attribute *a_entryUUID,
1032 **ap;
1034 a_entryUUID = backsql_operational_entryUUID( bi, eid );
1035 if ( a_entryUUID != NULL ) {
1036 for ( ap = &bsi->bsi_e->e_attrs;
1037 *ap;
1038 ap = &(*ap)->a_next );
1040 *ap = a_entryUUID;
1044 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
1045 || an_find( bsi->bsi_attrs, &AllOper )
1046 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
1048 ObjectClass *soc = NULL;
1050 if ( BACKSQL_CHECK_SCHEMA( bi ) ) {
1051 Attribute *a;
1052 const char *text = NULL;
1053 char textbuf[ 1024 ];
1054 size_t textlen = sizeof( textbuf );
1055 struct berval bv[ 2 ],
1056 *nvals;
1057 int rc = LDAP_SUCCESS;
1059 a = attr_find( bsi->bsi_e->e_attrs,
1060 slap_schema.si_ad_objectClass );
1061 if ( a != NULL ) {
1062 nvals = a->a_nvals;
1064 } else {
1065 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
1066 BER_BVZERO( &bv[ 1 ] );
1067 nvals = bv;
1070 rc = structural_class( nvals, &soc, NULL,
1071 &text, textbuf, textlen, op->o_tmpmemctx );
1072 if ( rc != LDAP_SUCCESS ) {
1073 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1074 "structural_class() failed %d (%s)\n",
1075 bsi->bsi_e->e_name.bv_val,
1076 rc, text ? text : "" );
1077 backsql_entry_clean( op, bsi->bsi_e );
1078 return rc;
1081 if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) {
1082 if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) {
1083 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1084 "computed structuralObjectClass %s "
1085 "does not match objectClass %s associated "
1086 "to entry\n",
1087 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
1088 bsi->bsi_oc->bom_oc->soc_cname.bv_val );
1089 backsql_entry_clean( op, bsi->bsi_e );
1090 return rc;
1093 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
1094 "computed structuralObjectClass %s "
1095 "is subclass of objectClass %s associated "
1096 "to entry\n",
1097 bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val,
1098 bsi->bsi_oc->bom_oc->soc_cname.bv_val );
1101 } else {
1102 soc = bsi->bsi_oc->bom_oc;
1105 rc = attr_merge_normalize_one( bsi->bsi_e,
1106 slap_schema.si_ad_structuralObjectClass,
1107 &soc->soc_cname,
1108 bsi->bsi_op->o_tmpmemctx );
1109 if ( rc != LDAP_SUCCESS ) {
1110 backsql_entry_clean( op, bsi->bsi_e );
1111 return rc;
1115 done:;
1116 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
1118 return LDAP_SUCCESS;