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