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.
6 * Portions Copyright 2002 Pierangelo Masarati.
7 * Portions Copyright 2004 Mark Adamson.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
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>.
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.
27 #include <sys/types.h>
28 #include "ac/string.h"
31 #include "proto-sql.h"
33 #ifdef BACKSQL_ARBITRARY_KEY
34 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
35 #endif /* BACKSQL_ARBITRARY_KEY */
38 backsql_free_entryID( backsql_entryID *id, int freeit )
40 backsql_entryID *next;
46 if ( !BER_BVISNULL( &id->eid_ndn ) ) {
47 if ( !BER_BVISNULL( &id->eid_dn )
48 && id->eid_dn.bv_val != id->eid_ndn.bv_val )
50 free( id->eid_dn.bv_val );
51 BER_BVZERO( &id->eid_dn );
54 free( id->eid_ndn.bv_val );
55 BER_BVZERO( &id->eid_ndn );
58 #ifdef BACKSQL_ARBITRARY_KEY
59 if ( id->eid_id.bv_val ) {
60 free( id->eid_id.bv_val );
61 BER_BVZERO( &id->eid_id );
64 if ( id->eid_keyval.bv_val ) {
65 free( id->eid_keyval.bv_val );
66 BER_BVZERO( &id->eid_keyval );
68 #endif /* BACKSQL_ARBITRARY_KEY */
78 * NOTE: the dn must be normalized
89 backsql_info *bi = op->o_bd->be_private;
90 SQLHSTMT sth = SQL_NULL_HSTMT;
94 struct berval realndn = BER_BVNULL;
97 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
102 * NOTE: id can be NULL; in this case, the function
103 * simply checks whether the DN can be successfully
104 * turned into an ID, returning LDAP_SUCCESS for
105 * positive cases, or the most appropriate error
108 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n",
109 ndn->bv_val, id == NULL ? " (no ID)" : "", 0 );
111 if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
112 Debug( LDAP_DEBUG_TRACE,
113 "backsql_dn2id(): DN \"%s\" (%ld bytes) "
114 "exceeds max DN length (%d):\n",
115 ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
119 /* return baseObject if available and matches */
120 /* FIXME: if ndn is already mucked, we cannot check this */
121 if ( bi->sql_baseObject != NULL &&
122 dn_match( ndn, &bi->sql_baseObject->e_nname ) )
125 #ifdef BACKSQL_ARBITRARY_KEY
126 ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
127 ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
128 #else /* ! BACKSQL_ARBITRARY_KEY */
129 id->eid_id = BACKSQL_BASEOBJECT_ID;
130 id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
131 #endif /* ! BACKSQL_ARBITRARY_KEY */
132 id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
134 ber_dupbv( &id->eid_ndn, &bi->sql_baseObject->e_nname );
135 ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_name );
144 Debug( LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0 );
145 assert( bi->sql_id_query );
146 rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
147 if ( rc != SQL_SUCCESS ) {
148 Debug( LDAP_DEBUG_TRACE,
149 "backsql_dn2id(): error preparing SQL:\n%s",
150 bi->sql_id_query, 0, 0);
151 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
158 if ( backsql_api_dn2odbc( op, rs, &realndn ) ) {
159 Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): "
160 "backsql_api_dn2odbc(\"%s\") failed\n",
161 ndn->bv_val, realndn.bv_val, 0 );
167 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
169 * Prepare an upper cased, byte reversed version
170 * that can be searched using indexes
173 for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--)
175 upperdn[ i ] = realndn.bv_val[ j ];
178 ldap_pvt_str2upper( upperdn );
180 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n",
182 ber_str2bv( upperdn, 0, 0, &tbbDN );
185 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
186 AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 );
187 ldap_pvt_str2upper( upperdn );
188 Debug( LDAP_DEBUG_TRACE,
189 "==>backsql_dn2id(): upperdn=\"%s\"\n",
191 ber_str2bv( upperdn, 0, 0, &tbbDN );
198 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
199 if ( rc != SQL_SUCCESS) {
201 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
202 "error binding dn=\"%s\" parameter:\n",
203 tbbDN.bv_val, 0, 0 );
204 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
209 rc = SQLExecute( sth );
210 if ( rc != SQL_SUCCESS ) {
211 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
212 "error executing query (\"%s\", \"%s\"):\n",
213 bi->sql_id_query, tbbDN.bv_val, 0 );
214 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
219 backsql_BindRowAsStrings( sth, &row );
220 rc = SQLFetch( sth );
221 if ( BACKSQL_SUCCESS( rc ) ) {
225 snprintf( buf, sizeof(buf),
226 "id=%s keyval=%s oc_id=%s dn=%s",
227 row.cols[ 0 ], row.cols[ 1 ],
228 row.cols[ 2 ], row.cols[ 3 ] );
229 Debug( LDAP_DEBUG_TRACE,
230 "<==backsql_dn2id(): %s\n", buf, 0, 0 );
231 #endif /* LDAP_DEBUG */
237 #ifdef BACKSQL_ARBITRARY_KEY
238 ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
239 ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
240 #else /* ! BACKSQL_ARBITRARY_KEY */
241 id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
242 id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
243 #endif /* ! BACKSQL_ARBITRARY_KEY */
244 id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
246 ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
248 if ( backsql_api_odbc2dn( op, rs, &dn ) ) {
252 res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, NULL );
253 if ( res != LDAP_SUCCESS ) {
254 Debug( LDAP_DEBUG_TRACE,
255 "<==backsql_dn2id(\"%s\"): "
256 "dnPrettyNormal failed (%d: %s)\n",
258 ldap_err2string( res ) );
261 (void)backsql_free_entryID( id, 0 );
264 if ( dn.bv_val != row.cols[ 3 ] ) {
273 res = LDAP_NO_SUCH_OBJECT;
274 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
277 backsql_FreeRow( &row );
280 if ( sth != SQL_NULL_HSTMT ) {
281 SQLFreeStmt( sth, SQL_DROP );
284 if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) {
285 ch_free( realndn.bv_val );
292 backsql_count_children(
296 unsigned long *nchildren )
298 SQLHSTMT sth = SQL_NULL_HSTMT;
301 int res = LDAP_SUCCESS;
303 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
306 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
307 Debug( LDAP_DEBUG_TRACE,
308 "backsql_count_children(): DN \"%s\" (%ld bytes) "
309 "exceeds max DN length (%d):\n",
310 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
315 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
316 bi->sql_has_children_query, 0, 0);
317 assert( bi->sql_has_children_query );
318 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
319 if ( rc != SQL_SUCCESS ) {
320 Debug( LDAP_DEBUG_TRACE,
321 "backsql_count_children(): error preparing SQL:\n%s",
322 bi->sql_has_children_query, 0, 0);
323 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
324 SQLFreeStmt( sth, SQL_DROP );
328 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
329 if ( rc != SQL_SUCCESS) {
331 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
332 "error binding dn=\"%s\" parameter:\n",
334 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
335 SQLFreeStmt( sth, SQL_DROP );
339 rc = SQLExecute( sth );
340 if ( rc != SQL_SUCCESS ) {
341 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
342 "error executing query (\"%s\", \"%s\"):\n",
343 bi->sql_has_children_query, dn->bv_val, 0 );
344 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
345 SQLFreeStmt( sth, SQL_DROP );
349 backsql_BindRowAsStrings( sth, &row );
351 rc = SQLFetch( sth );
352 if ( BACKSQL_SUCCESS( rc ) ) {
355 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
356 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
357 /* FIXME: braindead RDBMSes return
358 * a fractional number from COUNT!
366 backsql_FreeRow( &row );
368 SQLFreeStmt( sth, SQL_DROP );
370 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
377 backsql_has_children(
382 unsigned long nchildren;
385 rc = backsql_count_children( bi, dbh, dn, &nchildren );
387 if ( rc == LDAP_SUCCESS ) {
388 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
395 backsql_get_attr_vals( void *v_at, void *v_bsi )
397 backsql_at_map_rec *at = v_at;
398 backsql_srch_info *bsi = v_bsi;
399 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
401 SQLHSTMT sth = SQL_NULL_HSTMT;
408 #ifdef BACKSQL_ARBITRARY_KEY
409 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
410 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
411 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
412 bsi->bsi_c_eid->eid_keyval.bv_val );
413 #else /* ! BACKSQL_ARBITRARY_KEY */
414 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
415 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
416 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
417 bsi->bsi_c_eid->eid_keyval );
418 #endif /* ! BACKSQL_ARBITRARY_KEY */
420 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
421 if ( rc != SQL_SUCCESS ) {
422 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
423 "error preparing query: %s\n", at->bam_query, 0, 0 );
424 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
428 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
429 &bsi->bsi_c_eid->eid_keyval );
430 if ( rc != SQL_SUCCESS ) {
431 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
432 "error binding key value parameter\n", 0, 0, 0 );
437 #ifdef BACKSQL_ARBITRARY_KEY
438 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
439 "query=\"%s\" keyval=%s\n", at->bam_query,
440 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
441 #else /* !BACKSQL_ARBITRARY_KEY */
442 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
443 "query=\"%s\" keyval=%d\n", at->bam_query,
444 bsi->bsi_c_eid->eid_keyval, 0 );
445 #endif /* ! BACKSQL_ARBITRARY_KEY */
446 #endif /* BACKSQL_TRACE */
448 rc = SQLExecute( sth );
449 if ( ! BACKSQL_SUCCESS( rc ) ) {
450 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
451 "error executing attribute query \"%s\"\n",
452 at->bam_query, 0, 0 );
453 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
454 SQLFreeStmt( sth, SQL_DROP );
458 backsql_BindRowAsStrings( sth, &row );
460 rc = SQLFetch( sth );
461 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
462 for ( i = 0; i < row.ncols; i++ ) {
463 if ( row.value_len[ i ] > 0 ) {
466 bv.bv_val = row.cols[ i ];
468 bv.bv_len = row.col_prec[ i ];
471 * FIXME: what if a binary
474 bv.bv_len = strlen( row.cols[ i ] );
476 backsql_entry_addattr( bsi->bsi_e,
477 &row.col_names[ i ], &bv,
478 bsi->bsi_op->o_tmpmemctx );
481 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
482 (int)row.col_prec[ i ], 0, 0 );
484 Debug( LDAP_DEBUG_TRACE, "NULL value "
485 "in this row for attribute \"%s\"\n",
486 row.col_names[ i ].bv_val, 0, 0 );
487 #endif /* BACKSQL_TRACE */
492 backsql_FreeRow( &row );
493 SQLFreeStmt( sth, SQL_DROP );
494 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
496 if ( at->bam_next ) {
497 return backsql_get_attr_vals( at->bam_next, v_bsi );
504 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
506 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
510 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
512 assert( bsi->bsi_e );
514 memset( bsi->bsi_e, 0, sizeof( Entry ) );
516 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
519 e = entry_dup( bi->sql_baseObject );
521 return LDAP_NO_MEMORY;
529 ber_dupbv( &bsi->bsi_e->e_name, &eid->eid_dn );
530 ber_dupbv( &bsi->bsi_e->e_nname, &eid->eid_ndn );
532 bsi->bsi_e->e_attrs = NULL;
533 bsi->bsi_e->e_private = NULL;
535 bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
537 bsi->bsi_c_eid = eid;
539 #ifndef BACKSQL_ARBITRARY_KEY
540 bsi->bsi_e->e_id = eid->eid_id;
541 #endif /* ! BACKSQL_ARBITRARY_KEY */
543 rc = attr_merge_normalize_one( bsi->bsi_e,
544 slap_schema.si_ad_objectClass,
545 &bsi->bsi_oc->bom_oc->soc_cname,
546 bsi->bsi_op->o_tmpmemctx );
547 if ( rc != LDAP_SUCCESS ) {
548 entry_clean( bsi->bsi_e );
552 if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) )
554 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
555 "retrieving all attributes\n", 0, 0, 0 );
556 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
557 bsi, 0, AVL_INORDER );
560 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
561 "custom attribute list\n", 0, 0, 0 );
562 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
563 backsql_at_map_rec **vat;
564 AttributeName *an = &bsi->bsi_attrs[ i ];
567 /* if one of the attributes listed here is
568 * a subtype of another, it must be ignored,
569 * because subtypes are already dealt with
570 * by backsql_supad2at()
572 for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
579 if ( is_at_subtype( an->an_desc->ad_type,
580 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
586 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
587 if ( rc != 0 || vat == NULL ) {
588 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
589 "attribute \"%s\" is not defined "
590 "for objectlass \"%s\"\n",
592 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
596 for ( j = 0; vat[j]; j++ ) {
597 backsql_get_attr_vals( vat[j], bsi );
606 if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) {
607 Attribute *a_entryUUID,
610 a_entryUUID = backsql_operational_entryUUID( bi, eid );
611 if ( a_entryUUID != NULL ) {
612 for ( ap = &bsi->bsi_e->e_attrs;
614 ap = &(*ap)->a_next );
620 if ( global_schemacheck ) {
621 const char *text = NULL;
622 char textbuf[ 1024 ];
623 size_t textlen = sizeof( textbuf );
624 struct berval bv[ 2 ];
628 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
629 bv[ 1 ].bv_val = NULL;
631 rc = structural_class( bv, &soc, NULL,
632 &text, textbuf, textlen );
633 if ( rc != LDAP_SUCCESS ) {
634 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
635 "structural_class() failed %d (%s)\n",
636 bsi->bsi_e->e_name.bv_val,
637 rc, text ? text : "" );
638 entry_clean( bsi->bsi_e );
642 if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER )
643 || an_find( bsi->bsi_attrs, &AllOper )
644 || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) )
646 rc = attr_merge_normalize_one( bsi->bsi_e,
647 slap_schema.si_ad_structuralObjectClass,
648 &soc, bsi->bsi_op->o_tmpmemctx );
649 if ( rc != LDAP_SUCCESS ) {
650 entry_clean( bsi->bsi_e );
657 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );