2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2004 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.
24 #include <sys/types.h>
25 #include "ac/string.h"
28 #include "proto-sql.h"
30 #ifdef BACKSQL_ARBITRARY_KEY
31 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
32 #endif /* BACKSQL_ARBITRARY_KEY */
35 backsql_free_entryID( backsql_entryID *id, int freeit )
37 backsql_entryID *next;
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 )
47 free( id->eid_dn.bv_val );
48 BER_BVZERO( &id->eid_dn );
51 free( id->eid_ndn.bv_val );
52 BER_BVZERO( &id->eid_ndn );
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 );
61 if ( id->eid_keyval.bv_val ) {
62 free( id->eid_keyval.bv_val );
63 BER_BVZERO( &id->eid_keyval );
65 #endif /* BACKSQL_ARBITRARY_KEY */
75 * NOTE: the dn must be normalized
86 backsql_info *bi = op->o_bd->be_private;
87 SQLHSTMT sth = SQL_NULL_HSTMT;
91 struct berval realndn = BER_BVNULL;
94 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
99 * NOTE: id can be NULL; in this case, the function
100 * simply checks whether the DN can be successfully
101 * turned into an ID, returning LDAP_SUCCESS for
102 * positive cases, or the most appropriate error
105 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n",
106 ndn->bv_val, id == NULL ? " (no ID)" : "", 0 );
108 if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
109 Debug( LDAP_DEBUG_TRACE,
110 "backsql_dn2id(): DN \"%s\" (%ld bytes) "
111 "exceeds max DN length (%d):\n",
112 ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
116 /* return baseObject if available and matches */
117 /* FIXME: if ndn is already mucked, we cannot check this */
118 if ( bi->sql_baseObject != NULL &&
119 dn_match( ndn, &bi->sql_baseObject->e_nname ) )
122 #ifdef BACKSQL_ARBITRARY_KEY
123 ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
124 ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
125 #else /* ! BACKSQL_ARBITRARY_KEY */
126 id->eid_id = BACKSQL_BASEOBJECT_ID;
127 id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
128 #endif /* ! BACKSQL_ARBITRARY_KEY */
129 id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
131 ber_dupbv( &id->eid_ndn, &bi->sql_baseObject->e_nname );
132 ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_name );
141 Debug( LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0 );
142 assert( bi->sql_id_query );
143 rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
144 if ( rc != SQL_SUCCESS ) {
145 Debug( LDAP_DEBUG_TRACE,
146 "backsql_dn2id(): error preparing SQL:\n%s",
147 bi->sql_id_query, 0, 0);
148 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
155 if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
156 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
157 "backsql_api_dn2odbc(\"%s\") failed\n",
158 ndn->bv_val, realndn.bv_val, 0 );
164 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
166 * Prepare an upper cased, byte reversed version
167 * that can be searched using indexes
170 for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
172 upperdn[ i ] = realndn.bv_val[ j ];
175 ldap_pvt_str2upper( upperdn );
177 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n",
179 ber_str2bv( upperdn, 0, 0, &tbbDN );
182 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
183 AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
184 ldap_pvt_str2upper( upperdn );
185 Debug( LDAP_DEBUG_TRACE,
186 "==>backsql_dn2id(): upperdn=\"%s\"\n",
188 ber_str2bv( upperdn, 0, 0, &tbbDN );
195 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
196 if ( rc != SQL_SUCCESS) {
198 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
199 "error binding dn=\"%s\" parameter:\n",
200 tbbDN.bv_val, 0, 0 );
201 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
206 rc = SQLExecute( sth );
207 if ( rc != SQL_SUCCESS ) {
208 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
209 "error executing query (\"%s\", \"%s\"):\n",
210 bi->sql_id_query, tbbDN.bv_val, 0 );
211 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
216 backsql_BindRowAsStrings( sth, &row );
217 rc = SQLFetch( sth );
218 if ( BACKSQL_SUCCESS( rc ) ) {
222 snprintf( buf, sizeof(buf),
223 "id=%s keyval=%s oc_id=%s dn=%s",
224 row.cols[ 0 ], row.cols[ 1 ],
225 row.cols[ 2 ], row.cols[ 3 ] );
226 Debug( LDAP_DEBUG_TRACE,
227 "<==backsql_dn2id(): %s\n", buf, 0, 0 );
228 #endif /* LDAP_DEBUG */
234 #ifdef BACKSQL_ARBITRARY_KEY
235 ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
236 ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
237 #else /* ! BACKSQL_ARBITRARY_KEY */
238 id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
239 id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
240 #endif /* ! BACKSQL_ARBITRARY_KEY */
241 id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
243 ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
245 if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
249 res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, NULL );
250 if ( res != LDAP_SUCCESS ) {
251 Debug( LDAP_DEBUG_TRACE,
252 "<==backsql_dn2id(\"%s\"): "
253 "dnPrettyNormal failed (%d: %s)\n",
255 ldap_err2string( res ) );
258 (void)backsql_free_entryID( id, 0 );
261 if ( dn.bv_val != row.cols[ 3 ] ) {
270 res = LDAP_NO_SUCH_OBJECT;
271 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
274 backsql_FreeRow( &row );
277 if ( sth != SQL_NULL_HSTMT ) {
278 SQLFreeStmt( sth, SQL_DROP );
281 if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
282 ch_free( realndn.bv_val );
289 backsql_count_children(
293 unsigned long *nchildren )
295 SQLHSTMT sth = SQL_NULL_HSTMT;
298 int res = LDAP_SUCCESS;
300 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
303 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
304 Debug( LDAP_DEBUG_TRACE,
305 "backsql_count_children(): DN \"%s\" (%ld bytes) "
306 "exceeds max DN length (%d):\n",
307 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
312 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
313 bi->sql_has_children_query, 0, 0);
314 assert( bi->sql_has_children_query );
315 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
316 if ( rc != SQL_SUCCESS ) {
317 Debug( LDAP_DEBUG_TRACE,
318 "backsql_count_children(): error preparing SQL:\n%s",
319 bi->sql_has_children_query, 0, 0);
320 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
321 SQLFreeStmt( sth, SQL_DROP );
325 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
326 if ( rc != SQL_SUCCESS) {
328 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
329 "error binding dn=\"%s\" parameter:\n",
331 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
332 SQLFreeStmt( sth, SQL_DROP );
336 rc = SQLExecute( sth );
337 if ( rc != SQL_SUCCESS ) {
338 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
339 "error executing query (\"%s\", \"%s\"):\n",
340 bi->sql_has_children_query, dn->bv_val, 0 );
341 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
342 SQLFreeStmt( sth, SQL_DROP );
346 backsql_BindRowAsStrings( sth, &row );
348 rc = SQLFetch( sth );
349 if ( BACKSQL_SUCCESS( rc ) ) {
352 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
353 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
354 /* FIXME: braindead RDBMSes return
355 * a fractional number from COUNT!
363 backsql_FreeRow( &row );
365 SQLFreeStmt( sth, SQL_DROP );
367 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
374 backsql_has_children(
379 unsigned long nchildren;
382 rc = backsql_count_children( bi, dbh, dn, &nchildren );
384 if ( rc == LDAP_SUCCESS ) {
385 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
392 backsql_get_attr_vals( void *v_at, void *v_bsi )
394 backsql_at_map_rec *at = v_at;
395 backsql_srch_info *bsi = v_bsi;
396 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
398 SQLHSTMT sth = SQL_NULL_HSTMT;
405 #ifdef BACKSQL_ARBITRARY_KEY
406 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
407 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
408 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
409 bsi->bsi_c_eid->eid_keyval.bv_val );
410 #else /* ! BACKSQL_ARBITRARY_KEY */
411 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
412 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
413 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
414 bsi->bsi_c_eid->eid_keyval );
415 #endif /* ! BACKSQL_ARBITRARY_KEY */
417 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
418 if ( rc != SQL_SUCCESS ) {
419 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
420 "error preparing query: %s\n", at->bam_query, 0, 0 );
421 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
425 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
426 &bsi->bsi_c_eid->eid_keyval );
427 if ( rc != SQL_SUCCESS ) {
428 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
429 "error binding key value parameter\n", 0, 0, 0 );
434 #ifdef BACKSQL_ARBITRARY_KEY
435 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
436 "query=\"%s\" keyval=%s\n", at->bam_query,
437 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
438 #else /* !BACKSQL_ARBITRARY_KEY */
439 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
440 "query=\"%s\" keyval=%d\n", at->bam_query,
441 bsi->bsi_c_eid->eid_keyval, 0 );
442 #endif /* ! BACKSQL_ARBITRARY_KEY */
443 #endif /* BACKSQL_TRACE */
445 rc = SQLExecute( sth );
446 if ( ! BACKSQL_SUCCESS( rc ) ) {
447 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
448 "error executing attribute query \"%s\"\n",
449 at->bam_query, 0, 0 );
450 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
451 SQLFreeStmt( sth, SQL_DROP );
455 backsql_BindRowAsStrings( sth, &row );
457 rc = SQLFetch( sth );
458 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
459 for ( i = 0; i < row.ncols; i++ ) {
460 if ( row.value_len[ i ] > 0 ) {
463 bv.bv_val = row.cols[ i ];
465 bv.bv_len = row.col_prec[ i ];
468 * FIXME: what if a binary
471 bv.bv_len = strlen( row.cols[ i ] );
473 backsql_entry_addattr( bsi->bsi_e,
474 &row.col_names[ i ], &bv,
475 bsi->bsi_op->o_tmpmemctx );
478 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
479 (int)row.col_prec[ i ], 0, 0 );
481 Debug( LDAP_DEBUG_TRACE, "NULL value "
482 "in this row for attribute \"%s\"\n",
483 row.col_names[ i ].bv_val, 0, 0 );
484 #endif /* BACKSQL_TRACE */
489 backsql_FreeRow( &row );
490 SQLFreeStmt( sth, SQL_DROP );
491 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
493 if ( at->bam_next ) {
494 return backsql_get_attr_vals( at->bam_next, v_bsi );
501 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
503 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
506 AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
508 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
510 assert( bsi->bsi_e );
512 memset( bsi->bsi_e, 0, sizeof( Entry ) );
514 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
517 e = entry_dup( bi->sql_baseObject );
519 return LDAP_NO_MEMORY;
527 ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, bsi->bsi_op->o_tmpmemctx );
528 ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, bsi->bsi_op->o_tmpmemctx );
530 bsi->bsi_e->e_attrs = NULL;
531 bsi->bsi_e->e_private = NULL;
533 bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
535 bsi->bsi_c_eid = eid;
537 #ifndef BACKSQL_ARBITRARY_KEY
538 bsi->bsi_e->e_id = eid->eid_id;
539 #endif /* ! BACKSQL_ARBITRARY_KEY */
541 rc = attr_merge_normalize_one( bsi->bsi_e, ad_oc,
542 &bsi->bsi_oc->bom_oc->soc_cname,
543 bsi->bsi_op->o_tmpmemctx );
544 if ( rc != LDAP_SUCCESS ) {
545 entry_clean( bsi->bsi_e );
549 if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
551 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
552 "retrieving all attributes\n", 0, 0, 0 );
553 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
554 bsi, 0, AVL_INORDER );
557 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
558 "custom attribute list\n", 0, 0, 0 );
559 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
560 backsql_at_map_rec **vat;
561 AttributeName *an = &bsi->bsi_attrs[ i ];
564 /* if one of the attributes listed here is
565 * a subtype of another, it must be ignored,
566 * because subtypes are already dealt with
567 * by backsql_supad2at()
569 for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
576 if ( is_at_subtype( an->an_desc->ad_type,
577 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
583 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
584 if ( rc != 0 || vat == NULL ) {
585 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
586 "attribute \"%s\" is not defined "
587 "for objectlass \"%s\"\n",
589 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
593 for ( j = 0; vat[j]; j++ ) {
594 backsql_get_attr_vals( vat[j], bsi );
603 if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
604 Attribute *a_entryUUID,
607 a_entryUUID = backsql_operational_entryUUID( bi, eid );
608 if ( a_entryUUID != NULL ) {
609 for ( ap = &bsi->bsi_e->e_attrs;
611 ap = &(*ap)->a_next );
617 if ( global_schemacheck ) {
618 const char *text = NULL;
619 char textbuf[ 1024 ];
620 size_t textlen = sizeof( textbuf );
621 struct berval bv[ 2 ];
625 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
626 bv[ 1 ].bv_val = NULL;
628 rc = structural_class( bv, &soc, NULL,
629 &text, textbuf, textlen );
630 if ( rc != LDAP_SUCCESS ) {
631 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
632 "structural_class() failed %d (%s)\n",
633 bsi->bsi_e->e_name.bv_val,
634 rc, text ? text : "" );
635 entry_clean( bsi->bsi_e );
639 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
640 || an_find( bsi->bsi_attrs, &AllOper )
641 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
643 rc = attr_merge_normalize_one( bsi->bsi_e,
644 slap_schema.si_ad_structuralObjectClass,
645 &soc, bsi->bsi_op->o_tmpmemctx );
646 if ( rc != LDAP_SUCCESS ) {
647 entry_clean( bsi->bsi_e );
654 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );