entry-id.c 27.9 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
2
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
3
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
4
 * Copyright 1999-2010 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Portions Copyright 1999 Dmitry Kovalev.
6
 * Portions Copyright 2002 Pierangelo Masarati.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
7
 * Portions Copyright 2004 Mark Adamson.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
9
10
11
12
13
14
15
16
17
18
19
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* ACKNOWLEDGEMENTS:
 * This work was initially developed by Dmitry Kovalev for inclusion
20
21
 * by OpenLDAP Software.  Additional significant contributors include
 * Pierangelo Masarati and Mark Adamson.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
22
23
24
25
26
27
 */

#include "portable.h"

#include <stdio.h>
#include <sys/types.h>
Pierangelo Masarati's avatar
Pierangelo Masarati committed
28
#include "ac/string.h"
29

30
#include "lutil.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
31
#include "slap.h"
32
#include "proto-sql.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
33

34
35
36
37
#ifdef BACKSQL_ARBITRARY_KEY
struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
#endif /* BACKSQL_ARBITRARY_KEY */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
38
backsql_entryID *
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
backsql_entryID_dup( backsql_entryID *src, void *ctx )
{
	backsql_entryID	*dst;

	if ( src == NULL ) return NULL;

	dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx );
	ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx );
	if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) {
		dst->eid_dn = dst->eid_ndn;
	} else {
		ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx );
	}

#ifdef BACKSQL_ARBITRARY_KEY
	ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx );
	ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx );
#else /* ! BACKSQL_ARBITRARY_KEY */
	dst->eid_id = src->eid_id;
	dst->eid_keyval = src->eid_keyval;
#endif /* ! BACKSQL_ARBITRARY_KEY */

	dst->eid_oc = src->eid_oc;
	dst->eid_oc_id = src->eid_oc_id;

	return dst;
}

backsql_entryID *
backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx )
Dmitry Kovalev's avatar
Dmitry Kovalev committed
69
{
Pierangelo Masarati's avatar
Pierangelo Masarati committed
70
71
	backsql_entryID 	*next;

72
	assert( id != NULL );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
73

Pierangelo Masarati's avatar
Pierangelo Masarati committed
74
	next = id->eid_next;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
75

76
77
78
79
	if ( !BER_BVISNULL( &id->eid_ndn ) ) {
		if ( !BER_BVISNULL( &id->eid_dn )
				&& id->eid_dn.bv_val != id->eid_ndn.bv_val )
		{
80
			slap_sl_free( id->eid_dn.bv_val, ctx );
81
82
83
			BER_BVZERO( &id->eid_dn );
		}

84
		slap_sl_free( id->eid_ndn.bv_val, ctx );
85
		BER_BVZERO( &id->eid_ndn );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
86
87
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
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 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
92
93
	}

94
	if ( !BER_BVISNULL( &id->eid_keyval ) ) {
95
		slap_sl_free( id->eid_keyval.bv_val, ctx );
96
		BER_BVZERO( &id->eid_keyval );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
97
98
99
	}
#endif /* BACKSQL_ARBITRARY_KEY */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
100
	if ( freeit ) {
101
		slap_sl_free( id, ctx );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
102
103
104
	}

	return next;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
105
106
}

107
108
109
/*
 * NOTE: the dn must be normalized
 */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
110
111
int
backsql_dn2id(
112
113
	Operation		*op,
	SlapReply		*rs,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
114
	SQLHDBC			dbh,
115
	struct berval		*ndn,
116
117
	backsql_entryID		*id,
	int			matched,
118
	int			muck )
Dmitry Kovalev's avatar
Dmitry Kovalev committed
119
{
120
	backsql_info		*bi = op->o_bd->be_private;
121
	SQLHSTMT		sth = SQL_NULL_HSTMT; 
122
	BACKSQL_ROW_NTS		row = { 0 };
Pierangelo Masarati's avatar
Pierangelo Masarati committed
123
124
	RETCODE 		rc;
	int			res;
125
	struct berval		realndn = BER_BVNULL;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
126
127
128

	/* TimesTen */
	char			upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
129
	struct berval		tbbDN;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
130
131
	int			i, j;

132
133
134
135
136
137
	/*
	 * NOTE: id can be NULL; in this case, the function
	 * simply checks whether the DN can be successfully 
	 * turned into an ID, returning LDAP_SUCCESS for
	 * positive cases, or the most appropriate error
	 */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
138

139
140
141
	Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", 
			ndn->bv_val, id == NULL ? " (no ID expected)" : "",
			matched ? " matched expected" : "" );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
