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->lock.que_state = TRX_QUE_RUNNING;
233 
234 	trx->lock.wait_thr = NULL;
235 
236 	/* In MySQL we let the OS thread (not just the query thread) to wait
237 	for the lock to be released: */
238 
239 	return((!was_active && thr != NULL) ? thr : NULL);
240 }
241 
242 /**********************************************************************//**
243 Inits a query thread for a command. */
244 UNIV_INLINE
245 void
que_thr_init_command(que_thr_t * thr)246 que_thr_init_command(
247 /*=================*/
248 	que_thr_t*	thr)	/*!< in: query thread */
249 {
250 	thr->run_node = thr;
251 	thr->prev_node = thr->common.parent;
252 
253 	que_thr_move_to_run_state(thr);
254 }
255 
256 /**********************************************************************//**
257 Round robin scheduler.
258 @return a query thread of the graph moved to QUE_THR_RUNNING state, or
259 NULL; the query thread should be executed by que_run_threads by the
260 caller */
261 que_thr_t*
que_fork_scheduler_round_robin(que_fork_t * fork,que_thr_t * thr)262 que_fork_scheduler_round_robin(
263 /*===========================*/
264 	que_fork_t*	fork,		/*!< in: a query fork */
265 	que_thr_t*	thr)		/*!< in: current pos */
266 {
267 	trx_mutex_enter(fork->trx);
268 
269 	/* If no current, start first available. */
270 	if (thr == NULL) {
271 		thr = UT_LIST_GET_FIRST(fork->thrs);
272 	} else {
273 		thr = UT_LIST_GET_NEXT(thrs, thr);
274 	}
275 
276 	if (thr) {
277 
278 		fork->state = QUE_FORK_ACTIVE;
279 
280 		fork->last_sel_node = NULL;
281 
282 		switch (thr->state) {
283 		case QUE_THR_COMMAND_WAIT:
284 		case QUE_THR_COMPLETED:
285 			ut_a(!thr->is_active);
286 			que_thr_init_command(thr);
287 			break;
288 
289 		case QUE_THR_SUSPENDED:
290 		case QUE_THR_LOCK_WAIT:
291 		default:
292 			ut_error;
293 
294 		}
295 	}
296 
297 	trx_mutex_exit(fork->trx);
298 
299 	return(thr);
300 }
301 
302 /**********************************************************************//**
303 Starts execution of a command in a query fork. Picks a query thread which
304 is not in the QUE_THR_RUNNING state and moves it to that state. If none
305 can be chosen, a situation which may arise in parallelized fetches, NULL
306 is returned.
307 @return a query thread of the graph moved to QUE_THR_RUNNING state, or
308 NULL; the query thread should be executed by que_run_threads by the
309 caller */
310 que_thr_t*
que_fork_start_command(que_fork_t * fork)311 que_fork_start_command(
312 /*===================*/
313 	que_fork_t*	fork)	/*!< in: a query fork */
314 {
315 	que_thr_t*	thr;
316 	que_thr_t*	suspended_thr = NULL;
317 	que_thr_t*	completed_thr = NULL;
318 
319 	fork->state = QUE_FORK_ACTIVE;
320 
321 	fork->last_sel_node = NULL;
322 
323 	suspended_thr = NULL;
324 	completed_thr = NULL;
325 
326 	/* Choose the query thread to run: usually there is just one thread,
327 	but in a parallelized select, which necessarily is non-scrollable,
328 	there may be several to choose from */
329 
330 	/* First we try to find a query thread in the QUE_THR_COMMAND_WAIT
331 	state. Then we try to find a query thread in the QUE_THR_SUSPENDED
332 	state, finally we try to find a query thread in the QUE_THR_COMPLETED
333 	state */
334 
335 	/* We make a single pass over the thr list within which we note which
336 	threads are ready to run. */
337 	for (thr = UT_LIST_GET_FIRST(fork->thrs);
338 	     thr != NULL;
339 	     thr = UT_LIST_GET_NEXT(thrs, thr)) {
340 
341 		switch (thr->state) {
342 		case QUE_THR_COMMAND_WAIT:
343 
344 			/* We have to send the initial message to query thread
345 			to start it */
346 
347 			que_thr_init_command(thr);
348 
349 			return(thr);
350 
351 		case QUE_THR_SUSPENDED:
352 			/* In this case the execution of the thread was
353 			suspended: no initial message is needed because
354 			execution can continue from where it was left */
355 			if (!suspended_thr) {
356 				suspended_thr = thr;
357 			}
358 
359 			break;
360 
361 		case QUE_THR_COMPLETED:
362 			if (!completed_thr) {
363 				completed_thr = thr;
364 			}
365 
366 			break;
367 
368 		case QUE_THR_RUNNING:
369 		case QUE_THR_LOCK_WAIT:
370 		case QUE_THR_PROCEDURE_WAIT:
371 			ut_error;
372 		}
373 	}
374 
375 	if (suspended_thr) {
376 
377 		thr = suspended_thr;
378 		que_thr_move_to_run_state(thr);
379 
380 	} else if (completed_thr) {
381 
382 		thr = completed_thr;
383 		que_thr_init_command(thr);
384 	} else {
385 		ut_error;
386 	}
387 
388 	return(thr);
389 }
390 
391 /**********************************************************************//**
392 Calls que_graph_free_recursive for statements in a statement list. */
393 static
394 void
que_graph_free_stat_list(que_node_t * node)395 que_graph_free_stat_list(
396 /*=====================*/
397 	que_node_t*	node)	/*!< in: first query graph node in the list */
398 {
399 	while (node) {
400 		que_graph_free_recursive(node);
401 
402 		node = que_node_get_next(node);
403 	}
404 }
405 
406 /**********************************************************************//**
407 Frees a query graph, but not the heap where it was created. Does not free
408 explicit cursor declarations, they are freed in que_graph_free. */
409 void
que_graph_free_recursive(que_node_t * node)410 que_graph_free_recursive(
411 /*=====================*/
412 	que_node_t*	node)	/*!< in: query graph node */
413 {
414 	que_fork_t*	fork;
415 	que_thr_t*	thr;
416 	undo_node_t*	undo;
417 	sel_node_t*	sel;
418 	ins_node_t*	ins;
419 	upd_node_t*	upd;
420 	tab_node_t*	cre_tab;
421 	ind_node_t*	cre_ind;
422 	purge_node_t*	purge;
423 
424 	DBUG_ENTER("que_graph_free_recursive");
425 
426 	if (node == NULL) {
427 
428 		DBUG_VOID_RETURN;
429 	}
430 
431 	DBUG_PRINT("que_graph_free_recursive",
432 		   ("node: %p, type: %lu", node, que_node_get_type(node)));
433 
434 	switch (que_node_get_type(node)) {
435 
436 	case QUE_NODE_FORK:
437 		fork = static_cast<que_fork_t*>(node);
438 
439 		thr = UT_LIST_GET_FIRST(fork->thrs);
440 
441 		while (thr) {
442 			que_graph_free_recursive(thr);
443 
444 			thr = UT_LIST_GET_NEXT(thrs, thr);
445 		}
446 
447 		break;
448 	case QUE_NODE_THR:
449 
450 		thr = static_cast<que_thr_t*>(node);
451 
452 		ut_a(thr->magic_n == QUE_THR_MAGIC_N);
453 
454 		thr->magic_n = QUE_THR_MAGIC_FREED;
455 
456 		que_graph_free_recursive(thr->child);
457 
458 		break;
459 	case QUE_NODE_UNDO:
460 
461 		undo = static_cast<undo_node_t*>(node);
462 
463 		mem_heap_free(undo->heap);
464 
465 		break;
466 	case QUE_NODE_SELECT:
467 
468 		sel = static_cast<sel_node_t*>(node);
469 
470 		sel_node_free_private(sel);
471 
472 		break;
473 	case QUE_NODE_INSERT:
474 
475 		ins = static_cast<ins_node_t*>(node);
476 
477 		que_graph_free_recursive(ins->select);
478 		ins->select = NULL;
479 
480 		if (ins->entry_sys_heap != NULL) {
481 			mem_heap_free(ins->entry_sys_heap);
482 			ins->entry_sys_heap = NULL;
483 		}
484 
485 		break;
486 	case QUE_NODE_PURGE:
487 		purge = static_cast<purge_node_t*>(node);
488 
489 		mem_heap_free(purge->heap);
490 
491 		break;
492 
493 	case QUE_NODE_UPDATE:
494 		upd = static_cast<upd_node_t*>(node);
495 
496 		if (upd->in_mysql_interface) {
497 
498 			btr_pcur_free_for_mysql(upd->pcur);
499 			upd->in_mysql_interface = FALSE;
500 		}
501 
502 		que_graph_free_recursive(upd->cascade_node);
503 
504 		if (upd->cascade_heap) {
505 			mem_heap_free(upd->cascade_heap);
506 			upd->cascade_heap = NULL;
507 		}
508 
509 		que_graph_free_recursive(upd->select);
510 		upd->select = NULL;
511 
512 		if (upd->heap != NULL) {
513 			mem_heap_free(upd->heap);
514 			upd->heap = NULL;
515 		}
516 
517 		break;
518 	case QUE_NODE_CREATE_TABLE:
519 		cre_tab = static_cast<tab_node_t*>(node);
520 
521 		que_graph_free_recursive(cre_tab->tab_def);
522 		que_graph_free_recursive(cre_tab->col_def);
523 		que_graph_free_recursive(cre_tab->v_col_def);
524 
525 		mem_heap_free(cre_tab->heap);
526 
527 		break;
528 	case QUE_NODE_CREATE_INDEX:
529 		cre_ind = static_cast<ind_node_t*>(node);
530 
531 		que_graph_free_recursive(cre_ind->ind_def);
532 		que_graph_free_recursive(cre_ind->field_def);
533 
534 		mem_heap_free(cre_ind->heap);
535 
536 		break;
537 	case QUE_NODE_PROC:
538 		que_graph_free_stat_list(((proc_node_t*) node)->stat_list);
539 
540 		break;
541 	case QUE_NODE_IF:
542 		que_graph_free_stat_list(((if_node_t*) node)->stat_list);
543 		que_graph_free_stat_list(((if_node_t*) node)->else_part);
544 		que_graph_free_stat_list(((if_node_t*) node)->elsif_list);
545 
546 		break;
547 	case QUE_NODE_ELSIF:
548 		que_graph_free_stat_list(((elsif_node_t*) node)->stat_list);
549 
550 		break;
551 	case QUE_NODE_WHILE:
552 		que_graph_free_stat_list(((while_node_t*) node)->stat_list);
553 
554 		break;
555 	case QUE_NODE_FOR:
556 		que_graph_free_stat_list(((for_node_t*) node)->stat_list);
557 
558 		break;
559 
560 	case QUE_NODE_ASSIGNMENT:
561 	case QUE_NODE_EXIT:
562 	case QUE_NODE_RETURN:
563 	case QUE_NODE_COMMIT:
564 	case QUE_NODE_ROLLBACK:
565 	case QUE_NODE_LOCK:
566 	case QUE_NODE_FUNC:
567 	case QUE_NODE_ORDER:
568 	case QUE_NODE_ROW_PRINTF:
569 	case QUE_NODE_OPEN:
570 	case QUE_NODE_FETCH:
571 		/* No need to do anything */
572 
573 		break;
574 	default:
575 		ut_error;
576 	}
577 
578 	DBUG_VOID_RETURN;
579 }
580 
581 /**********************************************************************//**
582 Frees a query graph. */
583 void
que_graph_free(que_t * graph)584 que_graph_free(
585 /*===========*/
586 	que_t*	graph)	/*!< in: query graph; we assume that the memory
587 			heap where this graph was created is private
588 			to this graph: if not, then use
589 			que_graph_free_recursive and free the heap
590 			afterwards! */
591 {
592 	ut_ad(graph);
593 
594 	if (graph->sym_tab) {
595 		/* The following call frees dynamic memory allocated
596 		for variables etc. during execution. Frees also explicit
597 		cursor definitions. */
598 
599 		sym_tab_free_private(graph->sym_tab);
600 	}
601 
602 	if (graph->info && graph->info->graph_owns_us) {
603 		pars_info_free(graph->info);
604 	}
605 
606 	que_graph_free_recursive(graph);
607 
608 	mem_heap_free(graph->heap);
609 }
610 
611 /****************************************************************//**
612 Performs an execution step on a thr node.
613 @return query thread to run next, or NULL if none */
614 static
615 que_thr_t*
que_thr_node_step(que_thr_t * thr)616 que_thr_node_step(
617 /*==============*/
618 	que_thr_t*	thr)	/*!< in: query thread where run_node must
619 				be the thread node itself */
620 {
621 	ut_ad(thr->run_node == thr);
622 
623 	if (thr->prev_node == thr->common.parent) {
624 		/* If control to the node came from above, it is just passed
625 		on */
626 
627 		thr->run_node = thr->child;
628 
629 		return(thr);
630 	}
631 
632 	trx_mutex_enter(thr_get_trx(thr));
633 
634 	if (que_thr_peek_stop(thr)) {
635 
636 		trx_mutex_exit(thr_get_trx(thr));
637 
638 		return(thr);
639 	}
640 
641 	/* Thread execution completed */
642 
643 	thr->state = QUE_THR_COMPLETED;
644 
645 	trx_mutex_exit(thr_get_trx(thr));
646 
647 	return(NULL);
648 }
649 
650 /**********************************************************************//**
651 Moves a thread from another state to the QUE_THR_RUNNING state. Increments
652 the n_active_thrs counters of the query graph and transaction if thr was
653 not active.
654 ***NOTE***: This and ..._mysql are  the only functions in which such a
655 transition is allowed to happen! */
656 static
657 void
que_thr_move_to_run_state(que_thr_t * thr)658 que_thr_move_to_run_state(
659 /*======================*/
660 	que_thr_t*	thr)	/*!< in: an query thread */
661 {
662 	ut_ad(thr->state != QUE_THR_RUNNING);
663 
664 	if (!thr->is_active) {
665 		trx_t*	trx;
666 
667 		trx = thr_get_trx(thr);
668 
669 		thr->graph->n_active_thrs++;
670 
671 		trx->lock.n_active_thrs++;
672 
673 		thr->is_active = TRUE;
674 	}
675 
676 	thr->state = QUE_THR_RUNNING;
677 }
678 
679 /**********************************************************************//**
680 Stops a query thread if graph or trx is in a state requiring it. The
681 conditions are tested in the order (1) graph, (2) trx.
682 @return TRUE if stopped */
683 ibool
que_thr_stop(que_thr_t * thr)684 que_thr_stop(
685 /*=========*/
686 	que_thr_t*	thr)	/*!< in: query thread */
687 {
688 	que_t*		graph;
689 	trx_t*		trx = thr_get_trx(thr);
690 
691 	graph = thr->graph;
692 
693 	ut_ad(trx_mutex_own(trx));
694 
695 	if (graph->state == QUE_FORK_COMMAND_WAIT) {
696 
697 		thr->state = QUE_THR_SUSPENDED;
698 
699 	} else if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
700 
701 		trx->lock.wait_thr = thr;
702 		thr->state = QUE_THR_LOCK_WAIT;
703 
704 	} else if (trx->error_state != DB_SUCCESS
705 		   && trx->error_state != DB_LOCK_WAIT) {
706 
707 		/* Error handling built for the MySQL interface */
708 		thr->state = QUE_THR_COMPLETED;
709 
710 	} else if (graph->fork_type == QUE_FORK_ROLLBACK) {
711 
712 		thr->state = QUE_THR_SUSPENDED;
713 	} else {
714 		ut_ad(graph->state == QUE_FORK_ACTIVE);
715 
716 		return(FALSE);
717 	}
718 
719 	return(TRUE);
720 }
721 
722 /**********************************************************************//**
723 Decrements the query thread reference counts in the query graph and the
724 transaction.
725 *** NOTE ***:
726 This and que_thr_stop_for_mysql are the only functions where the reference
727 count can be decremented and this function may only be called from inside
728 que_run_threads! These restrictions exist to make the rollback code easier
729 to maintain. */
730 static
731 void
que_thr_dec_refer_count(que_thr_t * thr,que_thr_t ** next_thr)732 que_thr_dec_refer_count(
733 /*====================*/
734 	que_thr_t*	thr,		/*!< in: query thread */
735 	que_thr_t**	next_thr)	/*!< in/out: next query thread to run;
736 					if the value which is passed in is
737 					a pointer to a NULL pointer, then the
738 					calling function can start running
739 					a new query thread */
740 {
741 	trx_t*		trx;
742 	que_fork_t*	fork;
743 
744 	trx = thr_get_trx(thr);
745 
746 	ut_a(thr->is_active);
747 	ut_ad(trx_mutex_own(trx));
748 
749 	if (thr->state == QUE_THR_RUNNING) {
750 
751 		if (!que_thr_stop(thr)) {
752 
753 			ut_a(next_thr != NULL && *next_thr == NULL);
754 
755 			/* The reason for the thr suspension or wait was
756 			already canceled before we came here: continue
757 			running the thread.
758 
759 			This is also possible because in trx_commit_step() we
760 			assume a single query thread. We set the query thread
761 			state to QUE_THR_RUNNING. */
762 
763 			/* fprintf(stderr,
764 		       		"Wait already ended: trx: %p\n", trx); */
765 
766 			/* Normally srv_suspend_mysql_thread resets
767 			the state to DB_SUCCESS before waiting, but
768 			in this case we have to do it here,
769 			otherwise nobody does it. */
770 
771 			trx->error_state = DB_SUCCESS;
772 
773 			*next_thr = thr;
774 
775 			return;
776 		}
777 	}
778 
779 	fork = static_cast<que_fork_t*>(thr->common.parent);
780 
781 	--trx->lock.n_active_thrs;
782 
783 	--fork->n_active_thrs;
784 
785 	thr->is_active = FALSE;
786 }
787 
788 /**********************************************************************//**
789 A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
790 query thread is stopped and made inactive, except in the case where
791 it was put to the lock wait state in lock0lock.cc, but the lock has already
792 been granted or the transaction chosen as a victim in deadlock resolution. */
793 void
que_thr_stop_for_mysql(que_thr_t * thr)794 que_thr_stop_for_mysql(
795 /*===================*/
796 	que_thr_t*	thr)	/*!< in: query thread */
797 {
798 	trx_t*	trx;
799 
800 	trx = thr_get_trx(thr);
801 
802 	trx_mutex_enter(trx);
803 
804 	if (thr->state == QUE_THR_RUNNING) {
805 
806 		if (trx->error_state != DB_SUCCESS
807 		    && trx->error_state != DB_LOCK_WAIT) {
808 
809 			/* Error handling built for the MySQL interface */
810 			thr->state = QUE_THR_COMPLETED;
811 		} else {
812 			/* It must have been a lock wait but the lock was
813 			already released, or this transaction was chosen
814 			as a victim in selective deadlock resolution */
815 
816 			trx_mutex_exit(trx);
817 
818 			return;
819 		}
820 	}
821 
822 	ut_ad(thr->is_active == TRUE);
823 	ut_ad(trx->lock.n_active_thrs == 1);
824 	ut_ad(thr->graph->n_active_thrs == 1);
825 
826 	thr->is_active = FALSE;
827 	thr->graph->n_active_thrs--;
828 
829 	trx->lock.n_active_thrs--;
830 
831 	trx_mutex_exit(trx);
832 }
833 
834 /**********************************************************************//**
835 Moves a thread from another state to the QUE_THR_RUNNING state. Increments
836 the n_active_thrs counters of the query graph and transaction if thr was
837 not active. */
838 void
que_thr_move_to_run_state_for_mysql(que_thr_t * thr,trx_t * trx)839 que_thr_move_to_run_state_for_mysql(
840 /*================================*/
841 	que_thr_t*	thr,	/*!< in: an query thread */
842 	trx_t*		trx)	/*!< in: transaction */
843 {
844 	ut_a(thr->magic_n == QUE_THR_MAGIC_N);
845 
846 	if (!thr->is_active) {
847 
848 		thr->graph->n_active_thrs++;
849 
850 		trx->lock.n_active_thrs++;
851 
852 		thr->is_active = TRUE;
853 	}
854 
855 	thr->state = QUE_THR_RUNNING;
856 }
857 
858 /**********************************************************************//**
859 A patch for MySQL used to 'stop' a dummy query thread used in MySQL
860 select, when there is no error or lock wait. */
861 void
que_thr_stop_for_mysql_no_error(que_thr_t * thr,trx_t * trx)862 que_thr_stop_for_mysql_no_error(
863 /*============================*/
864 	que_thr_t*	thr,	/*!< in: query thread */
865 	trx_t*		trx)	/*!< in: transaction */
866 {
867 	ut_ad(thr->state == QUE_THR_RUNNING);
868 	ut_ad(thr->is_active == TRUE);
869 	ut_ad(trx->lock.n_active_thrs == 1);
870 	ut_ad(thr->graph->n_active_thrs == 1);
871 	ut_a(thr->magic_n == QUE_THR_MAGIC_N);
872 
873 	thr->state = QUE_THR_COMPLETED;
874 
875 	thr->is_active = FALSE;
876 	thr->graph->n_active_thrs--;
877 
878 	trx->lock.n_active_thrs--;
879 }
880 
881 /****************************************************************//**
882 Get the first containing loop node (e.g. while_node_t or for_node_t) for the
883 given node, or NULL if the node is not within a loop.
884 @return containing loop node, or NULL. */
885 que_node_t*
que_node_get_containing_loop_node(que_node_t * node)886 que_node_get_containing_loop_node(
887 /*==============================*/
888 	que_node_t*	node)	/*!< in: node */
889 {
890 	ut_ad(node);
891 
892 	for (;;) {
893 		ulint	type;
894 
895 		node = que_node_get_parent(node);
896 
897 		if (!node) {
898 			break;
899 		}
900 
901 		type = que_node_get_type(node);
902 
903 		if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
904 			break;
905 		}
906 	}
907 
908 	return(node);
909 }
910 
911 #ifndef NDEBUG
912 /** Gets information of an SQL query graph node.
913 @return type description */
914 static MY_ATTRIBUTE((warn_unused_result, nonnull))
915 const char*
que_node_type_string(const que_node_t * node)916 que_node_type_string(
917 /*=================*/
918 	const que_node_t*	node)	/*!< in: query graph node */
919 {
920 	switch (que_node_get_type(node)) {
921 	case QUE_NODE_SELECT:
922 		return("SELECT");
923 	case QUE_NODE_INSERT:
924 		return("INSERT");
925 	case QUE_NODE_UPDATE:
926 		return("UPDATE");
927 	case QUE_NODE_WHILE:
928 		return("WHILE");
929 	case QUE_NODE_ASSIGNMENT:
930 		return("ASSIGNMENT");
931 	case QUE_NODE_IF:
932 		return("IF");
933 	case QUE_NODE_FETCH:
934 		return("FETCH");
935 	case QUE_NODE_OPEN:
936 		return("OPEN");
937 	case QUE_NODE_PROC:
938 		return("STORED PROCEDURE");
939 	case QUE_NODE_FUNC:
940 		return("FUNCTION");
941 	case QUE_NODE_LOCK:
942 		return("LOCK");
943 	case QUE_NODE_THR:
944 		return("QUERY THREAD");
945 	case QUE_NODE_COMMIT:
946 		return("COMMIT");
947 	case QUE_NODE_UNDO:
948 		return("UNDO ROW");
949 	case QUE_NODE_PURGE:
950 		return("PURGE ROW");
951 	case QUE_NODE_ROLLBACK:
952 		return("ROLLBACK");
953 	case QUE_NODE_CREATE_TABLE:
954 		return("CREATE TABLE");
955 	case QUE_NODE_CREATE_INDEX:
956 		return("CREATE INDEX");
957 	case QUE_NODE_FOR:
958 		return("FOR LOOP");
959 	case QUE_NODE_RETURN:
960 		return("RETURN");
961 	case QUE_NODE_EXIT:
962 		return("EXIT");
963 	default:
964 		ut_ad(0);
965 		return("UNKNOWN NODE TYPE");
966 	}
967 }
968 #endif /* !NDEBUG */
969 
970 /**********************************************************************//**
971 Performs an execution step on a query thread.
972 @return query thread to run next: it may differ from the input
973 parameter if, e.g., a subprocedure call is made */
974 UNIV_INLINE
975 que_thr_t*
que_thr_step(que_thr_t * thr)976 que_thr_step(
977 /*=========*/
978 	que_thr_t*	thr)	/*!< in: query thread */
979 {
980 	que_node_t*	node;
981 	que_thr_t*	old_thr;
982 	trx_t*		trx;
983 	ulint		type;
984 
985 	trx = thr_get_trx(thr);
986 
987 	ut_ad(thr->state == QUE_THR_RUNNING);
988 	ut_a(trx->error_state == DB_SUCCESS);
989 
990 	thr->resource++;
991 
992 	node = thr->run_node;
993 	type = que_node_get_type(node);
994 
995 	old_thr = thr;
996 
997 	DBUG_PRINT("ib_que", ("Execute %u (%s) at %p",
998 			      unsigned(type), que_node_type_string(node),
999 			      (const void*) node));
1000 
1001 	if (type & QUE_NODE_CONTROL_STAT) {
1002 		if ((thr->prev_node != que_node_get_parent(node))
1003 		    && que_node_get_next(thr->prev_node)) {
1004 
1005 			/* The control statements, like WHILE, always pass the
1006 			control to the next child statement if there is any
1007 			child left */
1008 
1009 			thr->run_node = que_node_get_next(thr->prev_node);
1010 
1011 		} else if (type == QUE_NODE_IF) {
1012 			if_step(thr);
1013 		} else if (type == QUE_NODE_FOR) {
1014 			for_step(thr);
1015 		} else if (type == QUE_NODE_PROC) {
1016 
1017 			/* We can access trx->undo_no without reserving
1018 			trx->undo_mutex, because there cannot be active query
1019 			threads doing updating or inserting at the moment! */
1020 
1021 			if (thr->prev_node == que_node_get_parent(node)) {
1022 				trx->last_sql_stat_start.least_undo_no
1023 					= trx->undo_no;
1024 			}
1025 
1026 			proc_step(thr);
1027 		} else if (type == QUE_NODE_WHILE) {
1028 			while_step(thr);
1029 		} else {
1030 			ut_error;
1031 		}
1032 	} else if (type == QUE_NODE_ASSIGNMENT) {
1033 		assign_step(thr);
1034 	} else if (type == QUE_NODE_SELECT) {
1035 		thr = row_sel_step(thr);
1036 	} else if (type == QUE_NODE_INSERT) {
1037 		thr = row_ins_step(thr);
1038 	} else if (type == QUE_NODE_UPDATE) {
1039 		thr = row_upd_step(thr);
1040 	} else if (type == QUE_NODE_FETCH) {
1041 		thr = fetch_step(thr);
1042 	} else if (type == QUE_NODE_OPEN) {
1043 		thr = open_step(thr);
1044 	} else if (type == QUE_NODE_FUNC) {
1045 		proc_eval_step(thr);
1046 
1047 	} else if (type == QUE_NODE_LOCK) {
1048 
1049 		ut_error;
1050 	} else if (type == QUE_NODE_THR) {
1051 		thr = que_thr_node_step(thr);
1052 	} else if (type == QUE_NODE_COMMIT) {
1053 		thr = trx_commit_step(thr);
1054 	} else if (type == QUE_NODE_UNDO) {
1055 		thr = row_undo_step(thr);
1056 	} else if (type == QUE_NODE_PURGE) {
1057 		thr = row_purge_step(thr);
1058 	} else if (type == QUE_NODE_RETURN) {
1059 		thr = return_step(thr);
1060 	} else if (type == QUE_NODE_EXIT) {
1061 		thr = exit_step(thr);
1062 	} else if (type == QUE_NODE_ROLLBACK) {
1063 		thr = trx_rollback_step(thr);
1064 	} else if (type == QUE_NODE_CREATE_TABLE) {
1065 		thr = dict_create_table_step(thr);
1066 	} else if (type == QUE_NODE_CREATE_INDEX) {
1067 		thr = dict_create_index_step(thr);
1068 	} else if (type == QUE_NODE_ROW_PRINTF) {
1069 		thr = row_printf_step(thr);
1070 	} else {
1071 		ut_error;
1072 	}
1073 
1074 	if (type == QUE_NODE_EXIT) {
1075 		old_thr->prev_node = que_node_get_containing_loop_node(node);
1076 	} else {
1077 		old_thr->prev_node = node;
1078 	}
1079 
1080 	if (thr) {
1081 		ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1082 	}
1083 
1084 	return(thr);
1085 }
1086 
1087 /**********************************************************************//**
1088 Run a query thread until it finishes or encounters e.g. a lock wait. */
1089 static
1090 void
que_run_threads_low(que_thr_t * thr)1091 que_run_threads_low(
1092 /*================*/
1093 	que_thr_t*	thr)	/*!< in: query thread */
1094 {
1095 	trx_t*		trx;
1096 	que_thr_t*	next_thr;
1097 
1098 	ut_ad(thr->state == QUE_THR_RUNNING);
1099 	ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1100 	ut_ad(!trx_mutex_own(thr_get_trx(thr)));
1101 
1102 	/* cumul_resource counts how much resources the OS thread (NOT the
1103 	query thread) has spent in this function */
1104 
1105 	trx = thr_get_trx(thr);
1106 
1107 	do {
1108 		/* Check that there is enough space in the log to accommodate
1109 		possible log entries by this query step; if the operation can
1110 		touch more than about 4 pages, checks must be made also within
1111 		the query step! */
1112 
1113 		log_free_check();
1114 
1115 		/* Perform the actual query step: note that the query thread
1116 		may change if, e.g., a subprocedure call is made */
1117 
1118 		/*-------------------------*/
1119 		next_thr = que_thr_step(thr);
1120 		/*-------------------------*/
1121 
1122 		trx_mutex_enter(trx);
1123 
1124 		ut_a(next_thr == NULL || trx->error_state == DB_SUCCESS);
1125 
1126 		if (next_thr != thr) {
1127 			ut_a(next_thr == NULL);
1128 
1129 			/* This can change next_thr to a non-NULL value
1130 			if there was a lock wait that already completed. */
1131 
1132 			que_thr_dec_refer_count(thr, &next_thr);
1133 
1134 			if (next_thr != NULL) {
1135 
1136 				thr = next_thr;
1137 			}
1138 		}
1139 
1140 		ut_ad(trx == thr_get_trx(thr));
1141 
1142 		trx_mutex_exit(trx);
1143 
1144 	} while (next_thr != NULL);
1145 }
1146 
1147 /**********************************************************************//**
1148 Run a query thread. Handles lock waits. */
1149 void
que_run_threads(que_thr_t * thr)1150 que_run_threads(
1151 /*============*/
1152 	que_thr_t*	thr)	/*!< in: query thread */
1153 {
1154 	ut_ad(!trx_mutex_own(thr_get_trx(thr)));
1155 
1156 loop:
1157 	ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1158 
1159 	que_run_threads_low(thr);
1160 
1161 	switch (thr->state) {
1162 
1163 	case QUE_THR_RUNNING:
1164 		/* There probably was a lock wait, but it already ended
1165 		before we came here: continue running thr */
1166 
1167 		goto loop;
1168 
1169 	case QUE_THR_LOCK_WAIT:
1170 		lock_wait_suspend_thread(thr);
1171 
1172 		trx_mutex_enter(thr_get_trx(thr));
1173 
1174 		ut_a(thr_get_trx(thr)->id != 0);
1175 
1176 		if (thr_get_trx(thr)->error_state != DB_SUCCESS) {
1177 			/* thr was chosen as a deadlock victim or there was
1178 			a lock wait timeout */
1179 
1180 			que_thr_dec_refer_count(thr, NULL);
1181 			trx_mutex_exit(thr_get_trx(thr));
1182 			break;
1183 		}
1184 
1185 		trx_mutex_exit(thr_get_trx(thr));
1186 		goto loop;
1187 
1188 	case QUE_THR_COMPLETED:
1189 	case QUE_THR_COMMAND_WAIT:
1190 		/* Do nothing */
1191 		break;
1192 
1193 	default:
1194 		ut_error;
1195 	}
1196 }
1197 
1198 /*********************************************************************//**
1199 Evaluate the given SQL.
1200 @return error code or DB_SUCCESS */
1201 dberr_t
que_eval_sql(pars_info_t * info,const char * sql,ibool reserve_dict_mutex,trx_t * trx)1202 que_eval_sql(
1203 /*=========*/
1204 	pars_info_t*	info,	/*!< in: info struct, or NULL */
1205 	const char*	sql,	/*!< in: SQL string */
1206 	ibool		reserve_dict_mutex,
1207 				/*!< in: if TRUE, acquire/release
1208 				dict_sys->mutex around call to pars_sql. */
1209 	trx_t*		trx)	/*!< in: trx */
1210 {
1211 	que_thr_t*	thr;
1212 	que_t*		graph;
1213 
1214 	DBUG_ENTER("que_eval_sql");
1215 	DBUG_PRINT("que_eval_sql", ("query: %s", sql));
1216 
1217 	ut_a(trx->error_state == DB_SUCCESS);
1218 
1219 	if (reserve_dict_mutex) {
1220 		mutex_enter(&dict_sys->mutex);
1221 	}
1222 
1223 	graph = pars_sql(info, sql);
1224 
1225 	if (reserve_dict_mutex) {
1226 		mutex_exit(&dict_sys->mutex);
1227 	}
1228 
1229 	graph->trx = trx;
1230 	trx->graph = NULL;
1231 
1232 	graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
1233 
1234 	ut_a(thr = que_fork_start_command(graph));
1235 
1236 	que_run_threads(thr);
1237 
1238 	if (reserve_dict_mutex) {
1239 		mutex_enter(&dict_sys->mutex);
1240 	}
1241 
1242 	que_graph_free(graph);
1243 
1244 	if (reserve_dict_mutex) {
1245 		mutex_exit(&dict_sys->mutex);
1246 	}
1247 
1248 	ut_a(trx->error_state != 0);
1249 
1250 	DBUG_RETURN(trx->error_state);
1251 }
1252 
1253 /*********************************************************************//**
1254 Initialise the query sub-system. */
1255 void
que_init(void)1256 que_init(void)
1257 /*==========*/
1258 {
1259 	/* No op */
1260 }
1261 
1262 /*********************************************************************//**
1263 Close the query sub-system. */
1264 void
que_close(void)1265 que_close(void)
1266 /*===========*/
1267 {
1268 	/* No op */
1269 }
1270