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

📄 row0sel.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto table_exhausted;		}		goto next_rec;	}	/* PHASE 7: We found a new qualifying row for the current table; push	the row if prefetch is on, or move to the next table in the join */		plan->n_rows_fetched++;	ut_ad(plan->pcur.latch_mode == node->latch_mode);	if (node->select_will_do_update) {		/* This is a searched update and we can do the update in-place,		saving CPU time */		row_upd_in_place_in_select(node, thr, &mtr);		leaf_contains_updates = TRUE;		/* When the database is in the online backup mode, the number		of log records for a single mtr should be small: increment the		cost counter to ensure it */				cost_counter += 1 + (SEL_COST_LIMIT / 8);		if (plan->unique_search) {			goto table_exhausted;					}		goto next_rec;	}		if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT)				|| plan->unique_search || plan->no_prefetch) {		/* No prefetch in operation: go to the next table */			goto next_table;	}	sel_push_prefetched_row(plan);	if (plan->n_rows_prefetched == SEL_MAX_N_PREFETCH) {		/* The prefetch buffer is now full */				sel_pop_prefetched_row(plan);		goto next_table;	}next_rec:		ut_ad(!search_latch_locked);	if (mtr_has_extra_clust_latch) {		/* We must commit &mtr if we are moving to the next		non-clustered index record, because we could break the		latching order if we would access a different clustered		index page right away without releasing the previous. */		goto commit_mtr_for_a_while;	}		if (leaf_contains_updates		&& btr_pcur_is_after_last_on_page(&(plan->pcur), &mtr)) {		/* We must commit &mtr if we are moving to a different page,		because we have done updates to the x-latched leaf page, and		the latch would be released in btr_pcur_move_to_next, without		&mtr getting committed there */		ut_ad(node->asc);		goto commit_mtr_for_a_while;	}	if (node->asc) {		moved = btr_pcur_move_to_next(&(plan->pcur), &mtr);	} else {		moved = btr_pcur_move_to_prev(&(plan->pcur), &mtr);	}	if (!moved) {				goto table_exhausted;	}	cursor_just_opened = FALSE;	/* END OF RECORD LOOP	   ------------------ */	goto rec_loop;next_table:	/* We found a record which satisfies the conditions: we can move to	the next table or return a row in the result set */	ut_ad(btr_pcur_is_on_user_rec(&(plan->pcur), &mtr));		if (plan->unique_search && !node->can_get_updated) {		plan->cursor_at_end = TRUE;	} else {		ut_ad(!search_latch_locked);		plan->stored_cursor_rec_processed = TRUE;		btr_pcur_store_position(&(plan->pcur), &mtr);	}	mtr_commit(&mtr);	leaf_contains_updates = FALSE;	mtr_has_extra_clust_latch = FALSE;next_table_no_mtr:	/* If we use 'goto' to this label, it means that the row was popped	from the prefetched rows stack, and &mtr is already committed */		if (node->fetch_table + 1 == node->n_tables) {		sel_eval_select_list(node);		if (node->is_aggregate) {			goto table_loop;					}		sel_assign_into_var_values(node->into_list, node);				thr->run_node = que_node_get_parent(node);		if (search_latch_locked) {			rw_lock_s_unlock(&btr_search_latch);		}		err = DB_SUCCESS;		goto func_exit;	}	node->fetch_table++;	/* When we move to the next table, we first reset the plan cursor:	we do not care about resetting it when we backtrack from a table */		plan_reset_cursor(sel_node_get_nth_plan(node, node->fetch_table));		goto table_loop;table_exhausted:	/* The table cursor pcur reached the result set end: backtrack to the	previous table in the join if we do not have cached prefetched rows */		plan->cursor_at_end = TRUE;	mtr_commit(&mtr);	leaf_contains_updates = FALSE;	mtr_has_extra_clust_latch = FALSE;		if (plan->n_rows_prefetched > 0) {		/* The table became exhausted during a prefetch */			sel_pop_prefetched_row(plan);		goto next_table_no_mtr;	}table_exhausted_no_mtr:	if (node->fetch_table == 0) {		err = DB_SUCCESS;		if (node->is_aggregate && !node->aggregate_already_fetched) {			node->aggregate_already_fetched = TRUE;			sel_assign_into_var_values(node->into_list, node);			thr->run_node = que_node_get_parent(node);			if (search_latch_locked) {				rw_lock_s_unlock(&btr_search_latch);			}					goto func_exit;		}		node->state = SEL_NODE_NO_MORE_ROWS;				thr->run_node = que_node_get_parent(node);		if (search_latch_locked) {			rw_lock_s_unlock(&btr_search_latch);		}				goto func_exit;	}	node->fetch_table--;	goto table_loop;stop_for_a_while:	/* Return control for a while to que_run_threads, so that runaway	queries can be canceled. NOTE that when we come here, we must, in a	locking read, have placed the necessary (possibly waiting request)	record lock on the cursor record or its successor: when we reposition	the cursor, this record lock guarantees that nobody can meanwhile have	inserted new records which should have appeared in the result set,	which would result in the phantom problem. */ 	ut_ad(!search_latch_locked);	plan->stored_cursor_rec_processed = FALSE;	btr_pcur_store_position(&(plan->pcur), &mtr);	mtr_commit(&mtr);			ut_ad(sync_thread_levels_empty_gen(TRUE));	err = DB_SUCCESS;	goto func_exit;commit_mtr_for_a_while:	/* Stores the cursor position and commits &mtr; this is used if	&mtr may contain latches which would break the latching order if	&mtr would not be committed and the latches released. */ 	plan->stored_cursor_rec_processed = TRUE;	ut_ad(!search_latch_locked);	btr_pcur_store_position(&(plan->pcur), &mtr);	mtr_commit(&mtr);	leaf_contains_updates = FALSE;	mtr_has_extra_clust_latch = FALSE;		ut_ad(sync_thread_levels_empty_gen(TRUE));	goto table_loop;lock_wait_or_error:	/* See the note at stop_for_a_while: the same holds for this case */	ut_ad(!btr_pcur_is_before_first_on_page(&(plan->pcur), &mtr)							|| !node->asc);	ut_ad(!search_latch_locked);	plan->stored_cursor_rec_processed = FALSE;	btr_pcur_store_position(&(plan->pcur), &mtr);		mtr_commit(&mtr);			ut_ad(sync_thread_levels_empty_gen(TRUE));func_exit:	if (UNIV_LIKELY_NULL(heap)) {		mem_heap_free(heap);	}	return(err);}/**************************************************************************Performs a select step. This is a high-level function used in SQL executiongraphs. */que_thr_t*row_sel_step(/*=========*/				/* out: query thread to run next or NULL */	que_thr_t*	thr)	/* in: query thread */{	ulint		i_lock_mode;	sym_node_t*	table_node;	sel_node_t*	node;	ulint		err;	ut_ad(thr);		node = thr->run_node;	ut_ad(que_node_get_type(node) == QUE_NODE_SELECT);	/* If this is a new time this node is executed (or when execution	resumes after wait for a table intention lock), set intention locks	on the tables, or assign a read view */	if (node->into_list && (thr->prev_node == que_node_get_parent(node))) {		node->state = SEL_NODE_OPEN;	}	if (node->state == SEL_NODE_OPEN) {		/* It may be that the current session has not yet started		its transaction, or it has been committed: */		trx_start_if_not_started(thr_get_trx(thr));		plan_reset_cursor(sel_node_get_nth_plan(node, 0));		if (node->consistent_read) {			/* Assign a read view for the query */			node->read_view = trx_assign_read_view(							thr_get_trx(thr));		} else {			if (node->set_x_locks) {				i_lock_mode = LOCK_IX;			} else {				i_lock_mode = LOCK_IS;			}				table_node = node->table_list;				while (table_node) {				err = lock_table(0, table_node->table,							i_lock_mode, thr);				if (err != DB_SUCCESS) {						que_thr_handle_error(thr, DB_ERROR,								NULL, 0);					return(NULL);				}					table_node = que_node_get_next(table_node);			}		}			/* If this is an explicit cursor, copy stored procedure		variable values, so that the values cannot change between		fetches (currently, we copy them also for non-explicit		cursors) */		if (node->explicit_cursor &&				UT_LIST_GET_FIRST(node->copy_variables)) {			row_sel_copy_input_variable_vals(node);		}				node->state = SEL_NODE_FETCH;		node->fetch_table = 0;		if (node->is_aggregate) {			/* Reset the aggregate total values */			sel_reset_aggregate_vals(node);		}	}	err = row_sel(node, thr);	/* NOTE! if queries are parallelized, the following assignment may	have problems; the assignment should be made only if thr is the	only top-level thr in the graph: */		thr->graph->last_sel_node = node;	if (err == DB_SUCCESS) {		/* Ok: do nothing */	} else if (err == DB_LOCK_WAIT) {		return(NULL);	} else {		/* SQL error detected */		fprintf(stderr, "SQL error %lu\n", (ulong) err);		que_thr_handle_error(thr, DB_ERROR, NULL, 0);		return(NULL);	}	return(thr);} /**************************************************************************Performs a fetch for a cursor. */que_thr_t*fetch_step(/*=======*/				/* out: query thread to run next or NULL */	que_thr_t*	thr)	/* in: query thread */{	sel_node_t*	sel_node;	fetch_node_t*	node;	ut_ad(thr);		node = thr->run_node;	sel_node = node->cursor_def;		ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);	if (thr->prev_node != que_node_get_parent(node)) {		if (sel_node->state != SEL_NODE_NO_MORE_ROWS) {						sel_assign_into_var_values(node->into_list, sel_node);		}		thr->run_node = que_node_get_parent(node);		return(thr);	}	/* Make the fetch node the parent of the cursor definition for	the time of the fetch, so that execution knows to return to this	fetch node after a row has been selected or we know that there is	no row left */			sel_node->common.parent = node;		if (sel_node->state == SEL_NODE_CLOSED) {		/* SQL error detected */		fprintf(stderr, "SQL error %lu\n", (ulong)DB_ERROR);		que_thr_handle_error(thr, DB_ERROR, NULL, 0);		return(NULL);	}	thr->run_node = sel_node;	return(thr);} /***************************************************************Prints a row in a select result. */que_thr_t*row_printf_step(/*============*/				/* out: query thread to run next or NULL */	que_thr_t*	thr)	/* in: query thread */{	row_printf_node_t*	node;	sel_node_t*		sel_node;	que_node_t*		arg;	ut_ad(thr);		node = thr->run_node;		sel_node = node->sel_node;	ut_ad(que_node_get_type(node) == QUE_NODE_ROW_PRINTF);	if (thr->prev_node == que_node_get_parent(node)) {			/* Reset the cursor */		sel_node->state = SEL_NODE_OPEN;		/* Fetch next row to print */		thr->run_node = sel_node;				return(thr);	}	if (sel_node->state != SEL_NODE_FETCH) {		ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS);		/* No more rows to print */		thr->run_node = que_node_get_parent(node);			return(thr);	}	arg = sel_node->select_list;	while (arg) {		dfield_print_also_hex(que_node_get_val(arg));		fputs(" ::: ", stderr);		arg = que_node_get_next(arg);	}	putc('\n', stderr);	/* Fetch next row to print */	thr->run_node = sel_node;	return(thr);} /********************************************************************Converts a key value stored in MySQL format to an Innobase dtuple. The lastfield of the key value may be just a prefix of a fixed length field: hencethe parameter key_len. But currently we do not allow search keys where thelast field is only a prefix of the full key field len and print a warning ifsuch appears. A counterpart of this function isha_innobase::store_key_val_for_row() in ha_innodb.cc. */voidrow_sel_convert_mysql_key_to_innobase(/*==================================*/	dtuple_t*	tuple,		/* in: tuple where to build;					NOTE: we assume that the type info					in the tuple is already according

⌨️ 快捷键说明

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