142

143
144
145
146
147
	if ( id ) {
		/* NOTE: trap inconsistencies */
		assert( BER_BVISNULL( &id->eid_ndn ) );
	}

148
	if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
149
		Debug( LDAP_DEBUG_TRACE, 
150
151
			"   backsql_dn2id(\"%s\"): DN length=%ld "
			"exceeds max DN length %d:\n",
152
			ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
153
154
		return LDAP_OTHER;
	}
155
156

	/* return baseObject if available and matches */
157
158
159
160
	/* FIXME: if ndn is already mucked, we cannot check this */
	if ( bi->sql_baseObject != NULL &&
			dn_match( ndn, &bi->sql_baseObject->e_nname ) )
	{
161
162
		if ( id != NULL ) {
#ifdef BACKSQL_ARBITRARY_KEY
163
164
165
166
			ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv,
					op->o_tmpmemctx );
			ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv,
					op->o_tmpmemctx );
167
168
169
170
171
172
#else /* ! BACKSQL_ARBITRARY_KEY */
			id->eid_id = BACKSQL_BASEOBJECT_ID;
			id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
#endif /* ! BACKSQL_ARBITRARY_KEY */
			id->eid_oc_id = BACKSQL_BASEOBJECT_OC;

173
174
175
176
			ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname,
					op->o_tmpmemctx );
			ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name,
					op->o_tmpmemctx );
177
178
179
180
181
182

			id->eid_next = NULL;
		}

		return LDAP_SUCCESS;
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
183
184
	
	/* begin TimesTen */
185
186
	Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): id_query \"%s\"\n",
			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 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
189
190
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, 
191
192
193
			"   backsql_dn2id(\"%s\"): "
			"error preparing SQL:\n   %s", 
			ndn->bv_val, bi->sql_id_query, 0 );
194
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
195
196
197
198
199
200
201
202
203
204
205
206
207
		res = LDAP_OTHER;
		goto done;
	}

	realndn = *ndn;
	if ( muck ) {
		if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
			Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
				"backsql_api_dn2odbc(\"%s\") failed\n", 
				ndn->bv_val, realndn.bv_val, 0 );
			res = LDAP_OTHER;
			goto done;
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
208
209
	}

210
	if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
211
212
213
214
215
		/*
		 * Prepare an upper cased, byte reversed version 
		 * that can be searched using indexes
		 */

216
217
		for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
		{
218
			upperdn[ i ] = realndn.bv_val[ j ];
Pierangelo Masarati's avatar
Pierangelo Masarati committed
219
220
221
222
		}
		upperdn[ i ] = '\0';
		ldap_pvt_str2upper( upperdn );

223
224
225
		Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
				"upperdn=\"%s\"\n",
				ndn->bv_val, upperdn, 0 );
226
		ber_str2bv( upperdn, 0, 0, &tbbDN );
227

Pierangelo Masarati's avatar
Pierangelo Masarati committed
228
	} else {
229
		if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
230
			AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
231
232
			ldap_pvt_str2upper( upperdn );
			Debug( LDAP_DEBUG_TRACE,
233
234
235
				"   backsql_dn2id(\"%s\"): "
				"upperdn=\"%s\"\n",
				ndn->bv_val, upperdn, 0 );
236
			ber_str2bv( upperdn, 0, 0, &tbbDN );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
237
238

		} else {
239
			tbbDN = realndn;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
240
241
242
		}
	}

243
	rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
