1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2021, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file que/que0que.cc
29 Query graph
30 
31 Created 5/27/1996 Heikki Tuuri
32 *******************************************************/
33 
34 #include "ha_prototypes.h"
35 
36 #include "que0que.h"
37 
38 #ifdef UNIV_NONINL
39 #include "que0que.ic"
40 #endif
41 
42 #include "usr0sess.h"
43 #include "trx0trx.h"
44 #include "trx0roll.h"
45 #include "row0undo.h"
46 #include "row0ins.h"
47 #include "row0upd.h"
48 #include "row0sel.h"
49 #include "row0purge.h"
50 #include "dict0crea.h"
51 #include "log0log.h"
52 #include "eval0proc.h"
53 #include "lock0lock.h"
54 #include "eval0eval.h"
55 #include "pars0types.h"
56 
57 #define QUE_MAX_LOOPS_WITHOUT_CHECK	16
58 
59 /* Short introduction to query graphs
60    ==================================
61 
62 A query graph consists of nodes linked to each other in various ways. The
63 execution starts at que_run_threads() which takes a que_thr_t parameter.
64 que_thr_t contains two fields that control query graph execution: run_node
65 and prev_node. run_node is the next node to execute and prev_node is the
66 last node executed.
67 
68 Each node has a pointer to a 'next' statement, i.e., its brother, and a
69 pointer to its parent node. The next pointer is NULL in the last statement
70 of a block.
71 
72 Loop nodes contain a link to the first statement of the enclosed statement
73 list. While the loop runs, que_thr_step() checks if execution to the loop
74 node came from its parent or from one of the statement nodes in the loop. If
75 it came from the parent of the loop node it starts executing the first
76 statement node in the loop. If it came from one of the statement nodes in
77 the loop, then it checks if the statement node has another statement node
78 following it, and runs it if so.
79 
80 To signify loop ending, the loop statements (see e.g. while_step()) set
81 que_thr_t->run_node to the loop node's parent node. This is noticed on the
82 next call of que_thr_step() and execution proceeds to the node pointed to by
83 the loop node's 'next' pointer.
84 
85 For example, the code:
86 
87 X := 1;
88 WHILE X < 5 LOOP
89  X := X + 1;
90  X := X + 1;
91 X := 5
92 
93 will result in the following node hierarchy, with the X-axis indicating
94 'next' links and the Y-axis indicating parent/child links:
95 
96 A - W - A
97     |
98     |
99     A - A
100 
101 A = assign_node_t, W = while_node_t. */
102 
103 /* How a stored procedure containing COMMIT or ROLLBACK commands
104 is executed?
105 
106 The commit or rollback can be seen as a subprocedure call.
107 
108 When the transaction starts to handle a rollback or commit.
109 It builds a query graph which, when executed, will roll back
110 or commit the incomplete transaction. The transaction
111 is moved to the TRX_QUE_ROLLING_BACK or TRX_QUE_COMMITTING state.
112 If specified, the SQL cursors opened by the transaction are closed.
113 When the execution of the graph completes, it is like returning
114 from a subprocedure: the query thread which requested the operation
115 starts running again. */
116 
117 /**********************************************************************//**
118 Moves a thread from another state to the QUE_THR_RUNNING state. Increments
119 the n_active_thrs counters of the query graph and transaction.
120 ***NOTE***: This is the only function in which such a transition is allowed
121 to happen! */
122 static
123 void
124 que_thr_move_to_run_state(
125 /*======================*/
126 	que_thr_t*	thr);	/*!< in: an query thread */
127 
128 /***********************************************************************//**
129 Creates a query graph fork node.
130 @return own: fork node */
131 que_fork_t*
que_fork_create(que_t * graph,que_node_t * parent,ulint fork_type,mem_heap_t * heap)132 que_fork_create(
133 /*============*/
134 	que_t*		graph,		/*!< in: graph, if NULL then this
135 					fork node is assumed to be the
136 					graph root */
137 	que_node_t*	parent,		/*!< in: parent node */
138 	ulint		fork_type,	/*!< in: fork type */
139 	mem_heap_t*	heap)		/*!< in: memory heap where created */
140 {
141 	que_fork_t*	fork;
142 
143 	ut_ad(heap);
144 
145 	fork = static_cast<que_fork_t*>(mem_heap_zalloc(heap, sizeof(*fork)));
146 
147 	fork->heap = heap;
148 
149 	fork->fork_type = fork_type;
150 
151 	fork->common.parent = parent;
152 
153 	fork->common.type = QUE_NODE_FORK;
154 
155 	fork->state = QUE_FORK_COMMAND_WAIT;
156 
157 	fork->graph = (graph != NULL) ? graph : fork;
158 
159 	UT_LIST_INIT(fork->thrs, &que_thr_t::thrs);
160 
161 	return(fork);
162 }
163 
164 
165 /** Creates a query graph thread node.
166 @param[in]	parent		parent node, i.e., a fork node
167 @param[in]	heap		memory heap where created
168 @param[in]	prebuilt	row prebuilt structure
169 @return own: query thread node */
170 que_thr_t*
que_thr_create(que_fork_t * parent,mem_heap_t * heap,row_prebuilt_t * prebuilt)171 que_thr_create(
172 	que_fork_t*	parent,
173 	mem_heap_t*	heap,
174 	row_prebuilt_t*	prebuilt)
175 {
176 	que_thr_t*	thr;
177 
178 	ut_ad(parent != NULL);
179 	ut_ad(heap != NULL);
180 
181 	thr = static_cast<que_thr_t*>(mem_heap_zalloc(heap, sizeof(*thr)));
182 
183 	thr->graph = parent->graph;
184 
185 	thr->common.parent = parent;
186 
187 	thr->magic_n = QUE_THR_MAGIC_N;
188 
189 	thr->common.type = QUE_NODE_THR;
190 
191 	thr->state = QUE_THR_COMMAND_WAIT;
192 
193 	thr->lock_state = QUE_THR_LOCK_NOLOCK;
194 
195 	thr->prebuilt = prebuilt;
196 
197 	UT_LIST_ADD_LAST(parent->thrs, thr);
198 
199 	return(thr);
200 }
201 
202 /**********************************************************************//**
203 Moves a suspended query thread to the QUE_THR_RUNNING state and may release
204 a worker thread to execute it. This function should be used to end
205 the wait state of a query thread waiting for a lock or a stored procedure
206 completion.
207 @return the query thread that needs to be released. */
208 que_thr_t*
que_thr_end_lock_wait(trx_t * trx)209 que_thr_end_lock_wait(
210 /*==================*/
211 	trx_t*		trx)	/*!< in: transaction with que_state in
212 				QUE_THR_LOCK_WAIT */
213 {
214 	que_thr_t*	thr;
215 	ibool		was_active;
216 
217 	ut_ad(lock_mutex_own());
218 	ut_ad(trx_mutex_own(trx));
219 
220 	thr = trx->lock.wait_thr;
221 
222 	ut_ad(thr != NULL);
223 
224 	ut_ad(trx->lock.que_state == TRX_QUE_LOCK_WAIT);
225 	/* In MySQL this is the only possible state here */
226 	ut_a(thr->state == QUE_THR_LOCK_WAIT);
227 
228 	was_active = thr->is_active;
229 
230 	que_thr_move_to_run_state(thr);
231 
232 	trx->stats.stop_lock_wait(*trx);
233 
234 	trx->lock.que_state = TRX_QUE_RUNNING;
235 
236 	trx->lock.wait_thr = NULL;
237 
238 	/* In MySQL we let the OS thread (not just the query thread) to wait
239 	for the lock to be released: */
240 
241 	return((!was_active && thr != NULL) ? thr : NULL);
242 }
243 
244 /**********************************************************************//**
245 Inits a query thread for a command. */
246 UNIV_INLINE
247 void
que_thr_init_command(que_thr_t * thr)248 que_thr_init_command(
249 /*=================*/
250 	que_thr_t*	thr)	/*!< in: query thread */
251 {
252 	thr->run_node = thr;
253 	thr->prev_node = thr->common.parent;
254 
255 	que_thr_move_to_run_state(thr);
256 }
257 
258 /**********************************************************************//**
259 Round robin scheduler.
260 @return a query thread of the graph moved to QUE_THR_RUNNING state, or
261 NULL; the query thread should be executed by que_run_threads by the
262 caller */
263 que_thr_t*
que_fork_scheduler_round_robin(que_fork_t * fork,que_thr_t * thr)264 que_fork_scheduler_round_robin(
265 /*===========================*/
266 	que_fork_t*	fork,		/*!< in: a query fork */
267 	que_thr_t*	thr)		/*!< in: current pos */
268 {
269 	trx_mutex_enter(fork->trx);
270 
271 	/* If no current, start first available. */
272 	if (thr == NULL) {
273 		thr = UT_LIST_GET_FIRST(fork->thrs);
274 	} else {
275 		thr = UT_LIST_GET_NEXT(thrs, thr);
276 	}
277 
278 	if (thr) {
279 
280 		fork->state = QUE_FORK_ACTIVE;
281 
282 		fork->last_sel_node = NULL;
283 
284 		switch (thr->state) {
285 		case QUE_THR_COMMAND_WAIT:
286 		case QUE_THR_COMPLETED:
287 			ut_a(!thr->is_active);
288 			que_thr_init_command(thr);
289 			break;
290 
291 		case QUE_THR_SUSPENDED:
292 		case QUE_THR_LOCK_WAIT:
293 		default:
294 			ut_error;
295 
296 		}
297 	}
298 
299 	trx_mutex_exit(fork->trx);
300 
301 	return(thr);
302 }
303 
304 /**********************************************************************//**
305 Starts execution of a command in a query fork. Picks a query thread which
306 is not in the QUE_THR_RUNNING state and moves it to that state. If none
307 can be chosen, a situation which may arise in parallelized fetches, NULL
308 is returned.
309 @return a query thread of the graph moved to QUE_THR_RUNNING state, or
310 NULL; the query thread should be executed by que_run_threads by the
311 caller */
312 que_thr_t*
que_fork_start_command(que_fork_t * fork)313 que_fork_start_command(
314 /*===================*/
315 	que_fork_t*	fork)	/*!< in: a query fork */
316 {
317 	que_thr_t*	thr;
318 	que_thr_t*	suspended_thr = NULL;
319 	que_thr_t*	completed_thr = NULL;
320 
321 	fork->state = QUE_FORK_ACTIVE;
322 
323 	fork->last_sel_node = NULL;
324 
325 	suspended_thr = NULL;
326 	completed_thr = NULL;
327 
328 	/* Choose the query thread to run: usually there is just one thread,
329 	but in a parallelized select, which necessarily is non-scrollable,
330 	there may be several to choose from */
331 
332 	/* First we try to find a query thread in the QUE_THR_COMMAND_WAIT
333 	state. Then we try to find a query thread in the QUE_THR_SUSPENDED
334 	state, finally we try to find a query thread in the QUE_THR_COMPLETED
335 	state */
336 
337 	/* We make a single pass over the thr list within which we note which
338 	threads are ready to run. */
339 	for (thr = UT_LIST_GET_FIRST(fork->thrs);
340 	     thr != NULL;
341 	     thr = UT_LIST_GET_NEXT(thrs, thr)) {
342 
343 		switch (thr->state) {
344 		case QUE_THR_COMMAND_WAIT:
345 
346 			/* We have to send the initial message to query thread
347 			to start it */
348 
349 			que_thr_init_command(thr);
350 
351 			return(thr);
352 
353 		case QUE_THR_SUSPENDED:
354 			/* In this case the execution of the thread was
355 			suspended: no initial message is needed because
356 			execution can continue from where it was left */
357 			if (!suspended_thr) {
358 				suspended_thr = thr;
359 			}
360 
361 			break;
362 
363 		case QUE_THR_COMPLETED:
364 			if (!completed_thr) {
365 				completed_thr = thr;
366 			}
367 
368 			break;
369 
370 		case QUE_THR_RUNNING:
371 		case QUE_THR_LOCK_WAIT:
372 		case QUE_THR_PROCEDURE_WAIT:
373 			ut_error;
374 		}
375 	}
376 
377 	if (suspended_thr) {
378 
379 		thr = suspended_thr;
380 		que_thr_move_to_run_state(thr);
381 
382 	} else if (completed_thr) {
383 
384 		thr = completed_thr;
385 		que_thr_init_command(thr);
386 	} else {
387 		ut_error;
388 	}
389 
390 	return(thr);
391 }
392 
393 /**********************************************************************//**
394 Calls que_graph_free_recursive for statements in a statement list. */
395 static
396 void
que_graph_free_stat_list(que_node_t * node)397 que_graph_free_stat_list(
398 /*=====================*/
399 	que_node_t*	node)	/*!< in: first query graph node in the list */
400 {
401 	while (node) {
402 		que_graph_free_recursive(node);
403 
404 		node = que_node_get_next(node);
405 	}
406 }
407 
408 /**********************************************************************//**
409 Frees a query graph, but not the heap where it was created. Does not free
410 explicit cursor declarations, they are freed in que_graph_free. */
411 void
que_graph_free_recursive(que_node_t * node)412 que_graph_free_recursive(
413 /*=====================*/
414 	que_node_t*	node)	/*!< in: query graph node */
415 {
416 	que_fork_t*	fork;
417 	que_thr_t*	thr;
418 	undo_node_t*	undo;
419 	sel_node_t*	sel;
420 	ins_node_t*	ins;
421 	upd_node_t*	upd;
422 	tab_node_t*	cre_tab;
423 	ind_node_t*	cre_ind;
424 	purge_node_t*	purge;
425 
426 	DBUG_ENTER("que_graph_free_recursive");
427 
428 	if (node == NULL) {
429 
430 		DBUG_VOID_RETURN;
431 	}
432 
433 	DBUG_PRINT("que_graph_free_recursive",
434 		   ("node: %p, type: %lu", node, que_node_get_type(node)));
435 
436 	switch (que_node_get_type(node)) {
437 
438 	case QUE_NODE_FORK:
439 		fork = static_cast<que_fork_t*>(node);
440 
441 		thr = UT_LIST_GET_FIRST(fork->thrs);
442 
443 		while (thr) {
444 			que_graph_free_recursive(thr);
445 
446 			thr = UT_LIST_GET_NEXT(thrs, thr);
447 		}
448 
449 		break;
450 	case QUE_NODE_THR:
451 
452 		thr = static_cast<que_thr_t*>(node);
453 
454 		ut_a(thr->magic_n == QUE_THR_MAGIC_N);
455 
456 		thr->magic_n = QUE_THR_MAGIC_FREED;
457 
458 		que_graph_free_recursive(thr->child);
459 
460 		break;
461 	case QUE_NODE_UNDO:
462 
463 		undo = static_cast<undo_node_t*>(node);
464 
465 		mem_heap_free(undo->heap);
466 
467 		break;
468 	case QUE_NODE_SELECT:
469 
470 		sel = static_cast<sel_node_t*>(node);
471 
472 		sel_node_free_private(sel);
473 
474 		break;
475 	case QUE_NODE_INSERT:
476 
477 		ins = static_cast<ins_node_t*>(node);
478 
479 		que_graph_free_recursive(ins->select);
480 		ins->select = NULL;
481 
482 		if (ins->entry_sys_heap != NULL) {
483 			mem_heap_free(ins->entry_sys_heap);
484 			ins->entry_sys_heap = NULL;
485 		}
486 
487 		break;
488 	case QUE_NODE_PURGE:
489 		purge = static_cast<purge_node_t*>(node);
490 
491 		mem_heap_free(purge->heap);
492 
493 		break;
494 
495 	case QUE_NODE_UPDATE:
496 		upd = static_cast<upd_node_t*>(node);
497 
498 		if (upd->in_mysql_interface) {
499 
500 			btr_pcur_free_for_mysql(upd->pcur);
501 			upd->in_mysql_interface = FALSE;
502 		}
503 
504 		que_graph_free_recursive(upd->cascade_node);
505 
506 		if (upd->cascade_heap) {
507 			mem_heap_free(upd->cascade_heap);
508 			upd->cascade_heap = NULL;
509 		}
510 
511 		que_graph_free_recursive(upd->select);
512 		upd->select = NULL;
513 
514 		if (upd->heap != NULL) {
515 			mem_heap_free(upd->heap);
516 			upd->heap = NULL;
517 		}
518 
519 		break;
520 	case QUE_NODE_CREATE_TABLE:
521 		cre_tab = static_cast<tab_node_t*>(node);
522 
523 		que_graph_free_recursive(cre_tab->tab_def);
524 		que_graph_free_recursive(cre_tab->col_def);
525 		que_graph_free_recursive(cre_tab->v_col_def);
526 
527 		mem_heap_free(cre_tab->heap);
528 
529 		break;
530 	case QUE_NODE_CREATE_INDEX:
531 		cre_ind = static_cast<ind_node_t*>(node);
532 
533 		que_graph_free_recursive(cre_ind->ind_def);
534 		que_graph_free_recursive(cre_ind->field_def);
535 
536 		mem_heap_free(cre_ind->heap);
537 
538 		break;
539 	case QUE_NODE_PROC:
540 		que_graph_free_stat_list(((proc_node_t*) node)->stat_list);
541 
542 		break;
543 	case QUE_NODE_IF:
544 		que_graph_free_stat_list(((if_node_t*) node)->stat_list);
545 		que_graph_free_stat_list(((if_node_t*) node)->else_part);
546 		que_graph_free_stat_list(((if_node_t*) node)->elsif_list);
547 
548 		break;
549 	case QUE_NODE_ELSIF:
550 		que_graph_free_stat_list(((elsif_node_t*) node)->stat_list);
551 
552 		break;
553 	case QUE_NODE_WHILE:
554 		que_graph_free_stat_list(((while_node_t*) node)->stat_list);
555 
556 		break;
557 	case QUE_NODE_FOR:
558 		que_graph_free_stat_list(((for_node_t*) node)->stat_list);
559 
560 		break;
561 
562 	case QUE_NODE_ASSIGNMENT:
563 	case QUE_NODE_EXIT:
564 	case QUE_NODE_RETURN:
565 	case QUE_NODE_COMMIT:
566 	case QUE_NODE_ROLLBACK:
567 	case QUE_NODE_LOCK:
568 	case QUE_NODE_FUNC:
569 	case QUE_NODE_ORDER:
570 	case QUE_NODE_ROW_PRINTF:
571 	case QUE_NODE_OPEN:
572 	case QUE_NODE_FETCH:
573 		/* No need to do anything */
574 
575 		break;
576 	default:
577 		ut_error;
578 	}
579 
580 	DBUG_VOID_RETURN;
581 }
582 
583 /**********************************************************************//**
584 Frees a query graph. */
585 void
que_graph_free(que_t * graph)586 que_graph_free(
587 /*===========*/
588 	que_t*	graph)	/*!< in: query graph; we assume that the memory
589 			heap where this graph was created is private
590 			to this graph: if not, then use
591 			que_graph_free_recursive and free the heap
592 			afterwards! */
593 {
594 	ut_ad(graph);
595 
596 	if (graph->sym_tab) {
597 		/* The following call frees dynamic memory allocated
598 		for variables etc. during execution. Frees also explicit
599 		cursor definitions. */
600 
601 		sym_tab_free_private(graph->sym_tab);
602 	}
603 
604 	if (graph->info && graph->info->graph_owns_us) {
605 		pars_info_free(graph->info);
606 	}
607 
608 	que_graph_free_recursive(graph);
609 
610 	mem_heap_free(graph->heap);
611 }
612 
613 /****************************************************************//**
614 Performs an execution step on a thr node.
615 @return query thread to run next, or NULL if none */
616 static
617 que_thr_t*
que_thr_node_step(que_thr_t * thr)618 que_thr_node_step(
619 /*==============*/
620 	que_thr_t*	thr)	/*!< in: query thread where run_node must
621 				be the thread node itself */
622 {
623 	ut_ad(thr->run_node == thr);
624 
625 	if (thr->prev_node == thr->common.parent) {
626 		/* If control to the node came from above, it is just passed
627 		on */
628 
629 		thr->run_node = thr->child;
630 
631 		return(thr);
632 	}
633 
634 	trx_mutex_enter(thr_get_trx(thr));
635 
636 	if (que_thr_peek_stop(thr)) {
637 
638 		trx_mutex_exit(thr_get_trx(thr));
639 
640 		return(thr);
641 	}
642 
643 	/* Thread execution completed */
644 
645 	thr->state = QUE_THR_COMPLETED;
646 
647 	trx_mutex_exit(thr_get_trx(thr));
648 
649 	return(NULL);
650 }
651 
652 /**********************************************************************//**
653 Moves a thread from another state to the QUE_THR_RUNNING state. Increments
654 the n_active_thrs counters of the query graph and transaction if thr was
655 not active.
656 ***NOTE***: This and ..._mysql are  the only functions in which such a
657 transition is allowed to happen! */
658 static
659 void
que_thr_move_to_run_state(que_thr_t * thr)660 que_thr_move_to_run_state(
661 /*======================*/
662 	que_thr_t*	thr)	/*!< in: an query thread */
663 {
664 	ut_ad(thr->state != QUE_THR_RUNNING);
665 
666 	if (!thr->is_active) {
667 		trx_t*	trx;
668 
669 		trx = thr_get_trx(thr);
670 
671 		thr->graph->n_active_thrs++;
672 
673 		trx->lock.n_active_thrs++;
674 
675 		thr->is_active = TRUE;
676 	}
677 
678 	thr->state = QUE_THR_RUNNING;
679 }
680 
681 /**********************************************************************//**
682 Stops a query thread if graph or trx is in a state requiring it. The
683 conditions are tested in the order (1) graph, (2) trx.
684 @return TRUE if stopped */
685 ibool
que_thr_stop(que_thr_t * thr)686 que_thr_stop(
687 /*=========*/
688 	que_thr_t*	thr)	/*!< in: query thread */
689 {
690 	que_t*		graph;
691 	trx_t*		trx = thr_get_trx(thr);
692 
693 	graph = thr->graph;
694 
695 	ut_ad(trx_mutex_own(trx));
696 
697 	if (graph->state == QUE_FORK_COMMAND_WAIT) {
698 
699 		thr->state = QUE_THR_SUSPENDED;
700 
701 	} else if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
702 
703 		trx->lock.wait_thr = thr;
704 		thr->state = QUE_THR_LOCK_WAIT;
705 
706 	} else if (trx->error_state != DB_SUCCESS
707 		   && trx->error_state != DB_LOCK_WAIT) {
708 
709 		/* Error handling built for the MySQL interface */
710 		thr->state = QUE_THR_COMPLETED;
711 
712 	} else if (graph->fork_type == QUE_FORK_ROLLBACK) {
713 
714 		thr->state = QUE_THR_SUSPENDED;
715 	} else {
716 		ut_ad(graph->state == QUE_FORK_ACTIVE);
717 
718 		return(FALSE);
719 	}
720 
721 	return(TRUE);
722 }
723 
724 /**********************************************************************//**
725 Decrements the query thread reference counts in the query graph and the
726 transaction.
727 *** NOTE ***:
728 This and que_thr_stop_for_mysql are the only functions where the reference
729 count can be decremented and this function may only be called from inside
730 que_run_threads! These restrictions exist to make the rollback code easier
731 to maintain. */
732 static
733 void
que_thr_dec_refer_count(que_thr_t * thr,que_thr_t ** next_thr)734 que_thr_dec_refer_count(
735 /*====================*/
736 	que_thr_t*	thr,		/*!< in: query thread */
737 	que_thr_t**	next_thr)	/*!< in/out: next query thread to run;
738 					if the value which is passed in is
739 					a pointer to a NULL pointer, then the
740 					calling function can start running
741 					a new query thread */
742 {
743 	trx_t*		trx;
744 	que_fork_t*	fork;
745 
746 	trx = thr_get_trx(thr);
747 
748 	ut_a(thr->is_active);
749 	ut_ad(trx_mutex_own(trx));
750 
751 	if (thr->state == QUE_THR_RUNNING) {
752 
753 		if (!que_thr_stop(thr)) {
754 
755 			ut_a(next_thr != NULL && *next_thr == NULL);
756 
757 			/* The reason for the thr suspension or wait was
758 			already canceled before we came here: continue
759 			running the thread.
760 
761 			This is also possible because in trx_commit_step() we
762 			assume a single query thread. We set the query thread
763 			state to QUE_THR_RUNNING. */
764 
765 			/* fprintf(stderr,
766 		       		"Wait already ended: trx: %p\n", trx); */
767 
768 			/* Normally srv_suspend_mysql_thread resets
769 			the state to DB_SUCCESS before waiting, but
770 			in this case we have to do it here,
771 			otherwise nobody does it. */
772 
773 			trx->error_state = DB_SUCCESS;
774 
775 			*next_thr = thr;
776 
777 			return;
778 		}
779 	}
780 
781 	fork = static_cast<que_fork_t*>(thr->common.parent);
782 
783 	--trx->lock.n_active_thrs;
784 
785 	--fork->n_active_thrs;
786 
787 	thr->is_active = FALSE;
788 }
789 
790 /**********************************************************************//**
791 A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
792 query thread is stopped and made inactive, except in the case where
793 it was put to the lock wait state in lock0lock.cc, but the lock has already
794 been granted or the transaction chosen as a victim in deadlock resolution. */
795 void
que_thr_stop_for_mysql(que_thr_t * thr)796 que_thr_stop_for_mysql(
797 /*===================*/
798 	que_thr_t*	thr)	/*!< in: query thread */
799 {
800 	trx_t*	trx;
801 
802 	trx = thr_get_trx(thr);
803 
804 	trx_mutex_enter(trx);
805 
806 	if (thr->state == QUE_THR_RUNNING) {
807 
808 		if (trx->error_state != DB_SUCCESS
809 		    && trx->error_state != DB_LOCK_WAIT) {
810 
811 			/* Error handling built for the MySQL interface */
812 			thr->state = QUE_THR_COMPLETED;
813 		} else {
814 			/* It must have been a lock wait but the lock was
815 			already released, or this transaction was chosen
816 			as a victim in selective deadlock resolution */
817 
818 			trx_mutex_exit(trx);
819 
820 			return;
821 		}
822 	}
823 
824 	ut_ad(thr->is_active == TRUE);
825 	ut_ad(trx->lock.n_active_thrs == 1);
826 	ut_ad(thr->graph->n_active_thrs == 1);
827 
828 	thr->is_active = FALSE;
829 	thr->graph->n_active_thrs--;
830 
831 	trx->lock.n_active_thrs--;
832 
833 	trx_mutex_exit(trx);
834 }
835 
836 /**********************************************************************//**
837 Moves a thread from another state to the QUE_THR_RUNNING state. Increments
838 the n_active_thrs counters of the query graph and transaction if thr was
839 not active. */
840 void
que_thr_move_to_run_state_for_mysql(que_thr_t * thr,trx_t * trx)841 que_thr_move_to_run_state_for_mysql(
842 /*================================*/
843 	que_thr_t*	thr,	/*!< in: an query thread */
844 	trx_t*		trx)	/*!< in: transaction */
845 {
846 	ut_a(thr->magic_n == QUE_THR_MAGIC_N);
847 
848 	if (!thr->is_active) {
849 
850 		thr->graph->n_active_thrs++;
851 
852 		trx->lock.n_active_thrs++;
853 
854 		thr->is_active = TRUE;
855 	}
856 
857 	thr->state = QUE_THR_RUNNING;
858 }
859 
860 /**********************************************************************//**
861 A patch for MySQL used to 'stop' a dummy query thread used in MySQL
862 select, when there is no error or lock wait. */
863 void
que_thr_stop_for_mysql_no_error(que_thr_t * thr,trx_t * trx)864 que_thr_stop_for_mysql_no_error(
865 /*============================*/
866 	que_thr_t*	thr,	/*!< in: query thread */
867 	trx_t*		trx)	/*!< in: transaction */
868 {
869 	ut_ad(thr->state == QUE_THR_RUNNING);
870 	ut_ad(thr->is_active == TRUE);
871 	ut_ad(trx->lock.n_active_thrs == 1);
872 	ut_ad(thr->graph->n_active_thrs == 1);
873 	ut_a(thr->magic_n == QUE_THR_MAGIC_N);
874 
875 	thr->state = QUE_THR_COMPLETED;
876 
877 	thr->is_active = FALSE;
878 	thr->graph->n_active_thrs--;
879 
880 	trx->lock.n_active_thrs--;
881 }
882 
883 /****************************************************************//**
884 Get the first containing loop node (e.g. while_node_t or for_node_t) for the
885 given node, or NULL if the node is not within a loop.
886 @return containing loop node, or NULL. */
887 que_node_t*
que_node_get_containing_loop_node(que_node_t * node)888 que_node_get_containing_loop_node(
889 /*==============================*/
890 	que_node_t*	node)	/*!< in: node */
891 {
892 	ut_ad(node);
893 
894 	for (;;) {
895 		ulint	type;
896 
897 		node = que_node_get_parent(node);
898 
899 		if (!node) {
900 			break;
901 		}
902 
903 		type = que_node_get_type(node);
904 
905 		if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
906 			break;
907 		}
908 	}
909 
910 	return(node);
911 }
912 
913 #ifndef NDEBUG
914 /** Gets information of an SQL query graph node.
915 @return type description */
916 static MY_ATTRIBUTE((warn_unused_result, nonnull))
917 const char*
que_node_type_string(const que_node_t * node)918 que_node_type_string(
919 /*=================*/
920 	const que_node_t*	node)	/*!< in: query graph node */
921 {
922 	switch (que_node_get_type(node)) {
923 	case QUE_NODE_SELECT:
924 		return("SELECT");
925 	case QUE_NODE_INSERT:
926 		return("INSERT");
927 	case QUE_NODE_UPDATE:
928 		return("UPDATE");
929 	case QUE_NODE_WHILE:
930 		return("WHILE");
931 	case QUE_NODE_ASSIGNMENT:
932 		return("ASSIGNMENT");
933 	case QUE_NODE_IF:
934 		return("IF");
935 	case QUE_NODE_FETCH:
936 		return("FETCH");
937 	case QUE_NODE_OPEN:
938 		return("OPEN");
939 	case QUE_NODE_PROC:
940 		return("STORED PROCEDURE");
941 	case QUE_NODE_FUNC:
942 		return("FUNCTION");
943 	case QUE_NODE_LOCK:
944 		return("LOCK");
945 	case QUE_NODE_THR:
946 		return("QUERY THREAD");
947 	case QUE_NODE_COMMIT:
948 		return("COMMIT");
949 	case QUE_NODE_UNDO:
950 		return("UNDO ROW");
951 	case QUE_NODE_PURGE:
952 		return("PURGE ROW");
953 	case QUE_NODE_ROLLBACK:
954 		return("ROLLBACK");
955 	case QUE_NODE_CREATE_TABLE:
956 		return("CREATE TABLE");
957 	case QUE_NODE_CREATE_INDEX:
958 		return("CREATE INDEX");
959 	case QUE_NODE_FOR:
960 		return("FOR LOOP");
961 	case QUE_NODE_RETURN:
962 		return("RETURN");
963 	case QUE_NODE_EXIT:
964 		return("EXIT");
965 	default:
966 		ut_ad(0);
967 		return("UNKNOWN NODE TYPE");
968 	}
969 }
970 #endif /* !NDEBUG */
971 
972 /**********************************************************************//**
973 Performs an execution step on a query thread.
974 @return query thread to run next: it may differ from the input
975 parameter if, e.g., a subprocedure call is made */
976 UNIV_INLINE
977 que_thr_t*
que_thr_step(que_thr_t * thr)978 que_thr_step(
979 /*=========*/
980 	que_thr_t*	thr)	/*!< in: query thread */
981 {
982 	que_node_t*	node;
983 	que_thr_t*	old_thr;
984 	trx_t*		trx;
985 	ulint		type;
986 
987 	trx = thr_get_trx(thr);
988 
989 	ut_ad(thr->state == QUE_THR_RUNNING);
990 	ut_a(trx->error_state == DB_SUCCESS);
991 
992 	thr->resource++;
993 
994 	node = thr->run_node;
995 	type = que_node_get_type(node);
996 
997 	old_thr = thr;
998 
999 	DBUG_PRINT("ib_que", ("Execute %u (%s) at %p",
1000 			      unsigned(type), que_node_type_string(node),
1001 			      (const void*) node));
1002 
1003 	if (type & QUE_NODE_CONTROL_STAT) {
1004 		if ((thr->prev_node != que_node_get_parent(node))
1005 		    && que_node_get_next(thr->prev_node)) {
1006 
1007 			/* The control statements, like WHILE, always pass the
1008 			control to the next child statement if there is any
1009 			child left */
1010 
1011 			thr->run_node = que_node_get_next(thr->prev_node);
1012 
1013 		} else if (type == QUE_NODE_IF) {
1014 			if_step(thr);
1015 		} else if (type == QUE_NODE_FOR) {
1016 			for_step(thr);
1017 		} else if (type == QUE_NODE_PROC) {
1018 
1019 			/* We can access trx->undo_no without reserving
1020 			trx->undo_mutex, because there cannot be active query
1021 			threads doing updating or inserting at the moment! */
1022 
1023 			if (thr->prev_node == que_node_get_parent(node)) {
1024 				trx->last_sql_stat_start.least_undo_no
1025 					= trx->undo_no;
1026 			}
1027 
1028 			proc_step(thr);
1029 		} else if (type == QUE_NODE_WHILE) {
1030 			while_step(thr);
1031 		} else {
1032 			ut_error;
1033 		}
1034 	} else if (type == QUE_NODE_ASSIGNMENT) {
1035 		assign_step(thr);
1036 	} else if (type == QUE_NODE_SELECT) {
1037 		thr = row_sel_step(thr);
1038 	} else if (type == QUE_NODE_INSERT) {
1039 		thr = row_ins_step(thr);
1040 	} else if (type == QUE_NODE_UPDATE) {
1041 		thr = row_upd_step(thr);
1042 	} else if (type == QUE_NODE_FETCH) {
1043 		thr = fetch_step(thr);
1044 	} else if (type == QUE_NODE_OPEN) {
1045 		thr = open_step(thr);
1046 	} else if (type == QUE_NODE_FUNC) {
1047 		proc_eval_step(thr);
1048 
1049 	} else if (type == QUE_NODE_LOCK) {
1050 
1051 		ut_error;
1052 	} else if (type == QUE_NODE_THR) {
1053 		thr = que_thr_node_step(thr);
1054 	} else if (type == QUE_NODE_COMMIT) {
1055 		thr = trx_commit_step(thr);
1056 	} else if (type == QUE_NODE_UNDO) {
1057 		thr = row_undo_step(thr);
1058 	} else if (type == QUE_NODE_PURGE) {
1059 		thr = row_purge_step(thr);
1060 	} else if (type == QUE_NODE_RETURN) {
1061 		thr = return_step(thr);
1062 	} else if (type == QUE_NODE_EXIT) {
1063 		thr = exit_step(thr);
1064 	} else if (type == QUE_NODE_ROLLBACK) {
1065 		thr = trx_rollback_step(thr);
1066 	} else if (type == QUE_NODE_CREATE_TABLE) {
1067 		thr = dict_create_table_step(thr);
1068 	} else if (type == QUE_NODE_CREATE_INDEX) {
1069 		thr = dict_create_index_step(thr);
1070 	} else if (type == QUE_NODE_ROW_PRINTF) {
1071 		thr = row_printf_step(thr);
1072 	} else {
1073 		ut_error;
1074 	}
1075 
1076 	if (type == QUE_NODE_EXIT) {
1077 		old_thr->prev_node = que_node_get_containing_loop_node(node);
1078 	} else {
1079 		old_thr->prev_node = node;
1080 	}
1081 
1082 	if (thr) {
1083 		ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1084 	}
1085 
1086 	return(thr);
1087 }
1088 
1089 /**********************************************************************//**
1090 Run a query thread until it finishes or encounters e.g. a lock wait. */
1091 static
1092 void
que_run_threads_low(que_thr_t * thr)1093 que_run_threads_low(
1094 /*================*/
1095 	que_thr_t*	thr)	/*!< in: query thread */
1096 {
1097 	trx_t*		trx;
1098 	que_thr_t*	next_thr;
1099 
1100 	ut_ad(thr->state == QUE_THR_RUNNING);
1101 	ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1102 	ut_ad(!trx_mutex_own(thr_get_trx(thr)));
1103 
1104 	/* cumul_resource counts how much resources the OS thread (NOT the
1105 	query thread) has spent in this function */
1106 
1107 	trx = thr_get_trx(thr);
1108 
1109 	do {
1110 		/* Check that there is enough space in the log to accommodate
1111 		possible log entries by this query step; if the operation can
1112 		touch more than about 4 pages, checks must be made also within
1113 		the query step! */
1114 
1115 		log_free_check();
1116 
1117 		/* Perform the actual query step: note that the query thread
1118 		may change if, e.g., a subprocedure call is made */
1119 
1120 		/*-------------------------*/
1121 		next_thr = que_thr_step(thr);
1122 		/*-------------------------*/
1123 
1124 		trx_mutex_enter(trx);
1125 
1126 		ut_a(next_thr == NULL || trx->error_state == DB_SUCCESS);
1127 
1128 		if (next_thr != thr) {
1129 			ut_a(next_thr == NULL);
1130 
1131 			/* This can change next_thr to a non-NULL value
1132 			if there was a lock wait that already completed. */
1133 
1134 			que_thr_dec_refer_count(thr, &next_thr);
1135 
1136 			if (next_thr != NULL) {
1137 
1138 				thr = next_thr;
1139 			}
1140 		}
1141 
1142 		ut_ad(trx == thr_get_trx(thr));
1143 
1144 		trx_mutex_exit(trx);
1145 
1146 	} while (next_thr != NULL);
1147 }
1148 
1149 /**********************************************************************//**
1150 Run a query thread. Handles lock waits. */
1151 void
que_run_threads(que_thr_t * thr)1152 que_run_threads(
1153 /*============*/
1154 	que_thr_t*	thr)	/*!< in: query thread */
1155 {
1156 	ut_ad(!trx_mutex_own(thr_get_trx(thr)));
1157 
1158 loop:
1159 	ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1160 
1161 	que_run_threads_low(thr);
1162 
1163 	switch (thr->state) {
1164 
1165 	case QUE_THR_RUNNING:
1166 		/* There probably was a lock wait, but it already ended
1167 		before we came here: continue running thr */
1168 
1169 		goto loop;
1170 
1171 	case QUE_THR_LOCK_WAIT:
1172 		lock_wait_suspend_thread(thr);
1173 
1174 		trx_mutex_enter(thr_get_trx(thr));
1175 
1176 		ut_a(thr_get_trx(thr)->id != 0);
1177 
1178 		if (thr_get_trx(thr)->error_state != DB_SUCCESS) {
1179 			/* thr was chosen as a deadlock victim or there was
1180 			a lock wait timeout */
1181 
1182 			que_thr_dec_refer_count(thr, NULL);
1183 			trx_mutex_exit(thr_get_trx(thr));
1184 			break;
1185 		}
1186 
1187 		trx_mutex_exit(thr_get_trx(thr));
1188 		goto loop;
1189 
1190 	case QUE_THR_COMPLETED:
1191 	case QUE_THR_COMMAND_WAIT:
1192 		/* Do nothing */
1193 		break;
1194 
1195 	default:
1196 		ut_error;
1197 	}
1198 }
1199 
1200 /*********************************************************************//**
1201 Evaluate the given SQL.
1202 @return error code or DB_SUCCESS */
1203 dberr_t
que_eval_sql(pars_info_t * info,const char * sql,ibool reserve_dict_mutex,trx_t * trx)1204 que_eval_sql(
1205 /*=========*/
1206 	pars_info_t*	info,	/*!< in: info struct, or NULL */
1207 	const char*	sql,	/*!< in: SQL string */
1208 	ibool		reserve_dict_mutex,
1209 				/*!< in: if TRUE, acquire/release
1210 				dict_sys->mutex around call to pars_sql. */
1211 	trx_t*		trx)	/*!< in: trx */
1212 {
1213 	que_thr_t*	thr;
1214 	que_t*		graph;
1215 
1216 	DBUG_ENTER("que_eval_sql");
1217 	DBUG_PRINT("que_eval_sql", ("query: %s", sql));
1218 
1219 	ut_a(trx->error_state == DB_SUCCESS);
1220 
1221 	if (reserve_dict_mutex) {
1222 		mutex_enter(&dict_sys->mutex);
1223 	}
1224 
1225 	graph = pars_sql(info, sql);
1226 
1227 	if (reserve_dict_mutex) {
1228 		mutex_exit(&dict_sys->mutex);
1229 	}
1230 
1231 	graph->trx = trx;
1232 	trx->graph = NULL;
1233 
1234 	graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
1235 
1236 	ut_a(thr = que_fork_start_command(graph));
1237 
1238 	que_run_threads(thr);
1239 
1240 	if (reserve_dict_mutex) {
1241 		mutex_enter(&dict_sys->mutex);
1242 	}
1243 
1244 	que_graph_free(graph);
1245 
1246 	if (reserve_dict_mutex) {
1247 		mutex_exit(&dict_sys->mutex);
1248 	}
1249 
1250 	ut_a(trx->error_state != 0);
1251 
1252 	DBUG_RETURN(trx->error_state);
1253 }
1254 
1255 /*********************************************************************//**
1256 Initialise the query sub-system. */
1257 void
que_init(void)1258 que_init(void)
1259 /*==========*/
1260 {
1261 	/* No op */
1262 }
1263 
1264 /*********************************************************************//**
1265 Close the query sub-system. */
1266 void
que_close(void)1267 que_close(void)
1268 /*===========*/
1269 {
1270 	/* No op */
1271 }
1272