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

📄 row0sel.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
row_sel_build_prev_vers(/*====================*/					/* out: DB_SUCCESS or error code */	read_view_t*	read_view,	/* in: read view */	plan_t*		plan,		/* in: plan node for table */	rec_t*		rec,		/* in: record in a clustered index */	ulint**		offsets,	/* in/out: offsets returned by					rec_get_offsets(rec, plan->index) */	mem_heap_t**	offset_heap,	/* in/out: memory heap from which					the offsets are allocated */	rec_t**		old_vers,	/* out: old version, or NULL if the					record does not exist in the view:					i.e., it was freshly inserted					afterwards */	mtr_t*		mtr)		/* in: mtr */{	ulint	err;	if (plan->old_vers_heap) {		mem_heap_empty(plan->old_vers_heap);	} else {		plan->old_vers_heap = mem_heap_create(512);	}		err = row_vers_build_for_consistent_read(rec, mtr, plan->index,					offsets, read_view, offset_heap,					plan->old_vers_heap, old_vers);	return(err);}/*************************************************************************Tests the conditions which determine when the index segment we are searchingthrough has been exhausted. */UNIV_INLINEiboolrow_sel_test_end_conds(/*===================*/ 			/* out: TRUE if row passed the tests */	plan_t*	plan)	/* in: plan for the table; the column values must			already have been retrieved and the right sides of			comparisons evaluated */{	func_node_t*	cond;	/* All conditions in end_conds are comparisons of a column to an	expression */		cond = UT_LIST_GET_FIRST(plan->end_conds);	while (cond) {		/* Evaluate the left side of the comparison, i.e., get the		column value if there is an indirection */		eval_sym(cond->args);		/* Do the comparison */		if (!eval_cmp(cond)) {			return(FALSE);		}		cond = UT_LIST_GET_NEXT(cond_list, cond);	}	return(TRUE);}/*************************************************************************Tests the other conditions. */UNIV_INLINEiboolrow_sel_test_other_conds(/*=====================*/			/* out: TRUE if row passed the tests */	plan_t*	plan)	/* in: plan for the table; the column values must			already have been retrieved */{	func_node_t*	cond;		cond = UT_LIST_GET_FIRST(plan->other_conds);	while (cond) {		eval_exp(cond);		if (!eval_node_get_ibool_val(cond)) {			return(FALSE);		}		cond = UT_LIST_GET_NEXT(cond_list, cond);	}	return(TRUE);}/*************************************************************************Retrieves the clustered index record corresponding to a record in anon-clustered index. Does the necessary locking. */staticulintrow_sel_get_clust_rec(/*==================*/				/* out: DB_SUCCESS or error code */	sel_node_t*	node,	/* in: select_node */	plan_t*		plan,	/* in: plan node for table */	rec_t*		rec,	/* in: record in a non-clustered index */	que_thr_t*	thr,	/* in: query thread */	rec_t**		out_rec,/* out: clustered record or an old version of				it, NULL if the old version did not exist				in the read view, i.e., it was a fresh				inserted version */	mtr_t*		mtr)	/* in: mtr used to get access to the				non-clustered record; the same mtr is used to				access the clustered index */{	dict_index_t*	index;	rec_t*		clust_rec;	rec_t*		old_vers;	ulint		err;	mem_heap_t*	heap		= NULL;	ulint		offsets_[REC_OFFS_NORMAL_SIZE];	ulint*		offsets		= offsets_;	*offsets_ = (sizeof offsets_) / sizeof *offsets_;	*out_rec = NULL;	offsets = rec_get_offsets(rec,				btr_pcur_get_btr_cur(&plan->pcur)->index,				offsets, ULINT_UNDEFINED, &heap);		row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);	index = dict_table_get_first_index(plan->table);		btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,				node->latch_mode, &(plan->clust_pcur),				0, mtr);	clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));	/* Note: only if the search ends up on a non-infimum record is the	low_match value the real match to the search tuple */	if (!page_rec_is_user_rec(clust_rec)            || btr_pcur_get_low_match(&(plan->clust_pcur))	       < dict_index_get_n_unique(index)) {			ut_a(rec_get_deleted_flag(rec, plan->table->comp));		ut_a(node->read_view);		/* In a rare case it is possible that no clust rec is found		for a delete-marked secondary index record: if in row0umod.c		in row_undo_mod_remove_clust_low() we have already removed		the clust rec, while purge is still cleaning and removing		secondary index records associated with earlier versions of		the clustered index record. In that case we know that the		clustered index record did not exist in the read view of		trx. */		goto func_exit;	}	offsets = rec_get_offsets(clust_rec, index, offsets,						ULINT_UNDEFINED, &heap);	if (!node->read_view) {		/* Try to place a lock on the index record */        		/* If innodb_locks_unsafe_for_binlog option is used, 		we lock only the record, i.e., next-key locking is		not used. */		ulint	lock_type;		if (srv_locks_unsafe_for_binlog) {			lock_type = LOCK_REC_NOT_GAP;		} else {			lock_type = LOCK_ORDINARY;		}		err = lock_clust_rec_read_check_and_lock(0,				clust_rec, index, offsets,				node->row_lock_mode, lock_type, thr);		if (err != DB_SUCCESS) {			goto err_exit;		}	} else {		/* This is a non-locking consistent read: if necessary, fetch		a previous version of the record */		old_vers = NULL;		if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,							node->read_view)) {			err = row_sel_build_prev_vers(node->read_view, plan,						clust_rec, &offsets, &heap,						&old_vers, mtr);			if (err != DB_SUCCESS) {				goto err_exit;			}			clust_rec = old_vers;			if (clust_rec == NULL) {				goto func_exit;			}		}		/* If we had to go to an earlier version of row or the		secondary index record is delete marked, then it may be that		the secondary index record corresponding to clust_rec		(or old_vers) is not rec; in that case we must ignore		such row because in our snapshot rec would not have existed.		Remember that from rec we cannot see directly which transaction		id corresponds to it: we have to go to the clustered index		record. A query where we want to fetch all rows where		the secondary index value is in some interval would return		a wrong result if we would not drop rows which we come to		visit through secondary index records that would not really		exist in our snapshot. */				if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))		    && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,							clust_rec, index)) {			goto func_exit;		}	}	/* Fetch the columns needed in test conditions */	row_sel_fetch_columns(index, clust_rec, offsets,					UT_LIST_GET_FIRST(plan->columns));	*out_rec = clust_rec;func_exit:	err = DB_SUCCESS;err_exit:	if (UNIV_LIKELY_NULL(heap)) {		mem_heap_free(heap);	}	return(err);}/*************************************************************************Sets a lock on a record. */UNIV_INLINEulintsel_set_rec_lock(/*=============*/				/* out: DB_SUCCESS or error code */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index */	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */	ulint		mode,	/* in: lock mode */	ulint		type, 	/* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */	que_thr_t*	thr)	/* in: query thread */	{	trx_t*	trx;	ulint	err;	trx = thr_get_trx(thr);		if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) {		if (buf_LRU_buf_pool_running_out()) {						return(DB_LOCK_TABLE_FULL);		}	}	if (index->type & DICT_CLUSTERED) {		err = lock_clust_rec_read_check_and_lock(0,					rec, index, offsets, mode, type, thr);	} else {		err = lock_sec_rec_read_check_and_lock(0,					rec, index, offsets, mode, type, thr);	}	return(err);}/*************************************************************************Opens a pcur to a table index. */staticvoidrow_sel_open_pcur(/*==============*/	sel_node_t*	node,		/* in: select node */	plan_t*		plan,		/* in: table plan */	ibool		search_latch_locked,					/* in: TRUE if the thread currently					has the search latch locked in					s-mode */	mtr_t*		mtr)		/* in: mtr */{	dict_index_t*	index;	func_node_t*	cond;	que_node_t*	exp;	ulint		n_fields;	ulint		has_search_latch = 0;	/* RW_S_LATCH or 0 */ 	ulint		i;	if (search_latch_locked) {		has_search_latch = RW_S_LATCH;	}	index = plan->index;	/* Calculate the value of the search tuple: the exact match columns	get their expressions evaluated when we evaluate the right sides of	end_conds */	cond = UT_LIST_GET_FIRST(plan->end_conds);	while (cond) {		eval_exp(que_node_get_next(cond->args));			cond = UT_LIST_GET_NEXT(cond_list, cond);	}		if (plan->tuple) {		n_fields = dtuple_get_n_fields(plan->tuple);			if (plan->n_exact_match < n_fields) {			/* There is a non-exact match field which must be			evaluated separately */						eval_exp(plan->tuple_exps[n_fields - 1]);		}				for (i = 0; i < n_fields; i++) {			exp = plan->tuple_exps[i];				dfield_copy_data(dtuple_get_nth_field(plan->tuple, i),							que_node_get_val(exp));		}			/* Open pcur to the index */			btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,					node->latch_mode, &(plan->pcur),					has_search_latch, mtr);	} else {		/* Open the cursor to the start or the end of the index		(FALSE: no init) */		btr_pcur_open_at_index_side(plan->asc, index, node->latch_mode,						&(plan->pcur), FALSE, mtr);	}	ut_ad(plan->n_rows_prefetched == 0);	ut_ad(plan->n_rows_fetched == 0);	ut_ad(plan->cursor_at_end == FALSE); 	plan->pcur_is_open = TRUE;}/*************************************************************************Restores a stored pcur position to a table index. */staticiboolrow_sel_restore_pcur_pos(/*=====================*/				/* out: TRUE if the cursor should be moved to				the next record after we return from this				function (moved to the previous, in the case				of a descending cursor) without processing				again the current cursor record */	sel_node_t*	node,	/* in: select node */	plan_t*		plan,	/* in: table plan */	mtr_t*		mtr)	/* in: mtr */{	ibool	equal_position;	ulint	relative_position;	ut_ad(!plan->cursor_at_end);		relative_position = btr_pcur_get_rel_pos(&(plan->pcur));	equal_position = btr_pcur_restore_position(node->latch_mode,							&(plan->pcur), mtr);	/* If the cursor is traveling upwards, and relative_position is		(1) BTR_PCUR_BEFORE: this is not allowed, as we did not have a lock	yet on the successor of the page infimum;	(2) BTR_PCUR_AFTER: btr_pcur_restore_position placed the cursor on the	first record GREATER than the predecessor of a page supremum; we have	not yet processed the cursor record: no need to move the cursor to the	next record;	(3) BTR_PCUR_ON: btr_pcur_restore_position placed the cursor on the	last record LESS or EQUAL to the old stored user record; (a) if	equal_position is FALSE, this means that the cursor is now on a record	less than the old user record, and we must move to the next record;	(b) if equal_position is TRUE, then if	plan->stored_cursor_rec_processed is TRUE, we must move to the next	record, else there is no need to move the cursor. */	if (plan->asc) {		if (relative_position == BTR_PCUR_ON) {			if (equal_position) {				return(plan->stored_cursor_rec_processed);			}			return(TRUE);		}		ut_ad(relative_position == BTR_PCUR_AFTER		      || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);		return(FALSE);	}	/* If the cursor is traveling downwards, and relative_position is		(1) BTR_PCUR_BEFORE: btr_pcur_restore_position placed the cursor on	the last record LESS than the successor of a page infimum; we have not	processed the cursor record: no need to move the cursor;	(2) BTR_PCUR_AFTER: btr_pcur_restore_position placed the cursor on the	first record GREATER than the predecessor of a page supremum; we have	processed the cursor record: we should move the cursor to the previous	record;	(3) BTR_PCUR_ON: btr_pcur_restore_position placed the cursor on the	last record LESS or EQUAL to the old stored user record; (a) if	equal_position is FALSE, this means that the cursor is now on a record	less than the old user record, and we need not move to the previous	record; (b) if equal_position is TRUE, then if	plan->stored_cursor_rec_processed is TRUE, we must move to the previous	record, else there is no need to move the cursor. */	if (relative_position == BTR_PCUR_BEFORE	    || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) {		return(FALSE);	}	if (relative_position == BTR_PCUR_ON) {		if (equal_position) {			return(plan->stored_cursor_rec_processed);		}		return(FALSE);	}	ut_ad(relative_position == BTR_PCUR_AFTER		      || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);	return(TRUE);}/*************************************************************************Resets a plan cursor to a closed state. */UNIV_INLINEvoidplan_reset_cursor(/*==============*/	plan_t*	plan)	/* in: plan */{		plan->pcur_is_open = FALSE;	plan->cursor_at_end = FALSE;		plan->n_rows_fetched = 0;	plan->n_rows_prefetched = 0;}	/*************************************************************************Tries to do a shortcut to fetch a clustered index record with a unique key,using the hash index if possible (not always). */staticulintrow_sel_try_search_shortcut(/*========================*/				/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */	sel_node_t*	node,	/* in: select node for a consistent read */	plan_t*		plan,	/* in: plan for a unique search in clustered				index */	mtr_t*		mtr)	/* in: mtr */{	dict_index_t*	index;	rec_t*		rec;	mem_heap_t*	heap		= NULL;	ulint		offsets_[REC_OFFS_NORMAL_SIZE];	ulint*		offsets		= offsets_;	ulint		ret;	*offsets_ = (sizeof offsets_) / sizeof *offsets_;	index = plan->index;	ut_ad(node->read_view);	ut_ad(plan->unique_search);	ut_ad(!plan->must_get_clust);#ifdef UNIV_SYNC_DEBUG	ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));#endif /* UNIV_SYNC_DEBUG */		row_sel_open_pcur(node, plan, TRUE, mtr);	rec = btr_pcur_get_rec(&(plan->pcur));		if (!page_rec_is_user_rec(rec)) {		return(SEL_RETRY);

⌨️ 快捷键说明

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