244
245
	if ( rc != SQL_SUCCESS) {
		/* 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
251
		res = LDAP_OTHER;
		goto done;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
252
	}
Dmitry Kovalev's avatar
Dmitry Kovalev committed
253

Pierangelo Masarati's avatar
Pierangelo Masarati committed
254
255
	rc = SQLExecute( sth );
	if ( rc != SQL_SUCCESS ) {
256
		Debug( LDAP_DEBUG_TRACE, "   backsql_dn2id(\"%s\"): "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
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
261
		res = LDAP_OTHER;
		goto done;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
262
	}
Dmitry Kovalev's avatar
Dmitry Kovalev committed
263

264
	backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
265
266
	rc = SQLFetch( sth );
	if ( BACKSQL_SUCCESS( rc ) ) {
267
		char	buf[ SLAP_TEXT_BUFLEN ];
268

269
270
271
272
273
274
#ifdef LDAP_DEBUG
		snprintf( buf, sizeof(buf),
			"id=%s keyval=%s oc_id=%s dn=%s",
			row.cols[ 0 ], row.cols[ 1 ],
			row.cols[ 2 ], row.cols[ 3 ] );
		Debug( LDAP_DEBUG_TRACE,
275
276
			"   backsql_dn2id(\"%s\"): %s\n",
			ndn->bv_val, buf, 0 );
277
278
279
#endif /* LDAP_DEBUG */

		res = LDAP_SUCCESS;
280
		if ( id != NULL ) {
281
282
			struct berval	dn;

283
284
			id->eid_next = NULL;

Pierangelo Masarati's avatar
Pierangelo Masarati committed
285
#ifdef BACKSQL_ARBITRARY_KEY
286
287
288
289
			ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id,
					op->o_tmpmemctx );
			ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval,
					op->o_tmpmemctx );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
290
#else /* ! BACKSQL_ARBITRARY_KEY */
291
292
293
294
295
296
297
298
			if ( lutil_atoulx( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}
			if ( lutil_atoulx( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
299
#endif /* ! BACKSQL_ARBITRARY_KEY */
300
301
302
303
			if ( lutil_atoulx( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) {
				res = LDAP_OTHER;
				goto done;
			}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
304

305
306
			ber_str2bv( row.cols[ 3 ], 0, 0, &dn );

307
308
			if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
				res = LDAP_OTHER;
309
310
311
312
313
314
315
316
317
318
319
320
321
322
				goto done;
			}
			
			res = dnPrettyNormal( NULL, &dn,
					&id->eid_dn, &id->eid_ndn,
					op->o_tmpmemctx );
			if ( res != LDAP_SUCCESS ) {
				Debug( LDAP_DEBUG_TRACE,
					"   backsql_dn2id(\"%s\"): "
					"dnPrettyNormal failed (%d: %s)\n",
					realndn.bv_val, res,
					ldap_err2string( res ) );

				/* cleanup... */
323
				(void)backsql_free_entryID( id, 0, op->o_tmpmemctx );
324
325
			}

326
327
328
			if ( dn.bv_val != row.cols[ 3 ] ) {
				free( dn.bv_val );
			}
329
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
330
331
332

	} else {
		res = LDAP_NO_SUCH_OBJECT;
333
334
335
336
337
338
339
340
341
342
		if ( matched ) {
			struct berval	pdn = *ndn;

			/*
			 * Look for matched
			 */
			rs->sr_matched = NULL;
			while ( !be_issuffix( op->o_bd, &pdn ) ) {
				char		*matchedDN = NULL;
	
Pierangelo Masarati's avatar
Pierangelo Masarati committed
343
				dnParent( &pdn, &pdn );
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	
				/*
				 * Empty DN ("") defaults to LDAP_SUCCESS
				 */
				rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 );
				switch ( rs->sr_err ) {
				case LDAP_NO_SUCH_OBJECT:
					/* try another one */
					break;
					
				case LDAP_SUCCESS:
					matchedDN = pdn.bv_val;
					/* fail over to next case */
	
				default:
					rs->sr_err = LDAP_NO_SUCH_OBJECT;
					rs->sr_matched = matchedDN;
					goto done;
				} 
			}
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
365
366
	}

367
done:;
368
369
	backsql_FreeRow_x( &row, op->o_tmpmemctx );

370
371
372
	Debug( LDAP_DEBUG_TRACE,
		"<==backsql_dn2id(\"%s\"): err=%d\n",
		ndn->bv_val, res, 0 );
373
374
375
376
377
378
379
380
	if ( sth != SQL_NULL_HSTMT ) {
		SQLFreeStmt( sth, SQL_DROP );
	}

	if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
		ch_free( realndn.bv_val );
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
381
382
383
	return res;
}

384
int
385
backsql_count_children(
386
	Operation		*op,
387
	SQLHDBC			dbh,
388
389
	struct berval		*dn,
	unsigned long		*nchildren )
390
{
391
	backsql_info 		*bi = (backsql_info *)op->o_bd->be_private;
392
	SQLHSTMT		sth = SQL_NULL_HSTMT;
393
394
	BACKSQL_ROW_NTS		row;
	RETCODE 		rc;
395
	int			res = LDAP_SUCCESS;
396

397
	Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n", 
398
399
400
401
			dn->bv_val, 0, 0 );

	if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
		Debug( LDAP_DEBUG_TRACE, 
402
			"backsql_count_children(): DN \"%s\" (%ld bytes) "
403
404
405
406
407
408
			"exceeds max DN length (%d):\n",
			dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
		return LDAP_OTHER;
	}
	
	/* 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
414
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, 
415
			"backsql_count_children(): error preparing SQL:\n%s", 
416
417
			bi->sql_has_children_query, 0, 0);
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
418
419
420
421
		SQLFreeStmt( sth, SQL_DROP );
		return LDAP_OTHER;
	}

422
	rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
423
424
	if ( rc != SQL_SUCCESS) {
		/* end TimesTen */ 
425
		Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
426
427
			"error binding dn=\"%s\" parameter:\n", 
			dn->bv_val, 0, 0 );
