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