2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2005 The OpenLDAP Foundation.
5 * Portions Copyright 1999 Dmitry Kovalev.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
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>.
17 * This work was initially developed by Dmitry Kovalev for inclusion
18 * by OpenLDAP Software.
26 #include <sys/types.h>
27 #include "ac/string.h"
32 #include "proto-sql.h"
35 backsql_free_entryID( backsql_entryID *id, int freeit )
37 backsql_entryID *next;
43 if ( id->eid_dn.bv_val != NULL ) {
44 free( id->eid_dn.bv_val );
47 #ifdef BACKSQL_ARBITRARY_KEY
48 if ( id->eid_id.bv_val ) {
49 free( id->eid_id.bv_val );
52 if ( id->eid_keyval.bv_val ) {
53 free( id->eid_keyval.bv_val );
55 #endif /* BACKSQL_ARBITRARY_KEY */
77 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
82 * NOTE: id can be NULL; in this case, the function
83 * simply checks whether the DN can be successfully
84 * turned into an ID, returning LDAP_SUCCESS for
85 * positive cases, or the most appropriate error
88 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n",
89 dn->bv_val, id == NULL ? " (no ID)" : "", 0 );
91 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
92 Debug( LDAP_DEBUG_TRACE,
93 "backsql_dn2id(): DN \"%s\" (%ld bytes) "
94 "exceeds max DN length (%d):\n",
95 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
100 Debug(LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->id_query, 0, 0);
101 assert( bi->id_query );
102 rc = backsql_Prepare( dbh, &sth, bi->id_query, 0 );
103 if ( rc != SQL_SUCCESS ) {
104 Debug( LDAP_DEBUG_TRACE,
105 "backsql_dn2id(): error preparing SQL:\n%s",
107 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
108 SQLFreeStmt( sth, SQL_DROP );
112 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
114 * Prepare an upper cased, byte reversed version
115 * that can be searched using indexes
118 for ( i = 0, j = dn->bv_len - 1; dn->bv_val[ i ]; i++, j--) {
119 upperdn[ i ] = dn->bv_val[ j ];
122 ldap_pvt_str2upper( upperdn );
124 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n",
126 ber_str2bv( upperdn, 0, 0, &toBind );
129 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
130 AC_MEMCPY( upperdn, dn->bv_val, dn->bv_len + 1 );
131 ldap_pvt_str2upper( upperdn );
132 Debug( LDAP_DEBUG_TRACE,
133 "==>backsql_dn2id(): upperdn=\"%s\"\n",
135 ber_str2bv( upperdn, 0, 0, &toBind );
142 rc = backsql_BindParamStr( sth, 1, toBind.bv_val, BACKSQL_MAX_DN_LEN );
143 if ( rc != SQL_SUCCESS) {
145 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
146 "error binding dn=\"%s\" parameter:\n",
147 toBind.bv_val, 0, 0 );
148 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
149 SQLFreeStmt( sth, SQL_DROP );
153 rc = SQLExecute( sth );
154 if ( rc != SQL_SUCCESS ) {
155 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
156 "error executing query (\"%s\", \"%s\"):\n",
157 bi->id_query, toBind.bv_val, 0 );
158 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
159 SQLFreeStmt( sth, SQL_DROP );
163 backsql_BindRowAsStrings( sth, &row );
164 rc = SQLFetch( sth );
165 if ( BACKSQL_SUCCESS( rc ) ) {
167 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): id=%s keyval=%s oc_id=%s\n",
168 row.cols[ 0 ], row.cols[ 1 ], row.cols[ 2 ] );
171 #ifdef BACKSQL_ARBITRARY_KEY
172 ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
173 ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
174 #else /* ! BACKSQL_ARBITRARY_KEY */
175 id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
176 id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
177 #endif /* ! BACKSQL_ARBITRARY_KEY */
178 id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
180 ber_dupbv( &id->eid_dn, dn );
185 res = LDAP_NO_SUCH_OBJECT;
186 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
189 backsql_FreeRow( &row );
191 SQLFreeStmt( sth, SQL_DROP );
196 backsql_count_children(
200 unsigned long *nchildren )
205 int res = LDAP_SUCCESS;
207 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
210 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
211 Debug( LDAP_DEBUG_TRACE,
212 "backsql_count_children(): DN \"%s\" (%ld bytes) "
213 "exceeds max DN length (%d):\n",
214 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
219 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
220 bi->has_children_query, 0, 0);
221 assert( bi->has_children_query );
222 rc = backsql_Prepare( dbh, &sth, bi->has_children_query, 0 );
223 if ( rc != SQL_SUCCESS ) {
224 Debug( LDAP_DEBUG_TRACE,
225 "backsql_count_children(): error preparing SQL:\n%s",
226 bi->has_children_query, 0, 0);
227 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
228 SQLFreeStmt( sth, SQL_DROP );
232 rc = backsql_BindParamStr( sth, 1, dn->bv_val, BACKSQL_MAX_DN_LEN );
233 if ( rc != SQL_SUCCESS) {
235 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
236 "error binding dn=\"%s\" parameter:\n",
238 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
239 SQLFreeStmt( sth, SQL_DROP );
243 rc = SQLExecute( sth );
244 if ( rc != SQL_SUCCESS ) {
245 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
246 "error executing query (\"%s\", \"%s\"):\n",
247 bi->has_children_query, dn->bv_val, 0 );
248 backsql_PrintErrors( SQL_NULL_HENV, dbh, sth, rc );
249 SQLFreeStmt( sth, SQL_DROP );
253 backsql_BindRowAsStrings( sth, &row );
255 rc = SQLFetch( sth );
256 if ( BACKSQL_SUCCESS( rc ) ) {
259 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
260 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
261 /* FIXME: braindead RDBMSes return
262 * a fractional number from COUNT!
270 backsql_FreeRow( &row );
272 SQLFreeStmt( sth, SQL_DROP );
274 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
281 backsql_has_children(
286 unsigned long nchildren;
289 rc = backsql_count_children( bi, dbh, dn, &nchildren );
291 if ( rc == LDAP_SUCCESS ) {
292 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
299 backsql_get_attr_vals( void *v_at, void *v_bsi )
301 backsql_at_map_rec *at = v_at;
302 backsql_srch_info *bsi = v_bsi;
303 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
312 #ifdef BACKSQL_ARBITRARY_KEY
313 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
314 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
315 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
316 bsi->bsi_c_eid->eid_keyval.bv_val );
317 #else /* ! BACKSQL_ARBITRARY_KEY */
318 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
319 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
320 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
321 bsi->bsi_c_eid->eid_keyval );
322 #endif /* ! BACKSQL_ARBITRARY_KEY */
324 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
325 if ( rc != SQL_SUCCESS ) {
326 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
327 "error preparing query: %s\n", at->bam_query, 0, 0 );
328 backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc );
332 #ifdef BACKSQL_ARBITRARY_KEY
333 rc = backsql_BindParamStr( sth, 1, bsi->bsi_c_eid->eid_keyval.bv_val,
334 BACKSQL_MAX_KEY_LEN );
335 #else /* ! BACKSQL_ARBITRARY_KEY */
336 rc = backsql_BindParamID( sth, 1, &bsi->bsi_c_eid->eid_keyval );
337 #endif /* ! BACKSQL_ARBITRARY_KEY */
338 if ( rc != SQL_SUCCESS ) {
339 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
340 "error binding key value parameter\n", 0, 0, 0 );
345 #ifdef BACKSQL_ARBITRARY_KEY
346 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
347 "query=\"%s\" keyval=%s\n", at->bam_query,
348 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
349 #else /* !BACKSQL_ARBITRARY_KEY */
350 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
351 "query=\"%s\" keyval=%d\n", at->bam_query,
352 bsi->bsi_c_eid->eid_keyval, 0 );
353 #endif /* ! BACKSQL_ARBITRARY_KEY */
354 #endif /* BACKSQL_TRACE */
356 rc = SQLExecute( sth );
357 if ( ! BACKSQL_SUCCESS( rc ) ) {
358 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
359 "error executing attribute query \"%s\"\n",
360 at->bam_query, 0, 0 );
361 backsql_PrintErrors( bi->db_env, bsi->bsi_dbh, sth, rc );
362 SQLFreeStmt( sth, SQL_DROP );
366 backsql_BindRowAsStrings( sth, &row );
368 rc = SQLFetch( sth );
369 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
370 for ( i = 0; i < row.ncols; i++ ) {
371 if ( row.value_len[ i ] > 0 ) {
374 bv.bv_val = row.cols[ i ];
376 bv.bv_len = row.col_prec[ i ];
379 * FIXME: what if a binary
382 bv.bv_len = strlen( row.cols[ i ] );
384 backsql_entry_addattr( bsi->bsi_e,
385 &row.col_names[ i ], &bv,
386 bsi->bsi_op->o_tmpmemctx );
389 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
390 (int)row.col_prec[ i ], 0, 0 );
392 Debug( LDAP_DEBUG_TRACE, "NULL value "
393 "in this row for attribute \"%s\"\n",
394 row.col_names[ i ].bv_val, 0, 0 );
395 #endif /* BACKSQL_TRACE */
400 backsql_FreeRow( &row );
401 SQLFreeStmt( sth, SQL_DROP );
402 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
404 if ( at->bam_next ) {
405 return backsql_get_attr_vals( at->bam_next, v_bsi );
412 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
416 AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
418 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
420 assert( bsi->bsi_e );
422 memset( bsi->bsi_e, 0, sizeof( Entry ) );
424 rc = dnPrettyNormal( NULL, &eid->eid_dn,
425 &bsi->bsi_e->e_name, &bsi->bsi_e->e_nname,
426 bsi->bsi_op->o_tmpmemctx );
427 if ( rc != LDAP_SUCCESS ) {
431 bsi->bsi_e->e_attrs = NULL;
432 bsi->bsi_e->e_private = NULL;
434 bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
436 bsi->bsi_c_eid = eid;
438 #ifndef BACKSQL_ARBITRARY_KEY
439 bsi->bsi_e->e_id = eid->eid_id;
440 #endif /* ! BACKSQL_ARBITRARY_KEY */
442 rc = attr_merge_normalize_one( bsi->bsi_e, ad_oc,
443 &bsi->bsi_oc->bom_oc->soc_cname,
444 bsi->bsi_op->o_tmpmemctx );
445 if ( rc != LDAP_SUCCESS ) {
446 entry_clean( bsi->bsi_e );
450 if ( bsi->bsi_attrs != NULL ) {
451 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
452 "custom attribute list\n", 0, 0, 0 );
453 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
454 backsql_at_map_rec **vat;
455 AttributeName *an = &bsi->bsi_attrs[ i ];
458 /* if one of the attributes listed here is
459 * a subtype of another, it must be ignored,
460 * because subtypes are already dealt with
461 * by backsql_supad2at()
463 for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
470 if ( is_at_subtype( an->an_desc->ad_type,
471 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
477 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
478 if ( rc != 0 || vat == NULL ) {
479 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
480 "attribute \"%s\" is not defined "
481 "for objectlass \"%s\"\n",
483 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
487 for ( j = 0; vat[j]; j++ ) {
488 backsql_get_attr_vals( vat[j], bsi );
497 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
498 "retrieving all attributes\n", 0, 0, 0 );
499 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
500 bsi, 0, AVL_INORDER );
503 if ( global_schemacheck ) {
504 const char *text = NULL;
505 char textbuf[ 1024 ];
506 size_t textlen = sizeof( textbuf );
507 struct berval bv[ 2 ];
511 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
512 bv[ 1 ].bv_val = NULL;
514 rc = structural_class( bv, &soc, NULL,
515 &text, textbuf, textlen );
516 if ( rc != LDAP_SUCCESS ) {
517 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
518 "structural_class() failed %d (%s)\n",
519 bsi->bsi_e->e_name.bv_val,
520 rc, text ? text : "" );
521 entry_clean( bsi->bsi_e );
525 if ( ( bsi->bsi_flags | BSQL_SF_ALL_OPER )
526 || an_find( bsi->bsi_attrs, &AllOper ) ) {
527 rc = attr_merge_normalize_one( bsi->bsi_e,
528 slap_schema.si_ad_structuralObjectClass,
529 &soc, bsi->bsi_op->o_tmpmemctx );
530 if ( rc != LDAP_SUCCESS ) {
531 entry_clean( bsi->bsi_e );
537 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
542 #endif /* SLAPD_SQL */