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.
26 #include <sys/types.h>
27 #include "ac/string.h"
30 #include "proto-sql.h"
32 #ifdef BACKSQL_ARBITRARY_KEY
33 struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
34 #endif /* BACKSQL_ARBITRARY_KEY */
37 backsql_free_entryID( backsql_entryID *id, int freeit )
39 backsql_entryID *next;
45 if ( !BER_BVISNULL( &id->eid_ndn ) ) {
46 if ( !BER_BVISNULL( &id->eid_dn )
47 && id->eid_dn.bv_val != id->eid_ndn.bv_val )
49 free( id->eid_dn.bv_val );
50 BER_BVZERO( &id->eid_dn );
53 free( id->eid_ndn.bv_val );
54 BER_BVZERO( &id->eid_ndn );
57 #ifdef BACKSQL_ARBITRARY_KEY
58 if ( id->eid_id.bv_val ) {
59 free( id->eid_id.bv_val );
60 BER_BVZERO( &id->eid_id );
63 if ( id->eid_keyval.bv_val ) {
64 free( id->eid_keyval.bv_val );
65 BER_BVZERO( &id->eid_keyval );
67 #endif /* BACKSQL_ARBITRARY_KEY */
77 * NOTE: the dn must be normalized
92 char upperdn[ BACKSQL_MAX_DN_LEN + 1 ];
97 * NOTE: id can be NULL; in this case, the function
98 * simply checks whether the DN can be successfully
99 * turned into an ID, returning LDAP_SUCCESS for
100 * positive cases, or the most appropriate error
103 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n",
104 ndn->bv_val, id == NULL ? " (no ID)" : "", 0 );
106 if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) {
107 Debug( LDAP_DEBUG_TRACE,
108 "backsql_dn2id(): DN \"%s\" (%ld bytes) "
109 "exceeds max DN length (%d):\n",
110 ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN );
114 /* return baseObject if available and matches */
115 if ( bi->sql_baseObject != NULL && dn_match( ndn, &bi->sql_baseObject->e_nname ) ) {
117 #ifdef BACKSQL_ARBITRARY_KEY
118 ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
119 ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
120 #else /* ! BACKSQL_ARBITRARY_KEY */
121 id->eid_id = BACKSQL_BASEOBJECT_ID;
122 id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
123 #endif /* ! BACKSQL_ARBITRARY_KEY */
124 id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
126 ber_dupbv( &id->eid_ndn, &bi->sql_baseObject->e_nname );
127 ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_name );
136 Debug( LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0 );
137 assert( bi->sql_id_query );
138 rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
139 if ( rc != SQL_SUCCESS ) {
140 Debug( LDAP_DEBUG_TRACE,
141 "backsql_dn2id(): error preparing SQL:\n%s",
142 bi->sql_id_query, 0, 0);
143 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
144 SQLFreeStmt( sth, SQL_DROP );
148 if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) {
150 * Prepare an upper cased, byte reversed version
151 * that can be searched using indexes
154 for ( i = 0, j = ndn->bv_len - 1; ndn->bv_val[ i ]; i++, j--) {
155 upperdn[ i ] = ndn->bv_val[ j ];
158 ldap_pvt_str2upper( upperdn );
160 Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n",
162 ber_str2bv( upperdn, 0, 0, &tbbDN );
165 if ( BACKSQL_USE_REVERSE_DN( bi ) ) {
166 AC_MEMCPY( upperdn, ndn->bv_val, ndn->bv_len + 1 );
167 ldap_pvt_str2upper( upperdn );
168 Debug( LDAP_DEBUG_TRACE,
169 "==>backsql_dn2id(): upperdn=\"%s\"\n",
171 ber_str2bv( upperdn, 0, 0, &tbbDN );
178 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN );
179 if ( rc != SQL_SUCCESS) {
181 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
182 "error binding dn=\"%s\" parameter:\n",
183 tbbDN.bv_val, 0, 0 );
184 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
185 SQLFreeStmt( sth, SQL_DROP );
189 rc = SQLExecute( sth );
190 if ( rc != SQL_SUCCESS ) {
191 Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): "
192 "error executing query (\"%s\", \"%s\"):\n",
193 bi->sql_id_query, tbbDN.bv_val, 0 );
194 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
195 SQLFreeStmt( sth, SQL_DROP );
199 backsql_BindRowAsStrings( sth, &row );
200 rc = SQLFetch( sth );
201 if ( BACKSQL_SUCCESS( rc ) ) {
205 snprintf( buf, sizeof(buf),
206 "id=%s keyval=%s oc_id=%s dn=%s",
207 row.cols[ 0 ], row.cols[ 1 ],
208 row.cols[ 2 ], row.cols[ 3 ] );
209 Debug( LDAP_DEBUG_TRACE,
210 "<==backsql_dn2id(): %s\n", buf, 0, 0 );
211 #endif /* LDAP_DEBUG */
217 #ifdef BACKSQL_ARBITRARY_KEY
218 ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id );
219 ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval );
220 #else /* ! BACKSQL_ARBITRARY_KEY */
221 id->eid_id = strtol( row.cols[ 0 ], NULL, 0 );
222 id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 );
223 #endif /* ! BACKSQL_ARBITRARY_KEY */
224 id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 );
226 ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
228 res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, NULL );
229 if ( res != LDAP_SUCCESS ) {
230 Debug( LDAP_DEBUG_TRACE,
231 "<==backsql_dn2id(\"%s\"): "
232 "dnPrettyNormal failed (%d: %s)\n",
234 ldap_err2string( res ) );
237 (void)backsql_free_entryID( id, 0 );
244 res = LDAP_NO_SUCH_OBJECT;
245 Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): no match\n",
248 backsql_FreeRow( &row );
250 SQLFreeStmt( sth, SQL_DROP );
255 backsql_count_children(
259 unsigned long *nchildren )
264 int res = LDAP_SUCCESS;
266 Debug( LDAP_DEBUG_TRACE, "==>backsql_count_children(): dn=\"%s\"\n",
269 if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) {
270 Debug( LDAP_DEBUG_TRACE,
271 "backsql_count_children(): DN \"%s\" (%ld bytes) "
272 "exceeds max DN length (%d):\n",
273 dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
278 Debug(LDAP_DEBUG_TRACE, "children id query \"%s\"\n",
279 bi->sql_has_children_query, 0, 0);
280 assert( bi->sql_has_children_query );
281 rc = backsql_Prepare( dbh, &sth, bi->sql_has_children_query, 0 );
282 if ( rc != SQL_SUCCESS ) {
283 Debug( LDAP_DEBUG_TRACE,
284 "backsql_count_children(): error preparing SQL:\n%s",
285 bi->sql_has_children_query, 0, 0);
286 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
287 SQLFreeStmt( sth, SQL_DROP );
291 rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, dn );
292 if ( rc != SQL_SUCCESS) {
294 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
295 "error binding dn=\"%s\" parameter:\n",
297 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
298 SQLFreeStmt( sth, SQL_DROP );
302 rc = SQLExecute( sth );
303 if ( rc != SQL_SUCCESS ) {
304 Debug( LDAP_DEBUG_TRACE, "backsql_count_children(): "
305 "error executing query (\"%s\", \"%s\"):\n",
306 bi->sql_has_children_query, dn->bv_val, 0 );
307 backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc );
308 SQLFreeStmt( sth, SQL_DROP );
312 backsql_BindRowAsStrings( sth, &row );
314 rc = SQLFetch( sth );
315 if ( BACKSQL_SUCCESS( rc ) ) {
318 *nchildren = strtol( row.cols[ 0 ], &end, 0 );
319 if ( end[ 0 ] != '\0' && end[0] != '.' ) {
320 /* FIXME: braindead RDBMSes return
321 * a fractional number from COUNT!
329 backsql_FreeRow( &row );
331 SQLFreeStmt( sth, SQL_DROP );
333 Debug( LDAP_DEBUG_TRACE, "<==backsql_count_children(): %lu\n",
340 backsql_has_children(
345 unsigned long nchildren;
348 rc = backsql_count_children( bi, dbh, dn, &nchildren );
350 if ( rc == LDAP_SUCCESS ) {
351 return nchildren > 0 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
358 backsql_get_attr_vals( void *v_at, void *v_bsi )
360 backsql_at_map_rec *at = v_at;
361 backsql_srch_info *bsi = v_bsi;
362 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
371 #ifdef BACKSQL_ARBITRARY_KEY
372 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
373 "oc=\"%s\" attr=\"%s\" keyval=%s\n",
374 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
375 bsi->bsi_c_eid->eid_keyval.bv_val );
376 #else /* ! BACKSQL_ARBITRARY_KEY */
377 Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
378 "oc=\"%s\" attr=\"%s\" keyval=%ld\n",
379 BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val,
380 bsi->bsi_c_eid->eid_keyval );
381 #endif /* ! BACKSQL_ARBITRARY_KEY */
383 rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 );
384 if ( rc != SQL_SUCCESS ) {
385 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
386 "error preparing query: %s\n", at->bam_query, 0, 0 );
387 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
391 rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT,
392 &bsi->bsi_c_eid->eid_keyval );
393 if ( rc != SQL_SUCCESS ) {
394 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
395 "error binding key value parameter\n", 0, 0, 0 );
400 #ifdef BACKSQL_ARBITRARY_KEY
401 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
402 "query=\"%s\" keyval=%s\n", at->bam_query,
403 bsi->bsi_c_eid->eid_keyval.bv_val, 0 );
404 #else /* !BACKSQL_ARBITRARY_KEY */
405 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
406 "query=\"%s\" keyval=%d\n", at->bam_query,
407 bsi->bsi_c_eid->eid_keyval, 0 );
408 #endif /* ! BACKSQL_ARBITRARY_KEY */
409 #endif /* BACKSQL_TRACE */
411 rc = SQLExecute( sth );
412 if ( ! BACKSQL_SUCCESS( rc ) ) {
413 Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_values(): "
414 "error executing attribute query \"%s\"\n",
415 at->bam_query, 0, 0 );
416 backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc );
417 SQLFreeStmt( sth, SQL_DROP );
421 backsql_BindRowAsStrings( sth, &row );
423 rc = SQLFetch( sth );
424 for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
425 for ( i = 0; i < row.ncols; i++ ) {
426 if ( row.value_len[ i ] > 0 ) {
429 bv.bv_val = row.cols[ i ];
431 bv.bv_len = row.col_prec[ i ];
434 * FIXME: what if a binary
437 bv.bv_len = strlen( row.cols[ i ] );
439 backsql_entry_addattr( bsi->bsi_e,
440 &row.col_names[ i ], &bv,
441 bsi->bsi_op->o_tmpmemctx );
444 Debug( LDAP_DEBUG_TRACE, "prec=%d\n",
445 (int)row.col_prec[ i ], 0, 0 );
447 Debug( LDAP_DEBUG_TRACE, "NULL value "
448 "in this row for attribute \"%s\"\n",
449 row.col_names[ i ].bv_val, 0, 0 );
450 #endif /* BACKSQL_TRACE */
455 backsql_FreeRow( &row );
456 SQLFreeStmt( sth, SQL_DROP );
457 Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 );
459 if ( at->bam_next ) {
460 return backsql_get_attr_vals( at->bam_next, v_bsi );
467 backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
469 backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
472 AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
474 Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 );
476 assert( bsi->bsi_e );
478 memset( bsi->bsi_e, 0, sizeof( Entry ) );
480 if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
483 e = entry_dup( bi->sql_baseObject );
485 return LDAP_NO_MEMORY;
493 ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, bsi->bsi_op->o_tmpmemctx );
494 ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, bsi->bsi_op->o_tmpmemctx );
496 bsi->bsi_e->e_attrs = NULL;
497 bsi->bsi_e->e_private = NULL;
499 bsi->bsi_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private,
501 bsi->bsi_c_eid = eid;
503 #ifndef BACKSQL_ARBITRARY_KEY
504 bsi->bsi_e->e_id = eid->eid_id;
505 #endif /* ! BACKSQL_ARBITRARY_KEY */
507 rc = attr_merge_normalize_one( bsi->bsi_e, ad_oc,
508 &bsi->bsi_oc->bom_oc->soc_cname,
509 bsi->bsi_op->o_tmpmemctx );
510 if ( rc != LDAP_SUCCESS ) {
511 entry_clean( bsi->bsi_e );
515 if ( bsi->bsi_attrs != NULL ) {
516 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
517 "custom attribute list\n", 0, 0, 0 );
518 for ( i = 0; bsi->bsi_attrs[ i ].an_name.bv_val; i++ ) {
519 backsql_at_map_rec **vat;
520 AttributeName *an = &bsi->bsi_attrs[ i ];
523 /* if one of the attributes listed here is
524 * a subtype of another, it must be ignored,
525 * because subtypes are already dealt with
526 * by backsql_supad2at()
528 for ( j = 0; bsi->bsi_attrs[ j ].an_name.bv_val; j++ ) {
535 if ( is_at_subtype( an->an_desc->ad_type,
536 bsi->bsi_attrs[ j ].an_desc->ad_type ) )
542 rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat );
543 if ( rc != 0 || vat == NULL ) {
544 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
545 "attribute \"%s\" is not defined "
546 "for objectlass \"%s\"\n",
548 BACKSQL_OC_NAME( bsi->bsi_oc ), 0 );
552 for ( j = 0; vat[j]; j++ ) {
553 backsql_get_attr_vals( vat[j], bsi );
562 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): "
563 "retrieving all attributes\n", 0, 0, 0 );
564 avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals,
565 bsi, 0, AVL_INORDER );
568 if ( global_schemacheck ) {
569 const char *text = NULL;
570 char textbuf[ 1024 ];
571 size_t textlen = sizeof( textbuf );
572 struct berval bv[ 2 ];
576 bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname;
577 bv[ 1 ].bv_val = NULL;
579 rc = structural_class( bv, &soc, NULL,
580 &text, textbuf, textlen );
581 if ( rc != LDAP_SUCCESS ) {
582 Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): "
583 "structural_class() failed %d (%s)\n",
584 bsi->bsi_e->e_name.bv_val,
585 rc, text ? text : "" );
586 entry_clean( bsi->bsi_e );
590 if ( ( bsi->bsi_flags | BSQL_SF_ALL_OPER )
591 || an_find( bsi->bsi_attrs, &AllOper ) ) {
592 rc = attr_merge_normalize_one( bsi->bsi_e,
593 slap_schema.si_ad_structuralObjectClass,
594 &soc, bsi->bsi_op->o_tmpmemctx );
595 if ( rc != LDAP_SUCCESS ) {
596 entry_clean( bsi->bsi_e );
603 Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
608 #endif /* SLAPD_SQL */