428
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
429
430
431
432
433
434
		SQLFreeStmt( sth, SQL_DROP );
		return LDAP_OTHER;
	}

	rc = SQLExecute( sth );
	if ( rc != SQL_SUCCESS ) {
435
		Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
436
			"error executing query (\"%s\", \"%s\"):\n", 
437
438
			bi->sql_has_children_query, dn->bv_val, 0 );
		backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
439
440
441
442
		SQLFreeStmt( sth, SQL_DROP );
		return LDAP_OTHER;
	}

443
	backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx );
444
445
446
	
	rc = SQLFetch( sth );
	if ( BACKSQL_SUCCESS( rc ) ) {
447
448
449
		char *end;

		*nchildren = strtol( row.cols[ 0 ], &end, 0 );
450
		if ( end == row.cols[ 0 ] ) {
451
			res = LDAP_OTHER;
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

		} else {
			switch ( end[ 0 ] ) {
			case '\0':
				break;

			case '.': {
				unsigned long	ul;

				/* FIXME: braindead RDBMSes return
				 * a fractional number from COUNT!
				 */
				if ( lutil_atoul( &ul, end + 1 ) != 0 || ul != 0 ) {
					res = LDAP_OTHER;
				}
				} break;

			default:
				res = LDAP_OTHER;
			}
472
473
474
475
476
		}

	} else {
		res = LDAP_OTHER;
	}
477
	backsql_FreeRow_x( &row, op->o_tmpmemctx );
478
479
480

	SQLFreeStmt( sth, SQL_DROP );

481
482
	Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
			*nchildren, 0, 0 );
483
484
485
486

	return res;
}

487
488
int
backsql_has_children(
489
	Operation		*op,
490
491
492
493
494
495
	SQLHDBC			dbh,
	struct berval		*dn )
{
	unsigned long	nchildren;
	int		rc;

496
	rc = backsql_count_children( op, dbh, dn, &nchildren );
497
498
499
500
501
502
503
504

	if ( rc == LDAP_SUCCESS ) {
		return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
	}

	return rc;
}

505
506
static int
backsql_get_attr_vals( void *v_at, void *v_bsi )
Dmitry Kovalev's avatar
Dmitry Kovalev committed
507
{
508
509
	backsql_at_map_rec	*at = v_at;
	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
515
	unsigned long		i,
				k = 0,
516
517
				oldcount = 0,
				res = 0;
518
#ifdef BACKSQL_COUNTQUERY
Pierangelo Masarati's avatar
Pierangelo Masarati committed
519
	unsigned 		count,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
520
521
				j,
				append = 0;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
522
	SQLLEN			countsize = sizeof( count );
523
524
525
526
527
528
529
530
	Attribute		*attr = NULL;

	slap_mr_normalize_func		*normfunc = NULL;
#endif /* BACKSQL_COUNTQUERY */
#ifdef BACKSQL_PRETTY_VALIDATE
	slap_syntax_validate_func	*validate = NULL;
	slap_syntax_transform_func	*pretty = NULL;
#endif /* BACKSQL_PRETTY_VALIDATE */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
531

532
533
	assert( at != NULL );
	assert( bsi != NULL );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
534

Pierangelo Masarati's avatar
Pierangelo Masarati committed
535
	Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
536
		"oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n",
537
		BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, 
538
		BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
539

540
#ifdef BACKSQL_PRETTY_VALIDATE
541
542
	validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate;
	pretty =  at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty;
543
544
545
546
547
548
549

	if ( validate == NULL && pretty == NULL ) {
		return 1;
	}
#endif /* BACKSQL_PRETTY_VALIDATE */

#ifdef BACKSQL_COUNTQUERY
550
551
	if ( at->bam_true_ad->ad_type->sat_equality ) {
		normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize;
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
	}

	/* Count how many rows will be returned. This avoids memory 
	 * fragmentation that can result from loading the values in 
	 * one by one and using realloc() 
	 */
	rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error preparing count query: %s\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		return 1;
	}

	rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
			&bsi->bsi_c_eid->eid_keyval );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error binding key value parameter\n", 0, 0, 0 );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	rc = SQLExecute( sth );
	if ( ! BACKSQL_SUCCESS( rc ) ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error executing attribute count query '%s'\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG,
			(SQLPOINTER)&count,
			(SQLINTEGER)sizeof( count ),
			&countsize );

	rc = SQLFetch( sth );
	if ( rc != SQL_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
			"error fetch results of count query: %s\n",
			at->bam_countquery, 0, 0 );
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
		SQLFreeStmt( sth, SQL_DROP );
		return 1;
	}

	Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
602
		"number of values in query: %u\n", count, 0, 0 );
603
604
605
606
607
	SQLFreeStmt( sth, SQL_DROP );
	if ( count == 0 ) {
		return 1;
	}

608
	attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad );
609
610
611
612
	if ( attr != NULL ) {
		BerVarray	tmp;

		if ( attr->a_vals != NULL ) {
613
			oldcount = attr->a_numvals;
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
		}

		tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
		if ( tmp == NULL ) {
			return 1;
		}
		attr->a_vals = tmp;
		memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );

		if ( normfunc ) {
			tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) );
			if ( tmp == NULL ) {
				return 1;
			}
			attr->a_nvals = tmp;
			memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) );

		} else {
			attr->a_nvals = attr->a_vals;
		}
634
		attr->a_numvals += count;
635
636

	} else {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
637
		append = 1;
638
639

		/* Make space for the array of values */
640
		attr = attr_alloc( at->bam_true_ad );
641
		attr->a_numvals = count;
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
		attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) );
		if ( attr->a_vals == NULL ) {
			Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 );
			ch_free( attr );
			return 1;
		}
		if ( normfunc ) {
			attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) );
			if ( attr->a_nvals == NULL ) {
				ch_free( attr->a_vals );
				ch_free( attr );
				return 1;

			}

		} else {
			attr->a_nvals = attr->a_vals;
		}
	}
#endif /* BACKSQL_COUNTQUERY */

663
	rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
664
	if ( rc != SQL_SUCCESS ) {
665
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
666
			"error preparing query: %s\n", at->bam_query, 0, 0 );
667
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
668
669
670
671
672
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
673
674
675
		return 1;
	}

676
677
	rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
			&bsi->bsi_c_eid->eid_keyval );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
678
	if ( rc != SQL_SUCCESS ) {
679
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
Pierangelo Masarati's avatar
Pierangelo Masarati committed
680
			"error binding key value parameter\n", 0, 0, 0 );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
681
682
683
684
685
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
686
687
688
		return 1;
	}

689
#ifdef BACKSQL_TRACE
690
	Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
691
692
		"query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query,
		BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval), 0 );
693
694
#endif /* BACKSQL_TRACE */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
695
696
	rc = SQLExecute( sth );
	if ( ! BACKSQL_SUCCESS( rc ) ) {
697
		Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): "
698
			"error executing attribute query \"%s\"\n",
699
			at->bam_query, 0, 0 );
700
		backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
701
		SQLFreeStmt( sth, SQL_DROP );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
702
703
704
705
706
#ifdef BACKSQL_COUNTQUERY
		if ( append ) {
			attr_free( attr );
		}
#endif /* BACKSQL_COUNTQUERY */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
707
708
		return 1;
	}
Dmitry Kovalev's avatar
Dmitry Kovalev committed
709

710
	backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx );
711
712
713
714
715
716
717
#ifdef BACKSQL_COUNTQUERY
	j = oldcount;
#endif /* BACKSQL_COUNTQUERY */
	for ( rc = SQLFetch( sth ), k = 0;
			BACKSQL_SUCCESS( rc );
			rc = SQLFetch( sth ), k++ )
	{
718
		for ( i = 0; i < (unsigned long)row.ncols; i++ ) {
719

720
			if ( row.value_len[ i ] > 0 ) {
721
722
723
724
725
726
727
728
729
730
731
732
733
734
				struct berval		bv;
				int			retval;
#ifdef BACKSQL_TRACE
				AttributeDescription	*ad = NULL;
				const char		*text;

				retval = slap_bv2ad( &row.col_names[ i ], &ad, &text );
				if ( retval != LDAP_SUCCESS ) {
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"unable to find AttributeDescription %s "
						"in schema (%d)\n",
						bsi->bsi_e->e_name.bv_val,
						row.col_names[ i ].bv_val, retval );
735
736
					res = 1;
					goto done;
737
738
739
740
741
742
743
744
745
746
				}

				if ( ad != at->bam_ad ) {
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"column name %s differs from "
						"AttributeDescription %s\n",
						bsi->bsi_e->e_name.bv_val,
						ad->ad_cname.bv_val,
						at->bam_ad->ad_cname.bv_val );
747
748
					res = 1;
					goto done;
749
750
				}
#endif /* BACKSQL_TRACE */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
751

752
753
754
755
				/* ITS#3386, ITS#3113 - 20070308
				 * If a binary is fetched?
				 * must use the actual size read
				 * from the database.
Pierangelo Masarati's avatar
Pierangelo Masarati committed
756
				 */
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
				if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
#ifdef BACKSQL_TRACE
					Debug( LDAP_DEBUG_ANY,
						"==>backsql_get_attr_vals(\"%s\"): "
						"column name %s: data is binary; "
						"using database size %ld\n",
						bsi->bsi_e->e_name.bv_val,
						ad->ad_cname.bv_val,
						row.value_len[ i ] );
#endif /* BACKSQL_TRACE */
					bv.bv_val = row.cols[ i ];
					bv.bv_len = row.value_len[ i ];

				} else {
					ber_str2bv( row.cols[ i ], 0, 0, &bv );
				}
773
774
775
776
777

