add (and honor) a (configurable) baseObject to workaround ldap_entries view for RDBMSes that do not support UNION in views

This commit is contained in:
Pierangelo Masarati 2004-10-02 17:33:32 +00:00
parent fa8ee16d38
commit 796dce8657
9 changed files with 465 additions and 56 deletions

View File

@ -107,7 +107,7 @@ Note that the parameter number and order must not be changed.
Specifies the name of a function that converts a given value to uppercase.
This is used for CIS matching when the RDBMS is case sensitive.
.TP
.B upper_needs_cast { yes | no }
.B upper_needs_cast { NO | yes}
Set this directive to
.B yes
if
@ -151,7 +151,7 @@ This is
.B experimental
and may change in future releases.
.TP
.B has_ldapinfo_dn_ru { yes | no }
.B has_ldapinfo_dn_ru { NO | yes }
Explicitly inform the backend whether the SQL schema has dn_ru column
(dn in reverse uppercased form) or not.
Overrides automatic check (required by PostgreSQL/unixODBC).
@ -160,7 +160,7 @@ This is
and may change in future releases.
.TP
.B fail_if_no_mapping { yes | no }
.B fail_if_no_mapping { NO | yes }
When set to
.B yes
it forces
@ -181,6 +181,37 @@ This is
.B experimental
and may change in future releases.
.TP
.B allow_orphans { NO | yes }
When set to
.B yes
orphaned entries (i.e. without the parent entry in the database)
can be added. This option should be used with care, possibly
in conjunction with some special rule on the RDBMS side that
dynamically creates the missing parent.
.TP
.B baseObject [filename]
Instructs the database to create and manage an in-memory baseObject
entry instead of looking for one in the RDBMS.
If the (optional)
.B filename
argument is given, the entry is read from file
.B filename
in
.BR LDIF (5)
form.
This is particularly useful when
.B ldap_entries
information is stored in a view rather than in a table, and
.B union
is not supported for views, so that the view can only specify
one rule to compute the entry structure for one objectClass.
This topic is discussed further in section "METAINFORMATION USED".
This is
.B experimental
and may change in future releases.
.SH METAINFORMATION USED
.LP
Almost everything mentioned later is illustrated in examples located
@ -369,13 +400,26 @@ like this (by Robin Elfrink):
.LP
.nf
CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval)
AS SELECT (1000000000+userid),
AS
SELECT 0, UPPER('o=MyCompany,c=NL'),
3, 0, 'baseObject' FROM unixusers WHERE userid='root' UNION
SELECT (1000000000+userid),
UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')),
1, 0, userid FROM unixusers UNION
SELECT (2000000000+groupnummer),
UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')),
2, 0, groupnummer FROM groups;
.fi
.LP
If your RDBMS does not support
.B unions
in views, only one objectClass can be mapped in
.BR ldap_entries ,
and the baseObject cannot be created; in this case, see the
.B baseObject
directive for a possible workaround.
.LP
.SH Typical SQL backend operation
Having metainformation loaded, the SQL backend uses these tables to

View File

@ -357,6 +357,19 @@ typedef struct {
(!BER_BVISNULL( &(si)->sql_upper_func ))
#define BACKSQL_ALLOW_ORPHANS(si) \
((si)->sql_flags & BSQLF_ALLOW_ORPHANS)
Entry *sql_baseObject;
#ifdef BACKSQL_ARBITRARY_KEY
#define BACKSQL_BASEOBJECT_IDSTR "baseObject"
#define BACKSQL_BASEOBJECT_KEYVAL BACKSQL_BASEOBJECT_IDSTR
#define BACKSQL_IS_BASEOBJECT_ID(id) (bvmatch((id), &backsql_baseObject_bv)
#else /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_BASEOBJECT_ID 0
#define BACKSQL_BASEOBJECT_IDSTR "0"
#define BACKSQL_BASEOBJECT_KEYVAL 0
#define BACKSQL_IS_BASEOBJECT_ID(id) (*(id) == BACKSQL_BASEOBJECT_ID)
#endif /* ! BACKSQL_ARBITRARY_KEY */
#define BACKSQL_BASEOBJECT_OC 0
Avlnode *sql_db_conns;
Avlnode *sql_oc_by_oc;

View File

@ -73,7 +73,7 @@ backsql_bind( Operation *op, SlapReply *rs )
return 1;
}
dn = op->o_req_dn;
dn = op->o_req_ndn;
if ( backsql_api_dn2odbc( op, rs, &dn ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"backsql_api_dn2odbc failed\n",

View File

@ -58,7 +58,7 @@ backsql_compare( Operation *op, SlapReply *rs )
goto return_results;
}
dn = op->o_req_dn;
dn = op->o_req_ndn;
if ( backsql_api_dn2odbc( op, rs, &dn ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"backsql_api_dn2odbc failed\n",

View File

@ -27,8 +27,20 @@
#include <sys/types.h>
#include "slap.h"
#include "ldif.h"
#include "proto-sql.h"
static int
create_baseObject(
BackendDB *be,
const char *fname,
int lineno );
static int
read_baseObject(
BackendDB *be,
const char *fname );
int
backsql_db_config(
BackendDB *be,
@ -389,6 +401,39 @@ backsql_db_config(
"allow_orphans=%s\n",
BACKSQL_ALLOW_ORPHANS( bi ) ? "yes" : "no", 0, 0 );
} else if ( !strcasecmp( argv[ 0 ], "baseobject" ) ) {
if ( be->be_suffix == NULL ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): : "
"must be defined after \"suffix\"\n",
fname, lineno, 0 );
return 1;
}
if ( bi->sql_baseObject ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): : "
"\"baseObject\" already provided (will be overwritten)\n",
fname, lineno, 0 );
entry_free( bi->sql_baseObject );
}
switch ( argc ) {
case 1:
return create_baseObject( be, fname, lineno );
case 2:
return read_baseObject( be, argv[ 1 ] );
default:
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"trailing values "
"in \"baseObject\" directive?\n",
fname, lineno, 0 );
return 1;
}
} else if ( !strcasecmp( argv[ 0 ], "sqllayer") ) {
if ( backsql_api_config( bi, argv[ 1 ] ) ) {
Debug( LDAP_DEBUG_TRACE,
@ -405,5 +450,207 @@ backsql_db_config(
return 0;
}
/*
* Read the entries specified in fname and merge the attributes
* to the user defined baseObject entry. Note that if we find any errors
* what so ever, we will discard the entire entries, print an
* error message and return.
*/
static int
read_baseObject(
BackendDB *be,
const char *fname )
{
backsql_info *bi = (backsql_info *)be->be_private;
FILE *fp;
int rc = 0, lineno = 0, lmax = 0;
char *buf = NULL;
assert( fname );
fp = fopen( fname, "r" );
if ( fp == NULL ) {
Debug( LDAP_DEBUG_ANY,
"could not open back-sql baseObject attr file \"%s\" - absolute path?\n",
fname, 0, 0 );
perror( fname );
return LDAP_OTHER;
}
bi->sql_baseObject = (Entry *) SLAP_CALLOC( 1, sizeof(Entry) );
if ( bi->sql_baseObject == NULL ) {
Debug( LDAP_DEBUG_ANY,
"read_baseObject_file: SLAP_CALLOC failed", 0, 0, 0 );
fclose( fp );
return LDAP_NO_MEMORY;
}
bi->sql_baseObject->e_name = be->be_suffix[0];
bi->sql_baseObject->e_nname = be->be_nsuffix[0];
bi->sql_baseObject->e_attrs = NULL;
while ( ldif_read_record( fp, &lineno, &buf, &lmax ) ) {
Entry *e = str2entry( buf );
Attribute *a;
if( e == NULL ) {
fprintf( stderr, "back-sql baseObject: could not parse entry (line=%d)\n",
lineno );
rc = LDAP_OTHER;
break;
}
/* make sure the DN is the database's suffix */
if ( !be_issuffix( be, &e->e_nname ) ) {
fprintf( stderr,
"back-sql: invalid baseObject - dn=\"%s\" (line=%d)\n",
e->e_dn, lineno );
entry_free( e );
rc = EXIT_FAILURE;
break;
}
/*
* we found a valid entry, so walk thru all the attributes in the
* entry, and add each attribute type and description to baseObject
*/
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
if ( attr_merge( bi->sql_baseObject, a->a_desc, a->a_vals,
( a->a_nvals == a->a_vals ) ? NULL : a->a_nvals ) )
{
rc = LDAP_OTHER;
break;
}
}
entry_free( e );
if ( rc ) {
break;
}
}
if ( rc ) {
entry_free( bi->sql_baseObject );
bi->sql_baseObject = NULL;
}
ch_free( buf );
fclose( fp );
Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n", fname, 0, 0 );
return rc;
}
static int
create_baseObject(
BackendDB *be,
const char *fname,
int lineno )
{
backsql_info *bi = (backsql_info *)be->be_private;
LDAPRDN rdn;
char *p;
int rc, iAVA;
char buf[1024];
snprintf( buf, sizeof(buf),
"dn: %s\n"
"objectClass: extensibleObject\n"
"description: builtin baseObject for back-sql\n"
"description: all entries mapped in the \"ldap_entries\" table\n"
"description: must have \"" BACKSQL_BASEOBJECT_IDSTR "\" "
"in the \"parent\" column",
be->be_suffix[0].bv_val );
bi->sql_baseObject = str2entry( buf );
if ( bi->sql_baseObject == NULL ) {
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): "
"unable to parse baseObject entry\n",
fname, lineno, 0 );
return 1;
}
if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
return 0;
}
rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **) &p, LDAP_DN_FORMAT_LDAP );
if ( rc != LDAP_SUCCESS ) {
snprintf( buf, sizeof(buf),
"unable to extract RDN from baseObject DN \"%s\" (%d: %s)",
be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) );
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): %s\n",
fname, lineno, buf );
return 1;
}
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
LDAPAVA *ava = rdn[ iAVA ];
AttributeDescription *ad = NULL;
slap_syntax_transform_func *transf = NULL;
struct berval bv = BER_BVNULL;
const char *text = NULL;
assert( ava );
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
snprintf( buf, sizeof(buf),
"AttributeDescription of naming "
"attribute #%d from baseObject "
"DN \"%s\": %d: %s",
iAVA, be->be_suffix[ 0 ].bv_val,
rc, ldap_err2string( rc ) );
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): %s\n",
fname, lineno, buf );
return 1;
}
transf = ad->ad_type->sat_syntax->ssyn_pretty;
if ( transf ) {
/*
* transform value by pretty function
* if value is empty, use empty_bv
*/
rc = ( *transf )( ad->ad_type->sat_syntax,
ava->la_value.bv_len
? &ava->la_value
: (struct berval *) &slap_empty_bv,
&bv, NULL );
if ( rc != LDAP_SUCCESS ) {
snprintf( buf, sizeof(buf),
"prettying of attribute #%d from baseObject "
"DN \"%s\" failed: %d: %s",
iAVA, be->be_suffix[ 0 ].bv_val,
rc, ldap_err2string( rc ) );
Debug( LDAP_DEBUG_TRACE,
"<==backsql_db_config (%s line %d): %s\n",
fname, lineno, buf );
return 1;
}
}
if ( !BER_BVISNULL( &bv ) ) {
if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
ber_memfree( ava->la_value.bv_val );
}
ava->la_value = bv;
ava->la_flags |= LDAP_AVA_FREE_VALUE;
}
attr_merge_normalize_one( bi->sql_baseObject,
ad, &ava->la_value, NULL );
}
ldap_rdnfree( rdn );
return 0;
}
#endif /* SLAPD_SQL */

View File

@ -29,6 +29,10 @@
#include "slap.h"
#include "proto-sql.h"
#ifdef BACKSQL_ARBITRARY_KEY
struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
#endif /* BACKSQL_ARBITRARY_KEY */
backsql_entryID *
backsql_free_entryID( backsql_entryID *id, int freeit )
{
@ -40,15 +44,18 @@ backsql_free_entryID( backsql_entryID *id, int freeit )
if ( id->eid_dn.bv_val != NULL ) {
free( id->eid_dn.bv_val );
BER_BVZERO( &id->eid_dn );
}
#ifdef BACKSQL_ARBITRARY_KEY
if ( id->eid_id.bv_val ) {
free( id->eid_id.bv_val );
BER_BVZERO( &id->eid_id );
}
if ( id->eid_keyval.bv_val ) {
free( id->eid_keyval.bv_val );
BER_BVZERO( &id->eid_keyval );
}
#endif /* BACKSQL_ARBITRARY_KEY */
@ -93,9 +100,29 @@ backsql_dn2id(
dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
return LDAP_OTHER;
}
/* return baseObject if available and matches */
if ( bi->sql_baseObject != NULL && bvmatch( dn, &bi->sql_baseObject->e_nname ) ) {
if ( id != NULL ) {
#ifdef BACKSQL_ARBITRARY_KEY
ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
#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;
ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_nname );
id->eid_next = NULL;
}
return LDAP_SUCCESS;
}
/* begin TimesTen */
Debug(LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0);
Debug( LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0 );
assert( bi->sql_id_query );
rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
if ( rc != SQL_SUCCESS ) {
@ -405,6 +432,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
int
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
{
backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
int i;
int rc;
AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
@ -415,6 +443,19 @@ backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
memset( bsi->bsi_e, 0, sizeof( Entry ) );
if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
Entry *e;
e = entry_dup( bi->sql_baseObject );
if ( e == NULL ) {
return LDAP_NO_MEMORY;
}
*bsi->bsi_e = *e;
free( e );
goto done;
}
rc = dnPrettyNormal( NULL, &eid->eid_dn,
&bsi->bsi_e->e_name, &bsi->bsi_e->e_nname,
bsi->bsi_op->o_tmpmemctx );
@ -528,6 +569,7 @@ next:;
}
}
done:;
Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
return LDAP_SUCCESS;

