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

📄 row0sel.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************Select(c) 1997 Innobase OyCreated 12/19/1997 Heikki Tuuri*******************************************************/#include "row0sel.h"#ifdef UNIV_NONINL#include "row0sel.ic"#endif#include "dict0dict.h"#include "dict0boot.h"#include "trx0undo.h"#include "trx0trx.h"#include "btr0btr.h"#include "btr0cur.h"#include "btr0sea.h"#include "mach0data.h"#include "que0que.h"#include "row0upd.h"#include "row0row.h"#include "row0vers.h"#include "rem0cmp.h"#include "lock0lock.h"#include "eval0eval.h"#include "pars0sym.h"#include "pars0pars.h"#include "row0mysql.h"#include "read0read.h"#include "buf0lru.h"/* Maximum number of rows to prefetch; MySQL interface has another parameter */#define SEL_MAX_N_PREFETCH	16/* Number of rows fetched, after which to start prefetching; MySQL interfacehas another parameter */#define SEL_PREFETCH_LIMIT	1/* When a select has accessed about this many pages, it returns control backto que_run_threads: this is to allow canceling runaway queries */#define SEL_COST_LIMIT	100/* Flags for search shortcut */#define SEL_FOUND	0#define	SEL_EXHAUSTED	1#define SEL_RETRY	2/************************************************************************Returns TRUE if the user-defined column values in a secondary index recordare alphabetically the same as the corresponding columns in the clusteredindex record.NOTE: the comparison is NOT done as a binary comparison, but characterfields are compared with collation! */staticiboolrow_sel_sec_rec_is_for_clust_rec(/*=============================*/					/* out: TRUE if the secondary					record is equal to the corresponding					fields in the clustered record,					when compared with collation */	rec_t*		sec_rec,	/* in: secondary index record */	dict_index_t*	sec_index,	/* in: secondary index */	rec_t*		clust_rec,	/* in: clustered index record */	dict_index_t*	clust_index)	/* in: clustered index */{	dict_field_t*	ifield;        dict_col_t*     col;        byte*           sec_field;        ulint           sec_len;        byte*           clust_field;        ulint           clust_len;        ulint           n;        ulint           i;	dtype_t*	cur_type;	mem_heap_t*	heap		= NULL;	ulint		clust_offsets_[REC_OFFS_NORMAL_SIZE];	ulint		sec_offsets_[REC_OFFS_SMALL_SIZE];	ulint*		clust_offs	= clust_offsets_;	ulint*		sec_offs	= sec_offsets_;	ibool		is_equal	= TRUE;	*clust_offsets_ = (sizeof clust_offsets_) / sizeof *clust_offsets_;	*sec_offsets_ = (sizeof sec_offsets_) / sizeof *sec_offsets_;	clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,						ULINT_UNDEFINED, &heap);	sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs,						ULINT_UNDEFINED, &heap);        n = dict_index_get_n_ordering_defined_by_user(sec_index);        for (i = 0; i < n; i++) {		ifield = dict_index_get_nth_field(sec_index, i);                col = dict_field_get_col(ifield);                		clust_field = rec_get_nth_field(clust_rec, clust_offs,                                                dict_col_get_clust_pos(col),                                                &clust_len);		sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);		if (ifield->prefix_len > 0		    && clust_len != UNIV_SQL_NULL) {			cur_type = dict_col_get_type(				dict_field_get_col(ifield));			clust_len = dtype_get_at_most_n_mbchars(				cur_type,				ifield->prefix_len,				clust_len, (char*) clust_field);		}                if (0 != cmp_data_data(dict_col_get_type(col),                                        clust_field, clust_len,                                        sec_field, sec_len)) {			is_equal = FALSE;			goto func_exit;                }        }func_exit:	if (UNIV_LIKELY_NULL(heap)) {		mem_heap_free(heap);	}	return(is_equal);}/*************************************************************************Creates a select node struct. */sel_node_t*sel_node_create(/*============*/				/* out, own: select node struct */	mem_heap_t*	heap)	/* in: memory heap where created */{	sel_node_t*	node;	node = mem_heap_alloc(heap, sizeof(sel_node_t));	node->common.type = QUE_NODE_SELECT;	node->state = SEL_NODE_OPEN;	node->select_will_do_update = FALSE;	node->latch_mode = BTR_SEARCH_LEAF;	node->plans = NULL;		return(node);}/*************************************************************************Frees the memory private to a select node when a query graph is freed,does not free the heap where the node was originally created. */voidsel_node_free_private(/*==================*/	sel_node_t*	node)	/* in: select node struct */{	ulint	i;	plan_t*	plan;	if (node->plans != NULL) {		for (i = 0; i < node->n_tables; i++) {			plan = sel_node_get_nth_plan(node, i);			btr_pcur_close(&(plan->pcur));			btr_pcur_close(&(plan->clust_pcur));			if (plan->old_vers_heap) {				mem_heap_free(plan->old_vers_heap);			}		}	}}/*************************************************************************Evaluates the values in a select list. If there are aggregate functions,their argument value is added to the aggregate total. */UNIV_INLINEvoidsel_eval_select_list(/*=================*/	sel_node_t*	node)	/* in: select node */{	que_node_t*	exp;	exp = node->select_list;	while (exp) {		eval_exp(exp);		exp = que_node_get_next(exp);	}}/*************************************************************************Assigns the values in the select list to the possible into-variables inSELECT ... INTO ... */UNIV_INLINEvoidsel_assign_into_var_values(/*=======================*/	sym_node_t*	var,	/* in: first variable in a list of variables */	sel_node_t*	node)	/* in: select node */{	que_node_t*	exp;	if (var == NULL) {		return;	}	exp = node->select_list;	while (var) {		ut_ad(exp);		eval_node_copy_val(var->alias, exp);		exp = que_node_get_next(exp);		var = que_node_get_next(var);	}}/*************************************************************************Resets the aggregate value totals in the select list of an aggregate typequery. */UNIV_INLINEvoidsel_reset_aggregate_vals(/*=====================*/	sel_node_t*	node)	/* in: select node */{	func_node_t*	func_node;	ut_ad(node->is_aggregate);	func_node = node->select_list;	while (func_node) {		eval_node_set_int_val(func_node, 0);		func_node = que_node_get_next(func_node);	}		node->aggregate_already_fetched = FALSE;}/*************************************************************************Copies the input variable values when an explicit cursor is opened. */UNIV_INLINEvoidrow_sel_copy_input_variable_vals(/*=============================*/	sel_node_t*	node)	/* in: select node */{	sym_node_t*	var;	var = UT_LIST_GET_FIRST(node->copy_variables);	while (var) {		eval_node_copy_val(var, var->alias);		var->indirection = NULL;		var = UT_LIST_GET_NEXT(col_var_list, var);	}}/*************************************************************************Fetches the column values from a record. */staticvoidrow_sel_fetch_columns(/*==================*/	dict_index_t*	index,	/* in: record index */	rec_t*		rec,	/* in: record in a clustered or non-clustered				index */	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */	sym_node_t*	column)	/* in: first column in a column list, or				NULL */{	dfield_t*	val;	ulint		index_type;	ulint		field_no;	byte*		data;	ulint		len;		ut_ad(rec_offs_validate(rec, index, offsets));	if (index->type & DICT_CLUSTERED) {		index_type = SYM_CLUST_FIELD_NO;	} else {		index_type = SYM_SEC_FIELD_NO;	}	while (column) {		field_no = column->field_nos[index_type];		if (field_no != ULINT_UNDEFINED) {				data = rec_get_nth_field(rec, offsets, field_no, &len);						if (column->copy_val) {				eval_node_copy_and_alloc_val(column, data,									len);			} else {				val = que_node_get_val(column);				dfield_set_data(val, data, len);			}		}		column = UT_LIST_GET_NEXT(col_var_list, column);	}}/*************************************************************************Allocates a prefetch buffer for a column when prefetch is first time done. */staticvoidsel_col_prefetch_buf_alloc(/*=======================*/	sym_node_t*	column)	/* in: symbol table node for a column */{	sel_buf_t*	sel_buf;	ulint		i;	ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);		column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH							* sizeof(sel_buf_t));	for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {		sel_buf = column->prefetch_buf + i;		sel_buf->data = NULL;		sel_buf->val_buf_size = 0;	}}/*************************************************************************Frees a prefetch buffer for a column, including the dynamically allocatedmemory for data stored there. */voidsel_col_prefetch_buf_free(/*======================*/	sel_buf_t*	prefetch_buf)	/* in, own: prefetch buffer */{	sel_buf_t*	sel_buf;	ulint		i;	for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {		sel_buf = prefetch_buf + i;		if (sel_buf->val_buf_size > 0) {			mem_free(sel_buf->data);		}	}}/*************************************************************************Pops the column values for a prefetched, cached row from the column prefetchbuffers and places them to the val fields in the column nodes. */staticvoidsel_pop_prefetched_row(/*===================*/	plan_t*	plan)	/* in: plan node for a table */{	sym_node_t*	column;	sel_buf_t*	sel_buf;	dfield_t*	val;	byte*		data;	ulint		len;	ulint		val_buf_size;		ut_ad(plan->n_rows_prefetched > 0);	column = UT_LIST_GET_FIRST(plan->columns);	while (column) {		val = que_node_get_val(column);		if (!column->copy_val) {			/* We did not really push any value for the			column */			ut_ad(!column->prefetch_buf);			ut_ad(que_node_get_val_buf_size(column) == 0);#ifdef UNIV_DEBUG			dfield_set_data(val, NULL, 0);#endif			goto next_col;		}		ut_ad(column->prefetch_buf);		sel_buf = column->prefetch_buf + plan->first_prefetched;		data = sel_buf->data;		len = sel_buf->len;		val_buf_size = sel_buf->val_buf_size;		/* We must keep track of the allocated memory for		column values to be able to free it later: therefore		we swap the values for sel_buf and val */		sel_buf->data = dfield_get_data(val);		sel_buf->len = dfield_get_len(val);		sel_buf->val_buf_size = que_node_get_val_buf_size(column);				dfield_set_data(val, data, len);		que_node_set_val_buf_size(column, val_buf_size);next_col:		column = UT_LIST_GET_NEXT(col_var_list, column);	}	plan->n_rows_prefetched--;	plan->first_prefetched++;}/*************************************************************************Pushes the column values for a prefetched, cached row to the column prefetchbuffers from the val fields in the column nodes. */UNIV_INLINEvoidsel_push_prefetched_row(/*====================*/	plan_t*	plan)	/* in: plan node for a table */{	sym_node_t*	column;	sel_buf_t*	sel_buf;	dfield_t*	val;	byte*		data;	ulint		len;	ulint		pos;	ulint		val_buf_size;	if (plan->n_rows_prefetched == 0) {		pos = 0;		plan->first_prefetched = 0;	} else {		pos = plan->n_rows_prefetched;		/* We have the convention that pushing new rows starts only		after the prefetch stack has been emptied: */				ut_ad(plan->first_prefetched == 0);	}	plan->n_rows_prefetched++;		ut_ad(pos < SEL_MAX_N_PREFETCH);		column = UT_LIST_GET_FIRST(plan->columns);	while (column) {		if (!column->copy_val) {			/* There is no sense to push pointers to database			page fields when we do not keep latch on the page! */			goto next_col;		}				if (!column->prefetch_buf) {			/* Allocate a new prefetch buffer */			sel_col_prefetch_buf_alloc(column);		}		sel_buf = column->prefetch_buf + pos;		val = que_node_get_val(column);		data = dfield_get_data(val);		len = dfield_get_len(val);		val_buf_size = que_node_get_val_buf_size(column);		/* We must keep track of the allocated memory for		column values to be able to free it later: therefore		we swap the values for sel_buf and val */		dfield_set_data(val, sel_buf->data, sel_buf->len);		que_node_set_val_buf_size(column, sel_buf->val_buf_size);				sel_buf->data = data;		sel_buf->len = len;		sel_buf->val_buf_size = val_buf_size;next_col:				column = UT_LIST_GET_NEXT(col_var_list, column);	}}/*************************************************************************Builds a previous version of a clustered index record for a consistent read */staticulint

⌨️ 快捷键说明

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