#ifdef BACKSQL_PRETTY_VALIDATE
				if ( pretty ) {
					struct berval	pbv;

778
					retval = pretty( at->bam_true_ad->ad_type->sat_syntax,
779
780
781
782
						&bv, &pbv, bsi->bsi_op->o_tmpmemctx );
					bv = pbv;

				} else {
783
					retval = validate( at->bam_true_ad->ad_type->sat_syntax,
784
785
786
787
788
789
790
791
792
793
						&bv );
				}

				if ( retval != LDAP_SUCCESS ) {
					char	buf[ SLAP_TEXT_BUFLEN ];

					/* FIXME: we're ignoring invalid values,
					 * but we're accepting the attributes;
					 * should we fail at all? */
					snprintf( buf, sizeof( buf ),
794
							"unable to %s value #%lu "
795
796
							"of AttributeDescription %s",
							pretty ? "prettify" : "validate",
797
798
							k - oldcount,
							at->bam_ad->ad_cname.bv_val );
799
800
801
802
803
804
805
806
807
808
					Debug( LDAP_DEBUG_TRACE,
						"==>backsql_get_attr_vals(\"%s\"): "
						"%s (%d)\n",
						bsi->bsi_e->e_name.bv_val, buf, retval );
					continue;
				}
#endif /* BACKSQL_PRETTY_VALIDATE */

#ifndef BACKSQL_COUNTQUERY
				(void)backsql_entry_addattr( bsi->bsi_e, 
809
						at->bam_true_ad, &bv,
810
						bsi->bsi_op->o_tmpmemctx );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
811

812
813
814
815
816
#else /* BACKSQL_COUNTQUERY */
				if ( normfunc ) {
					struct berval	nbv;

					retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
817
818
						at->bam_true_ad->ad_type->sat_syntax,
						at->bam_true_ad->ad_type->sat_equality,
819
820
821
822
823
824
825
826
827
828
						&bv, &nbv,
						bsi->bsi_op->o_tmpmemctx );

					if ( retval != LDAP_SUCCESS ) {
						char	buf[ SLAP_TEXT_BUFLEN ];

						/* FIXME: we're ignoring invalid values,
						 * but we're accepting the attributes;
						 * should we fail at all? */
						snprintf( buf, sizeof( buf ),
829
							"unable to normalize value #%lu "
830
							"of AttributeDescription %s",
831
832
							k - oldcount,
							at->bam_ad->ad_cname.bv_val );
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
						Debug( LDAP_DEBUG_TRACE,
							"==>backsql_get_attr_vals(\"%s\"): "
							"%s (%d)\n",
							bsi->bsi_e->e_name.bv_val, buf, retval );

#ifdef BACKSQL_PRETTY_VALIDATE
						if ( pretty ) {
							bsi->bsi_op->o_tmpfree( bv.bv_val,
									bsi->bsi_op->o_tmpmemctx );
						}
#endif /* BACKSQL_PRETTY_VALIDATE */

						continue;
					}
					ber_dupbv( &attr->a_nvals[ j ], &nbv );
					bsi->bsi_op->o_tmpfree( nbv.bv_val,
							bsi->bsi_op->o_tmpmemctx );
				}

				ber_dupbv( &attr->a_vals[ j ], &bv );

				assert( j < oldcount + count );
				j++;
#endif /* BACKSQL_COUNTQUERY */

#ifdef BACKSQL_PRETTY_VALIDATE
				if ( pretty ) {
					bsi->bsi_op->o_tmpfree( bv.bv_val,
							bsi->bsi_op->o_tmpmemctx );
				}
#endif /* BACKSQL_PRETTY_VALIDATE */

865
#ifdef BACKSQL_TRACE
Pierangelo Masarati's avatar
Pierangelo Masarati committed
866
867
				Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
					(int)row.col_prec[ i ], 0, 0 );
868

Pierangelo Masarati's avatar
Pierangelo Masarati committed
869
870
			} else {
      				Debug( LDAP_DEBUG_TRACE, "NULL value "
871
					"in this row for attribute \"%s\"\n",
Pierangelo Masarati's avatar
Pierangelo Masarati committed
872
					row.col_names[ i ].bv_val, 0, 0 );
873
#endif /* BACKSQL_TRACE */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
874
875
876
877
			}
		}
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
878
879
880
881
882
883
884
885
886
887
888
889
890
891
#ifdef BACKSQL_COUNTQUERY
	if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) {
		/* don't leave around attributes with no values */
		attr_free( attr );

	} else if ( append ) {
		Attribute	**ap;

		for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next )
			/* goto last */ ;
		*ap =  attr;
	}
#endif /* BACKSQL_COUNTQUERY */

