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