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

📄 pars0opt.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************Simple SQL optimizer(c) 1997 Innobase OyCreated 12/21/1997 Heikki Tuuri*******************************************************/#include "pars0opt.h"#ifdef UNIV_NONINL#include "pars0opt.ic"#endif#include "row0sel.h"#include "row0ins.h"#include "row0upd.h"#include "dict0dict.h"#include "dict0mem.h"#include "que0que.h"#include "pars0grm.h"#include "pars0pars.h"#include "lock0lock.h"#define OPT_EQUAL	1	/* comparison by = */#define OPT_COMPARISON	2	/* comparison by <, >, <=, or >= */#define OPT_NOT_COND	1#define OPT_END_COND	2#define OPT_TEST_COND	3#define OPT_SCROLL_COND	4/***********************************************************************Inverts a comparison operator. */staticintopt_invert_cmp_op(/*==============*/			/* out: the equivalent operator when the order of			the arguments is switched */	int	op)	/* in: operator */{	if (op == '<') {		return('>');	} else if (op == '>') {		return('<');	} else if (op == '=') {		return('=');	} else if (op == PARS_LE_TOKEN) {		return(PARS_GE_TOKEN);	} else if (op == PARS_GE_TOKEN) {		return(PARS_LE_TOKEN);	} else {		ut_error;	}	return(0);}/***********************************************************************Checks if the value of an expression can be calculated BEFORE the nth tablein a join is accessed. If this is the case, it can possibly be used in anindex search for the nth table. */staticiboolopt_check_exp_determined_before(/*============================*/					/* out: TRUE if already determined */	que_node_t*	exp,		/* in: expression */	sel_node_t*	sel_node,	/* in: select node */	ulint		nth_table)	/* in: nth table will be accessed */{	func_node_t*	func_node;	sym_node_t*	sym_node;	dict_table_t*	table;	que_node_t*	arg;	ulint		i;	ut_ad(exp && sel_node);	if (que_node_get_type(exp) == QUE_NODE_FUNC) {		func_node = exp;		arg = func_node->args;		while (arg) {			if (!opt_check_exp_determined_before(arg, sel_node,								nth_table)) {				return(FALSE);			}			arg = que_node_get_next(arg);		}		return(TRUE);	}	ut_a(que_node_get_type(exp) == QUE_NODE_SYMBOL);	sym_node = exp;	if (sym_node->token_type != SYM_COLUMN) {		return(TRUE);	}	for (i = 0; i < nth_table; i++) {			table = sel_node_get_nth_plan(sel_node, i)->table;		if (sym_node->table == table) {			return(TRUE);		}	}	return(FALSE);	}/***********************************************************************Looks in a comparison condition if a column value is already restricted byit BEFORE the nth table is accessed. */staticque_node_t*opt_look_for_col_in_comparison_before(/*==================================*/					/* out: expression restricting the					value of the column, or NULL if not					known */	ulint		cmp_type,	/* in: OPT_EQUAL, OPT_COMPARISON */	ulint		col_no,		/* in: column number */	func_node_t*	search_cond,	/* in: comparison condition */	sel_node_t*	sel_node,	/* in: select node */	ulint		nth_table,	/* in: nth table in a join (a query					from a single table is considered a					join of 1 table) */	ulint*		op)		/* out: comparison operator ('=',					PARS_GE_TOKEN, ... ); this is inverted					if the column appears on the right					side */{	sym_node_t*	sym_node;	dict_table_t*	table;	que_node_t*	exp;	que_node_t*	arg;	ut_ad(search_cond);	ut_a((search_cond->func == '<')	     || (search_cond->func == '>')			     || (search_cond->func == '=')			     || (search_cond->func == PARS_GE_TOKEN)	     || (search_cond->func == PARS_LE_TOKEN));	table = sel_node_get_nth_plan(sel_node, nth_table)->table;	if ((cmp_type == OPT_EQUAL) && (search_cond->func != '=')) {		return(NULL);	} else if ((cmp_type == OPT_COMPARISON)			&& (search_cond->func != '<')			&& (search_cond->func != '>')						&& (search_cond->func != PARS_GE_TOKEN)			&& (search_cond->func != PARS_LE_TOKEN)) {		return(NULL);	}	arg = search_cond->args;	if (que_node_get_type(arg) == QUE_NODE_SYMBOL) {		sym_node = arg;		if ((sym_node->token_type == SYM_COLUMN)				&& (sym_node->table == table)				&& (sym_node->col_no == col_no)) {							/* sym_node contains the desired column id */			/* Check if the expression on the right side of the			operator is already determined */			exp = que_node_get_next(arg);							if (opt_check_exp_determined_before(exp, sel_node,								nth_table)) {				*op = search_cond->func;				return(exp);			}		}    	}    	exp = search_cond->args;        arg = que_node_get_next(arg);	if (que_node_get_type(arg) == QUE_NODE_SYMBOL) {		sym_node = arg;		if ((sym_node->token_type == SYM_COLUMN)				&& (sym_node->table == table)				&& (sym_node->col_no == col_no)) {							if (opt_check_exp_determined_before(exp, sel_node,								nth_table)) {				*op = opt_invert_cmp_op(search_cond->func);				return(exp);			}		}    	}		return(NULL);}/***********************************************************************Looks in a search condition if a column value is already restricted by thesearch condition BEFORE the nth table is accessed. Takes into account thatif we will fetch in an ascending order, we cannot utilize an upper limit fora column value; in a descending order, respectively, a lower limit. */staticque_node_t*opt_look_for_col_in_cond_before(/*============================*/					/* out: expression restricting the					value of the column, or NULL if not					known */	ulint		cmp_type,	/* in: OPT_EQUAL, OPT_COMPARISON */	ulint		col_no,		/* in: column number */	func_node_t*	search_cond,	/* in: search condition or NULL */	sel_node_t*	sel_node,	/* in: select node */	ulint		nth_table,	/* in: nth table in a join (a query					from a single table is considered a					join of 1 table) */	ulint*		op)		/* out: comparison operator ('=',					PARS_GE_TOKEN, ... ) */{	func_node_t*	new_cond;	que_node_t*	exp;	if (search_cond == NULL) {		return(NULL);	}			ut_a(que_node_get_type(search_cond) == QUE_NODE_FUNC);	ut_a(search_cond->func != PARS_OR_TOKEN);	ut_a(search_cond->func != PARS_NOT_TOKEN);			if (search_cond->func == PARS_AND_TOKEN) {		new_cond = search_cond->args;		exp = opt_look_for_col_in_cond_before(cmp_type, col_no,					new_cond, sel_node, nth_table, op);		if (exp) {			return(exp);		}		new_cond = que_node_get_next(new_cond);				exp = opt_look_for_col_in_cond_before(cmp_type, col_no,					new_cond, sel_node, nth_table, op);		return(exp);	}	exp = opt_look_for_col_in_comparison_before(cmp_type, col_no,					search_cond, sel_node, nth_table, op);	if (exp == NULL) {		return(NULL);	}	/* If we will fetch in an ascending order, we cannot utilize an upper	limit for a column value; in a descending order, respectively, a lower	limit */		if (sel_node->asc && ((*op == '<') || (*op == PARS_LE_TOKEN))) {		return(NULL);	} else if (!sel_node->asc && ((*op == '>') || (*op == PARS_GE_TOKEN))) {		return(NULL);	}	return(exp);}/***********************************************************************Calculates the goodness for an index according to a select node. Thegoodness is 4 times the number of first fields in index whose values wealready know exactly in the query. If we have a comparison condition foran additional field, 2 point are added. If the index is unique, and we knowall the unique fields for the index we add 1024 points. For a clustered indexwe add 1 point. */staticulintopt_calc_index_goodness(/*====================*/					/* out: goodness */	dict_index_t*	index,		/* in: index */	sel_node_t*	sel_node,	/* in: parsed select node */	ulint		nth_table,	/* in: nth table in a join */	que_node_t**	index_plan,	/* in/out: comparison expressions for					this index */	ulint*		last_op)	/* out: last comparison operator, if					goodness > 1 */{	que_node_t*	exp;	ulint		goodness;	ulint		n_fields;	ulint		col_no;	ulint		mix_id_col_no;	ulint		op;	ulint		j;	goodness = 0;	/* Note that as higher level node pointers in the B-tree contain	page addresses as the last field, we must not put more fields in	the search tuple than dict_index_get_n_unique_in_tree(index); see	the note in btr_cur_search_to_nth_level. */		n_fields = dict_index_get_n_unique_in_tree(index);	mix_id_col_no = dict_table_get_sys_col_no(index->table, DATA_MIX_ID);		for (j = 0; j < n_fields; j++) {		col_no = dict_index_get_nth_col_no(index, j);		exp = opt_look_for_col_in_cond_before(OPT_EQUAL, col_no,						sel_node->search_cond,						sel_node, nth_table, &op);		if (col_no == mix_id_col_no) {			ut_ad(exp == NULL);						index_plan[j] = NULL;			*last_op = '=';			goodness += 4;		} else if (exp) {						/* The value for this column is exactly known already			at this stage of the join */			index_plan[j] = exp;			*last_op = op;			goodness += 4;		} else {			/* Look for non-equality comparisons */			exp = opt_look_for_col_in_cond_before(OPT_COMPARISON,						col_no, sel_node->search_cond,						sel_node, nth_table, &op);			if (exp) {				index_plan[j] = exp;				*last_op = op;				goodness += 2;			}									break;		}		}	if (goodness >= 4 * dict_index_get_n_unique(index)) {		goodness += 1024;		if (index->type & DICT_CLUSTERED) {			goodness += 1024;		}	}	/* We have to test for goodness here, as last_op may note be set */	if (goodness && index->type & DICT_CLUSTERED) {		goodness++;	}	return(goodness);}/***********************************************************************Calculates the number of matched fields based on an index goodness. */UNIV_INLINEulintopt_calc_n_fields_from_goodness(/*============================*/				/* out: number of excatly or partially matched				fields */	ulint	goodness)	/* in: goodness */{	return(((goodness % 1024) + 2) / 4);}/***********************************************************************Converts a comparison operator to the corresponding search mode PAGE_CUR_GE,... */UNIV_INLINEulintopt_op_to_search_mode(/*==================*/			/* out: search mode */	ibool	asc,	/* in: TRUE if the rows should be fetched in an			ascending order */	ulint	op)	/* in: operator '=', PARS_GE_TOKEN, ... */{	if (op == '=') {		if (asc) {			return(PAGE_CUR_GE);		} else {			return(PAGE_CUR_LE);		}		} else if (op == '<') {		ut_a(!asc);		return(PAGE_CUR_L);

⌨️ 快捷键说明

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