Pierangelo Masarati's avatar
Pierangelo Masarati committed
892
893
894
	SQLFreeStmt( sth, SQL_DROP );
	Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );

895
	if ( at->bam_next ) {
896
897
898
		res = backsql_get_attr_vals( at->bam_next, v_bsi );
	} else {
		res = 1;
899
900
	}

901
902
903
904
905
906
#ifdef BACKSQL_TRACE
done:;
#endif /* BACKSQL_TRACE */
	backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx );

	return res;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
907
908
}

909
910
int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
Dmitry Kovalev's avatar
Dmitry Kovalev committed
911
{
912
913
	Operation		*op = bsi->bsi_op;
	backsql_info		*bi = (backsql_info *)op->o_bd->be_private;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
914
	int			i;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
915
	int			rc;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
916

Pierangelo Masarati's avatar
Pierangelo Masarati committed
917
	Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
Dmitry Kovalev's avatar
Dmitry Kovalev committed
918

919
	assert( bsi->bsi_e != NULL );
920
921
922

	memset( bsi->bsi_e, 0, sizeof( Entry ) );

923
	if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
924
		(void)entry_dup2( bsi->bsi_e, bi->sql_baseObject );
925
926
927
		goto done;
	}

928
929
930
	bsi->bsi_e->e_attrs = NULL;
	bsi->bsi_e->e_private = NULL;

931
932
	if ( eid->eid_oc == NULL ) {
		eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
Pierangelo Masarati's avatar
Pierangelo Masarati committed
933
			eid->eid_oc_id );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
934
935
936
937
938
939
940
		if ( eid->eid_oc == NULL ) {
			Debug( LDAP_DEBUG_TRACE,
				"backsql_id2entry(): unable to fetch objectClass with id=%lu for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n",
				eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id),
				eid->eid_dn.bv_val );
			return LDAP_OTHER;
		}
941
942
	}
	bsi->bsi_oc = eid->eid_oc;
943
	bsi->bsi_c_eid = eid;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
944

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
945
946
947
	ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx );
	ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx );

Pierangelo Masarati's avatar
Pierangelo Masarati committed
948
#ifndef BACKSQL_ARBITRARY_KEY	
949
	/* FIXME: unused */
950
	bsi->bsi_e->e_id = eid->eid_id;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
951
#endif /* ! BACKSQL_ARBITRARY_KEY */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
952
 
953
954
955
956
	rc = attr_merge_normalize_one( bsi->bsi_e,
			slap_schema.si_ad_objectClass,
			&bsi->bsi_oc->bom_oc->soc_cname,
			bsi->bsi_op->o_tmpmemctx );
957
	if ( rc != LDAP_SUCCESS ) {
958
		backsql_entry_clean( op, bsi->bsi_e );
959
960
961
		return rc;
	}

962
963
964
965
966
967
968
969
	if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
	{
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"retrieving all attributes\n", 0, 0, 0 );
		avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
				bsi, 0, AVL_INORDER );

	} else {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
970
971
		Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
			"custom attribute list\n", 0, 0, 0 );
972
		for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) {
973
			backsql_at_map_rec	**vat;
974
			AttributeName		*an = &bsi->bsi_attrs[ i ];
975
			int			j;
Pierangelo Masarati's avatar
Pierangelo Masarati committed
976

977
978
979
980
981
			/* if one of the attributes listed here is
			 * a subtype of another, it must be ignored,
			 * because subtypes are already dealt with
			 * by backsql_supad2at()
			 */
982
			for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) {
983
984
985
986
987
988
				/* skip self */
				if ( j == i ) {
					continue;
				}

				/* skip subtypes */
989
990
				if ( is_at_subtype( an->an_desc->ad_type,
							bsi->bsi_attrs[ j ].an_desc->ad_type ) )
991
992
993
994
995
				{
					goto next;
				}
			}

996
			rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
997
			if ( rc != 0 || vat == NULL ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
998
				Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
999
1000
						"attribute \"%s\" is not defined "
						"for objectlass \"%s\"\n",
For faster browsing, not all history is shown. View entire blame