View File

@ -163,6 +163,11 @@ backsql_db_destroy(
free( bi->sql_delentry_query );
free( bi->sql_delobjclasses_query );
free( bi->sql_delreferrals_query );
if ( bi->sql_baseObject ) {
entry_free( bi->sql_baseObject );
}
free( bi );
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 );

View File

@ -105,6 +105,9 @@ int backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn );
/*
* entry-id.c
*/
#ifdef BACKSQL_ARBITRARY_KEY
extern struct berval backsql_baseObject_bv;
#endif /* BACKSQL_ARBITRARY_KEY */
/* stores in *id the ID in table ldap_entries corresponding to DN, if any */
int backsql_dn2id( backsql_info *bi, backsql_entryID *id,

View File

@ -184,6 +184,8 @@ backsql_init_search(
bsi->bsi_filter_oc = NULL;
if ( get_base_id ) {
assert( op->o_bd->be_private );
rc = backsql_dn2id( (backsql_info *)op->o_bd->be_private,
&bsi->bsi_base_id, dbh, base );
}
@ -1393,8 +1395,9 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
backsql_BindRowAsStrings( sth, &row );
rc = SQLFetch( sth );
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
struct berval dn;
struct berval dn, ndn;
backsql_entryID *c_id = NULL;
int ret;
ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
@ -1402,6 +1405,20 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
continue;
}
ret = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
if ( dn.bv_val != row.cols[ 3 ] ) {
free( dn.bv_val );
}
if ( ret != LDAP_SUCCESS ) {
continue;
}
if ( bi->sql_baseObject && bvmatch( &ndn, &bi->sql_baseObject->e_nname ) ) {
free( ndn.bv_val );
continue;
}
c_id = (backsql_entryID *)ch_calloc( 1,
sizeof( backsql_entryID ) );
#ifdef BACKSQL_ARBITRARY_KEY
@ -1413,10 +1430,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
#endif /* ! BACKSQL_ARBITRARY_KEY */
c_id->eid_oc_id = bsi->bsi_oc->bom_id;
if ( dn.bv_val == row.cols[ 3 ] ) {
ber_dupbv( &c_id->eid_dn, &dn );
if ( ndn.bv_val == row.cols[ 3 ] ) {
ber_dupbv( &c_id->eid_dn, &ndn );
} else {
c_id->eid_dn = dn;
c_id->eid_dn = ndn;
}
/* append at end of list ... */
@ -1459,7 +1476,7 @@ backsql_search( Operation *op, SlapReply *rs )
Entry user_entry = { 0 };
int manageDSAit;
time_t stoptime = 0;
backsql_srch_info srch_info;
backsql_srch_info bsi;
backsql_entryID *eid = NULL;
struct berval base;
@ -1504,7 +1521,7 @@ backsql_search( Operation *op, SlapReply *rs )
/* compute it anyway; root does not use it */
stoptime = op->o_time + op->ors_tlimit;
base = op->o_req_dn;
base = op->o_req_ndn;
if ( backsql_api_dn2odbc( op, rs, &base ) ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"backsql_api_dn2odbc failed\n",
@ -1516,7 +1533,7 @@ backsql_search( Operation *op, SlapReply *rs )
}
/* init search */
rs->sr_err = backsql_init_search( &srch_info, &base,
rs->sr_err = backsql_init_search( &bsi, &base,
op->ors_scope,
op->ors_slimit, op->ors_tlimit,
stoptime, op->ors_filter,
@ -1526,20 +1543,47 @@ backsql_search( Operation *op, SlapReply *rs )
goto done;
}
/*
* for each objectclass we try to construct query which gets IDs
* of entries matching LDAP query filter and scope (or at least
* candidates), and get the IDs
*/
srch_info.bsi_n_candidates =
( op->ors_limit == NULL /* isroot == FALSE */ ? -2 :
bsi.bsi_n_candidates =
( op->ors_limit == NULL /* isroot == TRUE */ ? -2 :
( op->ors_limit->lms_s_unchecked == -1 ? -2 :
( op->ors_limit->lms_s_unchecked ) ) );
avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
&srch_info, BACKSQL_AVL_STOP, AVL_INORDER );
if ( op->ors_limit != NULL /* isroot == TRUE */
switch ( bsi.bsi_scope ) {
case LDAP_SCOPE_BASE:
case BACKSQL_SCOPE_BASE_LIKE:
/*
* probably already found...
*/
bsi.bsi_id_list = &bsi.bsi_base_id;
bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next;
break;
case LDAP_SCOPE_SUBTREE:
/*
* if baseObject is defined, and if it is the root
* of the search, add it to the candidate list
*/
if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &bsi.bsi_base_id.eid_id ) )
{
bsi.bsi_id_list = &bsi.bsi_base_id;
bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next;
}
/* FALLTHRU */
default:
/*
* for each objectclass we try to construct query which gets IDs
* of entries matching LDAP query filter and scope (or at least
* candidates), and get the IDs
*/
avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
&bsi, BACKSQL_AVL_STOP, AVL_INORDER );
}
if ( op->ors_limit != NULL /* isroot == FALSE */
&& op->ors_limit->lms_s_unchecked != -1
&& srch_info.bsi_n_candidates == -1 )
&& bsi.bsi_n_candidates == -1 )
{
rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
send_ldap_result( op, rs );
@ -1549,15 +1593,16 @@ backsql_search( Operation *op, SlapReply *rs )
/*
* now we load candidate entries (only those attributes
* mentioned in attrs and filter), test it against full filter
* and then send to client
* and then send to client; don't free entry_id if baseObject...
*/
for ( eid = srch_info.bsi_id_list;
for ( eid = bsi.bsi_id_list;
eid != NULL;
eid = backsql_free_entryID( eid, 1 ) )
eid = backsql_free_entryID( eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
{
int rc;
Attribute *hasSubordinate = NULL,
*a = NULL;
Entry *e = NULL;
/* check for abandon */
if ( op->o_abandon ) {
@ -1588,20 +1633,28 @@ backsql_search( Operation *op, SlapReply *rs )
eid->eid_id, eid->eid_oc_id, eid->eid_keyval );
#endif /* ! BACKSQL_ARBITRARY_KEY */
srch_info.bsi_e = &user_entry;
rc = backsql_id2entry( &srch_info, eid );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"error %d in backsql_id2entry() "
"- skipping\n", rc, 0, 0 );
continue;
/* don't recollect baseObject ... */
if ( BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
e = bi->sql_baseObject;
} else {
bsi.bsi_e = &user_entry;
rc = backsql_id2entry( &bsi, eid );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
"error %d in backsql_id2entry() "
"- skipping\n", rc, 0, 0 );
continue;
}
e = &user_entry;
}
/* check scope */
switch ( op->ors_scope ) {
case LDAP_SCOPE_BASE:
case BACKSQL_SCOPE_BASE_LIKE:
if ( !bvmatch( &user_entry.e_nname, &op->o_req_ndn ) ) {
if ( !bvmatch( &e->e_nname, &op->o_req_ndn ) ) {
goto next_entry;
}
break;
@ -1617,7 +1670,7 @@ backsql_search( Operation *op, SlapReply *rs )
}
case LDAP_SCOPE_SUBTREE:
if ( !dnIsSuffix( &user_entry.e_nname, &op->o_req_ndn ) ) {
if ( !dnIsSuffix( &e->e_nname, &op->o_req_ndn ) ) {
goto next_entry;
}
break;
@ -1626,23 +1679,23 @@ backsql_search( Operation *op, SlapReply *rs )
if ( !manageDSAit &&
op->ors_scope != LDAP_SCOPE_BASE &&
op->ors_scope != BACKSQL_SCOPE_BASE_LIKE &&
is_entry_referral( &user_entry ) )
is_entry_referral( e ) )
{
BerVarray refs;
refs = get_entry_referrals( op, &user_entry );
refs = get_entry_referrals( op, e );
if ( !refs ) {
backsql_srch_info srch_info2 = { 0 };
backsql_srch_info bsi2 = { 0 };
Entry user_entry2 = { 0 };
/* retry with the full entry... */
(void)backsql_init_search( &srch_info2,
&user_entry.e_name,
(void)backsql_init_search( &bsi2,
&e->e_nname,
LDAP_SCOPE_BASE,
-1, -1, -1, NULL,
dbh, op, rs, NULL, 0 );
srch_info2.bsi_e = &user_entry2;
rc = backsql_id2entry( &srch_info2, eid );
bsi2.bsi_e = &user_entry2;
rc = backsql_id2entry( &bsi2, eid );
if ( rc == LDAP_SUCCESS ) {
if ( is_entry_referral( &user_entry2 ) )
{
@ -1655,7 +1708,7 @@ backsql_search( Operation *op, SlapReply *rs )
if ( refs ) {
rs->sr_ref = referral_rewrite( refs,
&user_entry.e_name,
&e->e_name,
&op->o_req_dn,
op->ors_scope );
ber_bvarray_free( refs );
@ -1681,8 +1734,8 @@ backsql_search( Operation *op, SlapReply *rs )
* anyway; we should have used the frontend API function
* filter_has_subordinates()
*/
if ( srch_info.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) {
rc = backsql_has_children( bi, dbh, &user_entry.e_nname );
if ( bsi.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) {
rc = backsql_has_children( bi, dbh, &e->e_nname );
switch ( rc ) {
case LDAP_COMPARE_TRUE:
@ -1708,9 +1761,9 @@ backsql_search( Operation *op, SlapReply *rs )
}
}
if ( test_filter( op, &user_entry, op->ors_filter )
if ( test_filter( op, e, op->ors_filter )
== LDAP_COMPARE_TRUE ) {
if ( hasSubordinate && !( srch_info.bsi_flags & BSQL_SF_ALL_OPER )
if ( hasSubordinate && !( bsi.bsi_flags & BSQL_SF_ALL_OPER )
&& !ad_inlist( slap_schema.si_ad_hasSubordinates, op->ors_attrs ) ) {
a->a_next = NULL;
attr_free( hasSubordinate );
@ -1719,8 +1772,10 @@ backsql_search( Operation *op, SlapReply *rs )
rs->sr_attrs = op->ors_attrs;
rs->sr_operational_attrs = NULL;
rs->sr_entry = &user_entry;
rs->sr_flags = REP_ENTRY_MODIFIABLE;
rs->sr_entry = e;
if ( e == &user_entry ) {
rs->sr_flags = REP_ENTRY_MODIFIABLE;
}
sres = send_search_entry( op, rs );
rs->sr_entry = NULL;
rs->sr_attrs = NULL;
@ -1764,7 +1819,7 @@ end_of_search:;
: LDAP_REFERRAL;
} else {
rs->sr_err = srch_info.bsi_status;
rs->sr_err = bsi.bsi_status;
}
send_ldap_result( op, rs );
@ -1774,12 +1829,12 @@ end_of_search:;
}
done:;
if ( !BER_BVISNULL( &srch_info.bsi_base_id.eid_dn ) ) {
(void)backsql_free_entryID( &srch_info.bsi_base_id, 0 );
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_dn ) ) {
(void)backsql_free_entryID( &bsi.bsi_base_id, 0 );
}
if ( srch_info.bsi_attrs ) {
ch_free( srch_info.bsi_attrs );
if ( bsi.bsi_attrs ) {
ch_free( bsi.bsi_attrs );
}
if ( base.bv_val != op->o_req_ndn.bv_val ) {