⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 OpenLdap是LDAP的开源项目
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $OpenLDAP: pkg/ldap/servers/slapd/back-sql/search.c,v 1.81.2.13 2007/03/05 18:39:51 ando Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 1999-2007 The OpenLDAP Foundation. * Portions Copyright 1999 Dmitry Kovalev. * Portions Copyright 2002 Pierangelo Masarati. * Portions Copyright 2004 Mark Adamson. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by Dmitry Kovalev for inclusion * by OpenLDAP Software.  Additional significant contributors include * Pierangelo Masarati and Mark Adamson. */#include "portable.h"#include <stdio.h>#include <sys/types.h>#include "ac/string.h"#include "ac/ctype.h"#include "lutil.h"#include "slap.h"#include "proto-sql.h"static int backsql_process_filter( backsql_srch_info *bsi, Filter *f );static int backsql_process_filter_eq( backsql_srch_info *bsi, 		backsql_at_map_rec *at,		int casefold, struct berval *filter_value );static int backsql_process_filter_like( backsql_srch_info *bsi, 		backsql_at_map_rec *at,		int casefold, struct berval *filter_value );static int backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, 		backsql_at_map_rec *at );static intbacksql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ){	int 		n_attrs = 0;	AttributeName	*an = NULL;	if ( bsi->bsi_attrs == NULL ) {		return 1;	}	/*	 * clear the list (retrieve all attrs)	 */	if ( ad == NULL ) {		bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, bsi->bsi_op->o_tmpmemctx );		bsi->bsi_attrs = NULL;		bsi->bsi_flags |= BSQL_SF_ALL_ATTRS;		return 1;	}	for ( ; !BER_BVISNULL( &bsi->bsi_attrs[ n_attrs ].an_name ); n_attrs++ ) {		an = &bsi->bsi_attrs[ n_attrs ];				Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "			"attribute \"%s\" is in list\n", 			an->an_name.bv_val, 0, 0 );		/*		 * We can live with strcmp because the attribute 		 * list has been normalized before calling be_search		 */		if ( !BACKSQL_NCMP( &an->an_name, &ad->ad_cname ) ) {			return 1;		}	}		Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): "		"adding \"%s\" to list\n", ad->ad_cname.bv_val, 0, 0 );	an = (AttributeName *)bsi->bsi_op->o_tmprealloc( bsi->bsi_attrs,			sizeof( AttributeName ) * ( n_attrs + 2 ),			bsi->bsi_op->o_tmpmemctx );	if ( an == NULL ) {		return -1;	}	an[ n_attrs ].an_name = ad->ad_cname;	an[ n_attrs ].an_desc = ad;	BER_BVZERO( &an[ n_attrs + 1 ].an_name );	bsi->bsi_attrs = an;		return 1;}/* * Initializes the search structure. *  * If get_base_id != 0, the field bsi_base_id is filled  * with the entryID of bsi_base_ndn; it must be freed * by backsql_free_entryID() when no longer required. * * NOTE: base must be normalized */intbacksql_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, &AllUser ) == 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, &AllOper ) == 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, &NoAttrs ) == 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, &AllUser ) == 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, &AllOper ) == 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;			}		}	}	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;}static intbacksql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op ){	int		res;	if ( !f ) {		return 0;	}	backsql_strfcat_x( &bsi->bsi_flt_where,			bsi->bsi_op->o_tmpmemctx, "c", '(' /* ) */  );	while ( 1 ) {		res = backsql_process_filter( bsi, f );		if ( res < 0 ) {			/*			 * TimesTen : If the query has no answers,			 * don't bother to run the query.			 */			return -1;		} 		f = f->f_next;		if ( f == NULL ) {			break;		}		switch ( op ) {		case LDAP_FILTER_AND:			backsql_strfcat_x( &bsi->bsi_flt_where,					bsi->bsi_op->o_tmpmemctx, "l",					(ber_len_t)STRLENOF( " AND " ), 						" AND " );			break;		case LDAP_FILTER_OR:			backsql_strfcat_x( &bsi->bsi_flt_where,					bsi->bsi_op->o_tmpmemctx, "l",					(ber_len_t)STRLENOF( " OR " ),						" OR " );			break;		}	}	backsql_strfcat_x( &bsi->bsi_flt_where,			bsi->bsi_op->o_tmpmemctx, "c", /* ( */ ')' );	return 1;}static intbacksql_process_sub_filter( backsql_srch_info *bsi, Filter *f,	backsql_at_map_rec *at ){	backsql_info		*bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;	int			i;	int			casefold = 0;	if ( !f ) {		return 0;	}	/* always uppercase strings by now */#ifdef BACKSQL_UPPERCASE_FILTER	if ( f->f_sub_desc->ad_type->sat_substr &&			SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,				bi->sql_caseIgnoreMatch ) )#endif /* BACKSQL_UPPERCASE_FILTER */	{		casefold = 1;	}	if ( f->f_sub_desc->ad_type->sat_substr &&			SLAP_MR_ASSOCIATED( f->f_sub_desc->ad_type->sat_substr,				bi->sql_telephoneNumberMatch ) )	{		struct berval	bv;		ber_len_t	i, s, a;		/*		 * to check for matching telephone numbers		 * with intermixed chars, e.g. val='1234'		 * use		 * 		 * val LIKE '%1%2%3%4%'		 */		BER_BVZERO( &bv );		if ( f->f_sub_initial.bv_val ) {			bv.bv_len += f->f_sub_initial.bv_len;		}		if ( f->f_sub_any != NULL ) {			for ( a = 0; f->f_sub_any[ a ].bv_val != NULL; a++ ) {				bv.bv_len += f->f_sub_any[ a ].bv_len;			}		}		if ( f->f_sub_final.bv_val ) {			bv.bv_len += f->f_sub_final.bv_len;		}		bv.bv_len = 2 * bv.bv_len - 1;		bv.bv_val = ch_malloc( bv.bv_len + 1 );		s = 0;		if ( !BER_BVISNULL( &f->f_sub_initial ) ) {			bv.bv_val[ s ] = f->f_sub_initial.bv_val[ 0 ];			for ( i = 1; i < f->f_sub_initial.bv_len; i++ ) {				bv.bv_val[ s + 2 * i - 1 ] = '%';				bv.bv_val[ s + 2 * i ] = f->f_sub_initial.bv_val[ i ];			}			bv.bv_val[ s + 2 * i - 1 ] = '%';			s += 2 * i;		}		if ( f->f_sub_any != NULL ) {			for ( a = 0; !BER_BVISNULL( &f->f_sub_any[ a ] ); a++ ) {				bv.bv_val[ s ] = f->f_sub_any[ a ].bv_val[ 0 ];				for ( i = 1; i < f->f_sub_any[ a ].bv_len; i++ ) {					bv.bv_val[ s + 2 * i - 1 ] = '%';					bv.bv_val[ s + 2 * i ] = f->f_sub_any[ a ].bv_val[ i ];				}				bv.bv_val[ s + 2 * i - 1 ] = '%';				s += 2 * i;			}		}		if ( !BER_BVISNULL( &f->f_sub_final ) ) {			bv.bv_val[ s ] = f->f_sub_final.bv_val[ 0 ];			for ( i = 1; i < f->f_sub_final.bv_len; i++ ) {				bv.bv_val[ s + 2 * i - 1 ] = '%';				bv.bv_val[ s + 2 * i ] = f->f_sub_final.bv_val[ i ];			}				bv.bv_val[ s + 2 * i - 1 ] = '%';			s += 2 * i;		}		bv.bv_val[ s - 1 ] = '\0';		(void)backsql_process_filter_like( bsi, at, casefold, &bv );		ch_free( bv.bv_val );		return 1;	}	/*	 * When dealing with case-sensitive strings 	 * we may omit normalization; however, normalized	 * SQL filters are more liberal.	 */	backsql_strfcat_x( &bsi->bsi_flt_where,			bsi->bsi_op->o_tmpmemctx, "c", '(' /* ) */  );	/* TimesTen */	Debug( LDAP_DEBUG_TRACE, "backsql_process_sub_filter(%s):\n",		at->bam_ad->ad_cname.bv_val, 0, 0 );	Debug(LDAP_DEBUG_TRACE, "   expr: '%s%s%s'\n", at->bam_sel_expr.bv_val,		at->bam_sel_expr_u.bv_val ? "' '" : "",		at->bam_sel_expr_u.bv_val ? at->bam_sel_expr_u.bv_val : "" );	if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) {		/*		 * If a pre-upper-cased version of the column 		 * or a precompiled upper function exists, use it		 */		backsql_strfcat_x( &bsi->bsi_flt_where, 				bsi->bsi_op->o_tmpmemctx,				"bl",				&at->bam_sel_expr_u,				(ber_len_t)STRLENOF( " LIKE '" ),					" LIKE '" );	} else {		backsql_strfcat_x( &bsi->bsi_flt_where,				bsi->bsi_op->o_tmpmemctx,				"bl",				&at->bam_sel_expr,				(ber_len_t)STRLENOF( " LIKE '" ), " LIKE '" );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -