backsql_init_search(
	backsql_srch_info 	*bsi, 
	struct berval		*nbase, 
	int 			scope, 
	time_t 			stoptime, 
	Filter 			*filter, 
	SQLHDBC 		dbh,
	Operation 		*op,
	SlapReply		*rs,
	AttributeName 		*attrs,
	unsigned		flags )
{
	backsql_info		*bi = (backsql_info *)op->o_bd->be_private;
	int			rc = LDAP_SUCCESS;

	bsi->bsi_base_ndn = nbase;
	bsi->bsi_use_subtree_shortcut = 0;
	BER_BVZERO( &bsi->bsi_base_id.eid_dn );
	BER_BVZERO( &bsi->bsi_base_id.eid_ndn );
	bsi->bsi_scope = scope;
	bsi->bsi_filter = filter;
	bsi->bsi_dbh = dbh;
	bsi->bsi_op = op;
	bsi->bsi_rs = rs;
	bsi->bsi_flags = BSQL_SF_NONE;

	bsi->bsi_attrs = NULL;

	if ( BACKSQL_FETCH_ALL_ATTRS( bi ) ) {
		/*
		 * if requested, simply try to fetch all attributes
		 */
		bsi->bsi_flags |= BSQL_SF_ALL_ATTRS;

	} else {
		if ( BACKSQL_FETCH_ALL_USERATTRS( bi ) ) {
			bsi->bsi_flags |= BSQL_SF_ALL_USER;

		} else if ( BACKSQL_FETCH_ALL_OPATTRS( bi ) ) {
			bsi->bsi_flags |= BSQL_SF_ALL_OPER;
		}

		if ( attrs == NULL ) {
			/* NULL means all user attributes */
			bsi->bsi_flags |= BSQL_SF_ALL_USER;

		} else {
			AttributeName	*p;
			int		got_oc = 0;

			bsi->bsi_attrs = (AttributeName *)bsi->bsi_op->o_tmpalloc(
					sizeof( AttributeName ),
					bsi->bsi_op->o_tmpmemctx );
			BER_BVZERO( &bsi->bsi_attrs[ 0 ].an_name );
	
			for ( p = attrs; !BER_BVISNULL( &p->an_name ); p++ ) {
				if ( BACKSQL_NCMP( &p->an_name, slap_bv_all_user_attrs ) == 0 ) {
					/* handle "*" */
					bsi->bsi_flags |= BSQL_SF_ALL_USER;

					/* if all attrs are requested, there's
					 * no need to continue */
					if ( BSQL_ISF_ALL_ATTRS( bsi ) ) {
						bsi->bsi_op->o_tmpfree( bsi->bsi_attrs,
								bsi->bsi_op->o_tmpmemctx );
						bsi->bsi_attrs = NULL;
						break;
					}
					continue;

				} else if ( BACKSQL_NCMP( &p->an_name, slap_bv_all_operational_attrs ) == 0 ) {
					/* handle "+" */
					bsi->bsi_flags |= BSQL_SF_ALL_OPER;

					/* if all attrs are requested, there's
					 * no need to continue */
					if ( BSQL_ISF_ALL_ATTRS( bsi ) ) {
						bsi->bsi_op->o_tmpfree( bsi->bsi_attrs,
								bsi->bsi_op->o_tmpmemctx );
						bsi->bsi_attrs = NULL;
						break;
					}
					continue;

				} else if ( BACKSQL_NCMP( &p->an_name, slap_bv_no_attrs ) == 0 ) {
					/* ignore "1.1" */
					continue;

				} else if ( p->an_desc == slap_schema.si_ad_objectClass ) {
					got_oc = 1;
				}

				backsql_attrlist_add( bsi, p->an_desc );
			}

			if ( got_oc == 0 && !( bsi->bsi_flags & BSQL_SF_ALL_USER ) ) {
				/* add objectClass if not present,
				 * because it is required to understand
				 * if an entry is a referral, an alias 
				 * or so... */
				backsql_attrlist_add( bsi, slap_schema.si_ad_objectClass );
			}
		}

		if ( !BSQL_ISF_ALL_ATTRS( bsi ) && bi->sql_anlist ) {
			AttributeName	*p;
			
			/* use hints if available */
			for ( p = bi->sql_anlist; !BER_BVISNULL( &p->an_name ); p++ ) {
				if ( BACKSQL_NCMP( &p->an_name, slap_bv_all_user_attrs ) == 0 ) {
					/* handle "*" */
					bsi->bsi_flags |= BSQL_SF_ALL_USER;

					/* if all attrs are requested, there's
					 * no need to continue */
					if ( BSQL_ISF_ALL_ATTRS( bsi ) ) {
						bsi->bsi_op->o_tmpfree( bsi->bsi_attrs,
								bsi->bsi_op->o_tmpmemctx );
						bsi->bsi_attrs = NULL;
						break;
					}
					continue;

				} else if ( BACKSQL_NCMP( &p->an_name, slap_bv_all_operational_attrs ) == 0 ) {
					/* handle "+" */
					bsi->bsi_flags |= BSQL_SF_ALL_OPER;

					/* if all attrs are requested, there's
					 * no need to continue */
					if ( BSQL_ISF_ALL_ATTRS( bsi ) ) {
						bsi->bsi_op->o_tmpfree( bsi->bsi_attrs,
								bsi->bsi_op->o_tmpmemctx );
						bsi->bsi_attrs = NULL;
						break;
					}
					continue;
				}

				backsql_attrlist_add( bsi, p->an_desc );
			}

		}
	}

	bsi->bsi_id_list = NULL;
	bsi->bsi_id_listtail = &bsi->bsi_id_list;
	bsi->bsi_n_candidates = 0;
	bsi->bsi_stoptime = stoptime;
	BER_BVZERO( &bsi->bsi_sel.bb_val );
	bsi->bsi_sel.bb_len = 0;
	BER_BVZERO( &bsi->bsi_from.bb_val );
	bsi->bsi_from.bb_len = 0;
	BER_BVZERO( &bsi->bsi_join_where.bb_val );
	bsi->bsi_join_where.bb_len = 0;
	BER_BVZERO( &bsi->bsi_flt_where.bb_val );
	bsi->bsi_flt_where.bb_len = 0;
	bsi->bsi_filter_oc = NULL;

	if ( BACKSQL_IS_GET_ID( flags ) ) {
		int	matched = BACKSQL_IS_MATCHED( flags );
		int	getentry = BACKSQL_IS_GET_ENTRY( flags );
		int	gotit = 0;

		assert( op->o_bd->be_private != NULL );

		rc = backsql_dn2id( op, rs, dbh, nbase, &bsi->bsi_base_id,
				matched, 1 );

		/* the entry is collected either if requested for by getentry
		 * or if get noSuchObject and requested to climb the tree,
		 * so that a matchedDN or a referral can be returned */
		if ( ( rc == LDAP_NO_SUCH_OBJECT && matched ) || getentry ) {
			if ( !BER_BVISNULL( &bsi->bsi_base_id.eid_ndn ) ) {
				assert( bsi->bsi_e != NULL );
				
				if ( dn_match( nbase, &bsi->bsi_base_id.eid_ndn ) )
				{
					gotit = 1;
				}
			
				/*
				 * let's see if it is a referral and, in case, get it
				 */
				backsql_attrlist_add( bsi, slap_schema.si_ad_ref );
				rc = backsql_id2entry( bsi, &bsi->bsi_base_id );
				if ( rc == LDAP_SUCCESS ) {
					if ( is_entry_referral( bsi->bsi_e ) )
					{
						BerVarray erefs = get_entry_referrals( op, bsi->bsi_e );
						if ( erefs ) {
							rc = rs->sr_err = LDAP_REFERRAL;
							rs->sr_ref = referral_rewrite( erefs,
									&bsi->bsi_e->e_nname,
									&op->o_req_dn,
									scope );
							ber_bvarray_free( erefs );
	
						} else {
							rc = rs->sr_err = LDAP_OTHER;
							rs->sr_text = "bad referral object";
						}

					} else if ( !gotit ) {
						rc = rs->sr_err = LDAP_NO_SUCH_OBJECT;
					}
				}

			} else {
				rs->sr_err = rc;
			}
		}

		if ( gotit && BACKSQL_IS_GET_OC( flags ) ) {
			bsi->bsi_base_id.eid_oc = backsql_id2oc( bi,
				bsi->bsi_base_id.eid_oc_id );
			if ( bsi->bsi_base_id.eid_oc == NULL ) {
				/* error? */
				backsql_free_entryID( &bsi->bsi_base_id, 1,
					op->o_tmpmemctx );
				rc = rs->sr_err = LDAP_OTHER;
			}
		}
	}

	bsi->bsi_status = rc;

	switch ( rc ) {
	case LDAP_SUCCESS:
	case LDAP_REFERRAL:
		break;

	default:
		bsi->bsi_op->o_tmpfree( bsi->bsi_attrs,
				bsi->bsi_op->o_tmpmemctx );
		break;
	}

	return rc;
}