1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
23
Created 5/27/1996 Heikki Tuuri
24
*******************************************************/
40
#include "row0purge.h"
41
#include "dict0crea.h"
43
#include "eval0proc.h"
44
#include "eval0eval.h"
45
#include "pars0types.h"
47
#define QUE_PARALLELIZE_LIMIT (64 * 256 * 256 * 256)
48
#define QUE_ROUND_ROBIN_LIMIT (64 * 256 * 256 * 256)
49
#define QUE_MAX_LOOPS_WITHOUT_CHECK 16
52
/* If the following flag is set TRUE, the module will print trace info
53
of SQL execution in the UNIV_SQL_DEBUG version */
54
UNIV_INTERN ibool que_trace_on = FALSE;
55
#endif /* UNIV_DEBUG */
57
/* Short introduction to query graphs
58
==================================
60
A query graph consists of nodes linked to each other in various ways. The
61
execution starts at que_run_threads() which takes a que_thr_t parameter.
62
que_thr_t contains two fields that control query graph execution: run_node
63
and prev_node. run_node is the next node to execute and prev_node is the
66
Each node has a pointer to a 'next' statement, i.e., its brother, and a
67
pointer to its parent node. The next pointer is NULL in the last statement
70
Loop nodes contain a link to the first statement of the enclosed statement
71
list. While the loop runs, que_thr_step() checks if execution to the loop
72
node came from its parent or from one of the statement nodes in the loop. If
73
it came from the parent of the loop node it starts executing the first
74
statement node in the loop. If it came from one of the statement nodes in
75
the loop, then it checks if the statement node has another statement node
76
following it, and runs it if so.
78
To signify loop ending, the loop statements (see e.g. while_step()) set
79
que_thr_t->run_node to the loop node's parent node. This is noticed on the
80
next call of que_thr_step() and execution proceeds to the node pointed to by
81
the loop node's 'next' pointer.
83
For example, the code:
91
will result in the following node hierarchy, with the X-axis indicating
92
'next' links and the Y-axis indicating parent/child links:
99
A = assign_node_t, W = while_node_t. */
101
/* How a stored procedure containing COMMIT or ROLLBACK commands
104
The commit or rollback can be seen as a subprocedure call.
105
The problem is that if there are several query threads
106
currently running within the transaction, their action could
107
mess the commit or rollback operation. Or, at the least, the
108
operation would be difficult to visualize and keep in control.
110
Therefore the query thread requesting a commit or a rollback
111
sends to the transaction a signal, which moves the transaction
112
to TRX_QUE_SIGNALED state. All running query threads of the
113
transaction will eventually notice that the transaction is now in
114
this state and voluntarily suspend themselves. Only the last
115
query thread which suspends itself will trigger handling of
118
When the transaction starts to handle a rollback or commit
119
signal, it builds a query graph which, when executed, will
120
roll back or commit the incomplete transaction. The transaction
121
is moved to the TRX_QUE_ROLLING_BACK or TRX_QUE_COMMITTING state.
122
If specified, the SQL cursors opened by the transaction are closed.
123
When the execution of the graph completes, it is like returning
124
from a subprocedure: the query thread which requested the operation
125
starts running again. */
127
/**********************************************************************//**
128
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
129
the n_active_thrs counters of the query graph and transaction.
130
***NOTE***: This is the only function in which such a transition is allowed
134
que_thr_move_to_run_state(
135
/*======================*/
136
que_thr_t* thr); /*!< in: an query thread */
138
/***********************************************************************//**
139
Adds a query graph to the session's list of graphs. */
144
que_t* graph, /*!< in: graph */
145
sess_t* sess) /*!< in: session */
147
ut_ad(mutex_own(&kernel_mutex));
149
UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
152
/***********************************************************************//**
153
Creates a query graph fork node.
154
@return own: fork node */
159
que_t* graph, /*!< in: graph, if NULL then this
160
fork node is assumed to be the
162
que_node_t* parent, /*!< in: parent node */
163
ulint fork_type, /*!< in: fork type */
164
mem_heap_t* heap) /*!< in: memory heap where created */
170
fork = mem_heap_alloc(heap, sizeof(que_fork_t));
172
fork->common.type = QUE_NODE_FORK;
173
fork->n_active_thrs = 0;
175
fork->state = QUE_FORK_COMMAND_WAIT;
183
fork->common.parent = parent;
184
fork->fork_type = fork_type;
188
UT_LIST_INIT(fork->thrs);
190
fork->sym_tab = NULL;
198
/***********************************************************************//**
199
Creates a query graph thread node.
200
@return own: query thread node */
205
que_fork_t* parent, /*!< in: parent node, i.e., a fork node */
206
mem_heap_t* heap) /*!< in: memory heap where created */
210
ut_ad(parent && heap);
212
thr = mem_heap_alloc(heap, sizeof(que_thr_t));
214
thr->common.type = QUE_NODE_THR;
215
thr->common.parent = parent;
217
thr->magic_n = QUE_THR_MAGIC_N;
219
thr->graph = parent->graph;
221
thr->state = QUE_THR_COMMAND_WAIT;
223
thr->is_active = FALSE;
225
thr->run_node = NULL;
227
thr->lock_state = QUE_THR_LOCK_NOLOCK;
229
UT_LIST_ADD_LAST(thrs, parent->thrs, thr);
234
/**********************************************************************//**
235
Moves a suspended query thread to the QUE_THR_RUNNING state and may release
236
a single worker thread to execute it. This function should be used to end
237
the wait state of a query thread waiting for a lock or a stored procedure
243
que_thr_t* thr, /*!< in: query thread in the
245
or QUE_THR_PROCEDURE_WAIT, or
246
QUE_THR_SIG_REPLY_WAIT state */
247
que_thr_t** next_thr) /*!< in/out: next query thread to run;
248
if the value which is passed in is
249
a pointer to a NULL pointer, then the
250
calling function can start running
251
a new query thread; if NULL is passed
252
as the parameter, it is ignored */
256
ut_ad(mutex_own(&kernel_mutex));
258
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
259
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
260
|| (thr->state == QUE_THR_SIG_REPLY_WAIT));
261
ut_ad(thr->run_node);
263
thr->prev_node = thr->run_node;
265
was_active = thr->is_active;
267
que_thr_move_to_run_state(thr);
274
if (next_thr && *next_thr == NULL) {
278
srv_que_task_enqueue_low(thr);
282
/**********************************************************************//**
283
Same as que_thr_end_wait, but no parameter next_thr available. */
286
que_thr_end_wait_no_next_thr(
287
/*=========================*/
288
que_thr_t* thr) /*!< in: query thread in the QUE_THR_LOCK_WAIT,
289
or QUE_THR_PROCEDURE_WAIT, or
290
QUE_THR_SIG_REPLY_WAIT state */
294
ut_a(thr->state == QUE_THR_LOCK_WAIT); /* In MySQL this is the
295
only possible state here */
296
ut_ad(mutex_own(&kernel_mutex));
298
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
299
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
300
|| (thr->state == QUE_THR_SIG_REPLY_WAIT));
302
was_active = thr->is_active;
304
que_thr_move_to_run_state(thr);
311
/* In MySQL we let the OS thread (not just the query thread) to wait
312
for the lock to be released: */
314
srv_release_mysql_thread_if_suspended(thr);
316
/* srv_que_task_enqueue_low(thr); */
319
/**********************************************************************//**
320
Inits a query thread for a command. */
323
que_thr_init_command(
324
/*=================*/
325
que_thr_t* thr) /*!< in: query thread */
328
thr->prev_node = thr->common.parent;
330
que_thr_move_to_run_state(thr);
333
/**********************************************************************//**
334
Starts execution of a command in a query fork. Picks a query thread which
335
is not in the QUE_THR_RUNNING state and moves it to that state. If none
336
can be chosen, a situation which may arise in parallelized fetches, NULL
338
@return a query thread of the graph moved to QUE_THR_RUNNING state, or
339
NULL; the query thread should be executed by que_run_threads by the
343
que_fork_start_command(
344
/*===================*/
345
que_fork_t* fork) /*!< in: a query fork */
348
que_thr_t* suspended_thr = NULL;
349
que_thr_t* completed_thr = NULL;
351
fork->state = QUE_FORK_ACTIVE;
353
fork->last_sel_node = NULL;
355
suspended_thr = NULL;
356
completed_thr = NULL;
358
/* Choose the query thread to run: usually there is just one thread,
359
but in a parallelized select, which necessarily is non-scrollable,
360
there may be several to choose from */
362
/* First we try to find a query thread in the QUE_THR_COMMAND_WAIT
363
state. Then we try to find a query thread in the QUE_THR_SUSPENDED
364
state, finally we try to find a query thread in the QUE_THR_COMPLETED
367
thr = UT_LIST_GET_FIRST(fork->thrs);
369
/* We make a single pass over the thr list within which we note which
370
threads are ready to run. */
372
switch (thr->state) {
373
case QUE_THR_COMMAND_WAIT:
375
/* We have to send the initial message to query thread
378
que_thr_init_command(thr);
382
case QUE_THR_SUSPENDED:
383
/* In this case the execution of the thread was
384
suspended: no initial message is needed because
385
execution can continue from where it was left */
386
if (!suspended_thr) {
392
case QUE_THR_COMPLETED:
393
if (!completed_thr) {
399
case QUE_THR_LOCK_WAIT:
404
thr = UT_LIST_GET_NEXT(thrs, thr);
410
que_thr_move_to_run_state(thr);
412
} else if (completed_thr) {
415
que_thr_init_command(thr);
421
/**********************************************************************//**
422
After signal handling is finished, returns control to a query graph error
423
handling routine. (Currently, just returns the control to the root of the
424
graph so that the graph can communicate an error message to the client.) */
427
que_fork_error_handle(
428
/*==================*/
429
trx_t* trx __attribute__((unused)), /*!< in: trx */
430
que_t* fork) /*!< in: query graph which was run before signal
431
handling started, NULL not allowed */
435
ut_ad(mutex_own(&kernel_mutex));
436
ut_ad(trx->sess->state == SESS_ERROR);
437
ut_ad(UT_LIST_GET_LEN(trx->reply_signals) == 0);
438
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
440
thr = UT_LIST_GET_FIRST(fork->thrs);
442
while (thr != NULL) {
443
ut_ad(!thr->is_active);
444
ut_ad(thr->state != QUE_THR_SIG_REPLY_WAIT);
445
ut_ad(thr->state != QUE_THR_LOCK_WAIT);
448
thr->prev_node = thr->child;
449
thr->state = QUE_THR_COMPLETED;
451
thr = UT_LIST_GET_NEXT(thrs, thr);
454
thr = UT_LIST_GET_FIRST(fork->thrs);
456
que_thr_move_to_run_state(thr);
459
srv_que_task_enqueue_low(thr);
462
/****************************************************************//**
463
Tests if all the query threads in the same fork have a given state.
464
@return TRUE if all the query threads in the same fork were in the
468
que_fork_all_thrs_in_state(
469
/*=======================*/
470
que_fork_t* fork, /*!< in: query fork */
471
ulint state) /*!< in: state */
475
thr_node = UT_LIST_GET_FIRST(fork->thrs);
477
while (thr_node != NULL) {
478
if (thr_node->state != state) {
483
thr_node = UT_LIST_GET_NEXT(thrs, thr_node);
489
/**********************************************************************//**
490
Calls que_graph_free_recursive for statements in a statement list. */
493
que_graph_free_stat_list(
494
/*=====================*/
495
que_node_t* node) /*!< in: first query graph node in the list */
498
que_graph_free_recursive(node);
500
node = que_node_get_next(node);
504
/**********************************************************************//**
505
Frees a query graph, but not the heap where it was created. Does not free
506
explicit cursor declarations, they are freed in que_graph_free. */
509
que_graph_free_recursive(
510
/*=====================*/
511
que_node_t* node) /*!< in: query graph node */
528
switch (que_node_get_type(node)) {
533
thr = UT_LIST_GET_FIRST(fork->thrs);
536
que_graph_free_recursive(thr);
538
thr = UT_LIST_GET_NEXT(thrs, thr);
546
if (thr->magic_n != QUE_THR_MAGIC_N) {
548
"que_thr struct appears corrupt;"
550
(unsigned long) thr->magic_n);
551
mem_analyze_corruption(thr);
555
thr->magic_n = QUE_THR_MAGIC_FREED;
557
que_graph_free_recursive(thr->child);
564
mem_heap_free(undo->heap);
567
case QUE_NODE_SELECT:
571
sel_node_free_private(sel);
574
case QUE_NODE_INSERT:
578
que_graph_free_recursive(ins->select);
580
mem_heap_free(ins->entry_sys_heap);
586
mem_heap_free(purge->heap);
590
case QUE_NODE_UPDATE:
594
if (upd->in_mysql_interface) {
596
btr_pcur_free_for_mysql(upd->pcur);
599
que_graph_free_recursive(upd->cascade_node);
601
if (upd->cascade_heap) {
602
mem_heap_free(upd->cascade_heap);
605
que_graph_free_recursive(upd->select);
607
mem_heap_free(upd->heap);
610
case QUE_NODE_CREATE_TABLE:
613
que_graph_free_recursive(cre_tab->tab_def);
614
que_graph_free_recursive(cre_tab->col_def);
615
que_graph_free_recursive(cre_tab->commit_node);
617
mem_heap_free(cre_tab->heap);
620
case QUE_NODE_CREATE_INDEX:
623
que_graph_free_recursive(cre_ind->ind_def);
624
que_graph_free_recursive(cre_ind->field_def);
625
que_graph_free_recursive(cre_ind->commit_node);
627
mem_heap_free(cre_ind->heap);
631
que_graph_free_stat_list(((proc_node_t*)node)->stat_list);
635
que_graph_free_stat_list(((if_node_t*)node)->stat_list);
636
que_graph_free_stat_list(((if_node_t*)node)->else_part);
637
que_graph_free_stat_list(((if_node_t*)node)->elsif_list);
641
que_graph_free_stat_list(((elsif_node_t*)node)->stat_list);
645
que_graph_free_stat_list(((while_node_t*)node)->stat_list);
649
que_graph_free_stat_list(((for_node_t*)node)->stat_list);
653
case QUE_NODE_ASSIGNMENT:
655
case QUE_NODE_RETURN:
656
case QUE_NODE_COMMIT:
657
case QUE_NODE_ROLLBACK:
661
case QUE_NODE_ROW_PRINTF:
664
/* No need to do anything */
669
"que_node struct appears corrupt; type %lu\n",
670
(unsigned long) que_node_get_type(node));
671
mem_analyze_corruption(node);
676
/**********************************************************************//**
677
Frees a query graph. */
682
que_t* graph) /*!< in: query graph; we assume that the memory
683
heap where this graph was created is private
684
to this graph: if not, then use
685
que_graph_free_recursive and free the heap
690
if (graph->sym_tab) {
691
/* The following call frees dynamic memory allocated
692
for variables etc. during execution. Frees also explicit
693
cursor definitions. */
695
sym_tab_free_private(graph->sym_tab);
698
if (graph->info && graph->info->graph_owns_us) {
699
pars_info_free(graph->info);
702
que_graph_free_recursive(graph);
704
mem_heap_free(graph->heap);
707
/****************************************************************//**
708
Performs an execution step on a thr node.
709
@return query thread to run next, or NULL if none */
714
que_thr_t* thr) /*!< in: query thread where run_node must
715
be the thread node itself */
717
ut_ad(thr->run_node == thr);
719
if (thr->prev_node == thr->common.parent) {
720
/* If control to the node came from above, it is just passed
723
thr->run_node = thr->child;
728
mutex_enter(&kernel_mutex);
730
if (que_thr_peek_stop(thr)) {
732
mutex_exit(&kernel_mutex);
737
/* Thread execution completed */
739
thr->state = QUE_THR_COMPLETED;
741
mutex_exit(&kernel_mutex);
746
/**********************************************************************//**
747
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
748
the n_active_thrs counters of the query graph and transaction if thr was
750
***NOTE***: This and ..._mysql are the only functions in which such a
751
transition is allowed to happen! */
754
que_thr_move_to_run_state(
755
/*======================*/
756
que_thr_t* thr) /*!< in: an query thread */
760
ut_ad(thr->state != QUE_THR_RUNNING);
762
trx = thr_get_trx(thr);
764
if (!thr->is_active) {
766
(thr->graph)->n_active_thrs++;
768
trx->n_active_thrs++;
770
thr->is_active = TRUE;
772
ut_ad((thr->graph)->n_active_thrs == 1);
773
ut_ad(trx->n_active_thrs == 1);
776
thr->state = QUE_THR_RUNNING;
779
/**********************************************************************//**
780
Decrements the query thread reference counts in the query graph and the
781
transaction. May start signal handling, e.g., a rollback.
783
This and que_thr_stop_for_mysql are the only functions where the reference
784
count can be decremented and this function may only be called from inside
785
que_run_threads or que_thr_check_if_switch! These restrictions exist to make
786
the rollback code easier to maintain. */
789
que_thr_dec_refer_count(
790
/*====================*/
791
que_thr_t* thr, /*!< in: query thread */
792
que_thr_t** next_thr) /*!< in/out: next query thread to run;
793
if the value which is passed in is
794
a pointer to a NULL pointer, then the
795
calling function can start running
796
a new query thread */
803
fork = thr->common.parent;
804
trx = thr_get_trx(thr);
806
mutex_enter(&kernel_mutex);
808
ut_a(thr->is_active);
810
if (thr->state == QUE_THR_RUNNING) {
812
stopped = que_thr_stop(thr);
815
/* The reason for the thr suspension or wait was
816
already canceled before we came here: continue
817
running the thread */
819
/* fputs("!!!!!!!! Wait already ended: continue thr\n",
822
if (next_thr && *next_thr == NULL) {
823
/* Normally srv_suspend_mysql_thread resets
824
the state to DB_SUCCESS before waiting, but
825
in this case we have to do it here,
826
otherwise nobody does it. */
827
trx->error_state = DB_SUCCESS;
832
srv_que_task_enqueue_low(thr);
835
mutex_exit(&kernel_mutex);
841
ut_ad(fork->n_active_thrs == 1);
842
ut_ad(trx->n_active_thrs == 1);
844
fork->n_active_thrs--;
845
trx->n_active_thrs--;
847
thr->is_active = FALSE;
849
if (trx->n_active_thrs > 0) {
851
mutex_exit(&kernel_mutex);
856
fork_type = fork->fork_type;
858
/* Check if all query threads in the same fork are completed */
860
if (que_fork_all_thrs_in_state(fork, QUE_THR_COMPLETED)) {
863
case QUE_FORK_ROLLBACK:
864
/* This is really the undo graph used in rollback,
865
no roll_node in this graph */
867
ut_ad(UT_LIST_GET_LEN(trx->signals) > 0);
868
ut_ad(trx->handling_signals == TRUE);
870
trx_finish_rollback_off_kernel(fork, trx, next_thr);
874
case QUE_FORK_RECOVERY:
875
case QUE_FORK_MYSQL_INTERFACE:
881
ut_error; /*!< not used in MySQL */
885
if (UT_LIST_GET_LEN(trx->signals) > 0 && trx->n_active_thrs == 0) {
887
/* If the trx is signaled and its query thread count drops to
888
zero, then we start processing a signal; from it we may get
889
a new query thread to run */
891
trx_sig_start_handle(trx, next_thr);
894
if (trx->handling_signals && UT_LIST_GET_LEN(trx->signals) == 0) {
896
trx_end_signal_handling(trx);
899
mutex_exit(&kernel_mutex);
902
/**********************************************************************//**
903
Stops a query thread if graph or trx is in a state requiring it. The
904
conditions are tested in the order (1) graph, (2) trx. The kernel mutex has
906
@return TRUE if stopped */
911
que_thr_t* thr) /*!< in: query thread */
917
ut_ad(mutex_own(&kernel_mutex));
922
if (graph->state == QUE_FORK_COMMAND_WAIT) {
923
thr->state = QUE_THR_SUSPENDED;
925
} else if (trx->que_state == TRX_QUE_LOCK_WAIT) {
927
UT_LIST_ADD_FIRST(trx_thrs, trx->wait_thrs, thr);
928
thr->state = QUE_THR_LOCK_WAIT;
930
} else if (trx->error_state != DB_SUCCESS
931
&& trx->error_state != DB_LOCK_WAIT) {
933
/* Error handling built for the MySQL interface */
934
thr->state = QUE_THR_COMPLETED;
936
} else if (UT_LIST_GET_LEN(trx->signals) > 0
937
&& graph->fork_type != QUE_FORK_ROLLBACK) {
939
thr->state = QUE_THR_SUSPENDED;
941
ut_ad(graph->state == QUE_FORK_ACTIVE);
949
/**********************************************************************//**
950
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
951
query thread is stopped and made inactive, except in the case where
952
it was put to the lock wait state in lock0lock.c, but the lock has already
953
been granted or the transaction chosen as a victim in deadlock resolution. */
956
que_thr_stop_for_mysql(
957
/*===================*/
958
que_thr_t* thr) /*!< in: query thread */
962
trx = thr_get_trx(thr);
964
mutex_enter(&kernel_mutex);
966
if (thr->state == QUE_THR_RUNNING) {
968
if (trx->error_state != DB_SUCCESS
969
&& trx->error_state != DB_LOCK_WAIT) {
971
/* Error handling built for the MySQL interface */
972
thr->state = QUE_THR_COMPLETED;
974
/* It must have been a lock wait but the lock was
975
already released, or this transaction was chosen
976
as a victim in selective deadlock resolution */
978
mutex_exit(&kernel_mutex);
984
ut_ad(thr->is_active == TRUE);
985
ut_ad(trx->n_active_thrs == 1);
986
ut_ad(thr->graph->n_active_thrs == 1);
988
thr->is_active = FALSE;
989
(thr->graph)->n_active_thrs--;
991
trx->n_active_thrs--;
993
mutex_exit(&kernel_mutex);
996
/**********************************************************************//**
997
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
998
the n_active_thrs counters of the query graph and transaction if thr was
1002
que_thr_move_to_run_state_for_mysql(
1003
/*================================*/
1004
que_thr_t* thr, /*!< in: an query thread */
1005
trx_t* trx) /*!< in: transaction */
1007
if (thr->magic_n != QUE_THR_MAGIC_N) {
1009
"que_thr struct appears corrupt; magic n %lu\n",
1010
(unsigned long) thr->magic_n);
1012
mem_analyze_corruption(thr);
1017
if (!thr->is_active) {
1019
thr->graph->n_active_thrs++;
1021
trx->n_active_thrs++;
1023
thr->is_active = TRUE;
1026
thr->state = QUE_THR_RUNNING;
1029
/**********************************************************************//**
1030
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
1031
select, when there is no error or lock wait. */
1034
que_thr_stop_for_mysql_no_error(
1035
/*============================*/
1036
que_thr_t* thr, /*!< in: query thread */
1037
trx_t* trx) /*!< in: transaction */
1039
ut_ad(thr->state == QUE_THR_RUNNING);
1040
ut_ad(thr->is_active == TRUE);
1041
ut_ad(trx->n_active_thrs == 1);
1042
ut_ad(thr->graph->n_active_thrs == 1);
1044
if (thr->magic_n != QUE_THR_MAGIC_N) {
1046
"que_thr struct appears corrupt; magic n %lu\n",
1047
(unsigned long) thr->magic_n);
1049
mem_analyze_corruption(thr);
1054
thr->state = QUE_THR_COMPLETED;
1056
thr->is_active = FALSE;
1057
(thr->graph)->n_active_thrs--;
1059
trx->n_active_thrs--;
1062
/****************************************************************//**
1063
Get the first containing loop node (e.g. while_node_t or for_node_t) for the
1064
given node, or NULL if the node is not within a loop.
1065
@return containing loop node, or NULL. */
1068
que_node_get_containing_loop_node(
1069
/*==============================*/
1070
que_node_t* node) /*!< in: node */
1077
node = que_node_get_parent(node);
1083
type = que_node_get_type(node);
1085
if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
1093
/**********************************************************************//**
1094
Prints info of an SQL query graph node. */
1097
que_node_print_info(
1098
/*================*/
1099
que_node_t* node) /*!< in: query graph node */
1104
type = que_node_get_type(node);
1106
if (type == QUE_NODE_SELECT) {
1108
} else if (type == QUE_NODE_INSERT) {
1110
} else if (type == QUE_NODE_UPDATE) {
1112
} else if (type == QUE_NODE_WHILE) {
1114
} else if (type == QUE_NODE_ASSIGNMENT) {
1116
} else if (type == QUE_NODE_IF) {
1118
} else if (type == QUE_NODE_FETCH) {
1120
} else if (type == QUE_NODE_OPEN) {
1122
} else if (type == QUE_NODE_PROC) {
1123
str = "STORED PROCEDURE";
1124
} else if (type == QUE_NODE_FUNC) {
1126
} else if (type == QUE_NODE_LOCK) {
1128
} else if (type == QUE_NODE_THR) {
1129
str = "QUERY THREAD";
1130
} else if (type == QUE_NODE_COMMIT) {
1132
} else if (type == QUE_NODE_UNDO) {
1134
} else if (type == QUE_NODE_PURGE) {
1136
} else if (type == QUE_NODE_ROLLBACK) {
1138
} else if (type == QUE_NODE_CREATE_TABLE) {
1139
str = "CREATE TABLE";
1140
} else if (type == QUE_NODE_CREATE_INDEX) {
1141
str = "CREATE INDEX";
1142
} else if (type == QUE_NODE_FOR) {
1144
} else if (type == QUE_NODE_RETURN) {
1146
} else if (type == QUE_NODE_EXIT) {
1149
str = "UNKNOWN NODE TYPE";
1152
fprintf(stderr, "Node type %lu: %s, address %p\n",
1153
(ulong) type, str, (void*) node);
1156
/**********************************************************************//**
1157
Performs an execution step on a query thread.
1158
@return query thread to run next: it may differ from the input
1159
parameter if, e.g., a subprocedure call is made */
1164
que_thr_t* thr) /*!< in: query thread */
1171
trx = thr_get_trx(thr);
1173
ut_ad(thr->state == QUE_THR_RUNNING);
1174
ut_a(trx->error_state == DB_SUCCESS);
1178
node = thr->run_node;
1179
type = que_node_get_type(node);
1185
fputs("To execute: ", stderr);
1186
que_node_print_info(node);
1189
if (type & QUE_NODE_CONTROL_STAT) {
1190
if ((thr->prev_node != que_node_get_parent(node))
1191
&& que_node_get_next(thr->prev_node)) {
1193
/* The control statements, like WHILE, always pass the
1194
control to the next child statement if there is any
1197
thr->run_node = que_node_get_next(thr->prev_node);
1199
} else if (type == QUE_NODE_IF) {
1201
} else if (type == QUE_NODE_FOR) {
1203
} else if (type == QUE_NODE_PROC) {
1205
/* We can access trx->undo_no without reserving
1206
trx->undo_mutex, because there cannot be active query
1207
threads doing updating or inserting at the moment! */
1209
if (thr->prev_node == que_node_get_parent(node)) {
1210
trx->last_sql_stat_start.least_undo_no
1215
} else if (type == QUE_NODE_WHILE) {
1220
} else if (type == QUE_NODE_ASSIGNMENT) {
1222
} else if (type == QUE_NODE_SELECT) {
1223
thr = row_sel_step(thr);
1224
} else if (type == QUE_NODE_INSERT) {
1225
thr = row_ins_step(thr);
1226
} else if (type == QUE_NODE_UPDATE) {
1227
thr = row_upd_step(thr);
1228
} else if (type == QUE_NODE_FETCH) {
1229
thr = fetch_step(thr);
1230
} else if (type == QUE_NODE_OPEN) {
1231
thr = open_step(thr);
1232
} else if (type == QUE_NODE_FUNC) {
1233
proc_eval_step(thr);
1235
} else if (type == QUE_NODE_LOCK) {
1239
thr = que_lock_step(thr);
1241
} else if (type == QUE_NODE_THR) {
1242
thr = que_thr_node_step(thr);
1243
} else if (type == QUE_NODE_COMMIT) {
1244
thr = trx_commit_step(thr);
1245
} else if (type == QUE_NODE_UNDO) {
1246
thr = row_undo_step(thr);
1247
} else if (type == QUE_NODE_PURGE) {
1248
thr = row_purge_step(thr);
1249
} else if (type == QUE_NODE_RETURN) {
1250
thr = return_step(thr);
1251
} else if (type == QUE_NODE_EXIT) {
1252
thr = exit_step(thr);
1253
} else if (type == QUE_NODE_ROLLBACK) {
1254
thr = trx_rollback_step(thr);
1255
} else if (type == QUE_NODE_CREATE_TABLE) {
1256
thr = dict_create_table_step(thr);
1257
} else if (type == QUE_NODE_CREATE_INDEX) {
1258
thr = dict_create_index_step(thr);
1259
} else if (type == QUE_NODE_ROW_PRINTF) {
1260
thr = row_printf_step(thr);
1265
if (type == QUE_NODE_EXIT) {
1266
old_thr->prev_node = que_node_get_containing_loop_node(node);
1268
old_thr->prev_node = node;
1272
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1278
/**********************************************************************//**
1279
Run a query thread until it finishes or encounters e.g. a lock wait. */
1282
que_run_threads_low(
1283
/*================*/
1284
que_thr_t* thr) /*!< in: query thread */
1286
que_thr_t* next_thr;
1287
ulint cumul_resource;
1290
ut_ad(thr->state == QUE_THR_RUNNING);
1291
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1292
ut_ad(!mutex_own(&kernel_mutex));
1294
/* cumul_resource counts how much resources the OS thread (NOT the
1295
query thread) has spent in this function */
1297
loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK;
1300
/* Check that there is enough space in the log to accommodate
1301
possible log entries by this query step; if the operation can touch
1302
more than about 4 pages, checks must be made also within the query
1307
/* Perform the actual query step: note that the query thread
1308
may change if, e.g., a subprocedure call is made */
1310
/*-------------------------*/
1311
next_thr = que_thr_step(thr);
1312
/*-------------------------*/
1314
ut_a(!next_thr || (thr_get_trx(next_thr)->error_state == DB_SUCCESS));
1318
if (next_thr != thr) {
1319
ut_a(next_thr == NULL);
1321
/* This can change next_thr to a non-NULL value if there was
1322
a lock wait that already completed. */
1323
que_thr_dec_refer_count(thr, &next_thr);
1325
if (next_thr == NULL) {
1330
loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK;
1338
/**********************************************************************//**
1339
Run a query thread. Handles lock waits. */
1344
que_thr_t* thr) /*!< in: query thread */
1347
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1348
que_run_threads_low(thr);
1350
mutex_enter(&kernel_mutex);
1352
switch (thr->state) {
1354
case QUE_THR_RUNNING:
1355
/* There probably was a lock wait, but it already ended
1356
before we came here: continue running thr */
1358
mutex_exit(&kernel_mutex);
1362
case QUE_THR_LOCK_WAIT:
1363
mutex_exit(&kernel_mutex);
1365
/* The ..._mysql_... function works also for InnoDB's
1366
internal threads. Let us wait that the lock wait ends. */
1368
srv_suspend_mysql_thread(thr);
1370
if (thr_get_trx(thr)->error_state != DB_SUCCESS) {
1371
/* thr was chosen as a deadlock victim or there was
1372
a lock wait timeout */
1374
que_thr_dec_refer_count(thr, NULL);
1381
case QUE_THR_COMPLETED:
1382
case QUE_THR_COMMAND_WAIT:
1390
mutex_exit(&kernel_mutex);
1393
/*********************************************************************//**
1394
Evaluate the given SQL.
1395
@return error code or DB_SUCCESS */
1400
pars_info_t* info, /*!< in: info struct, or NULL */
1401
const char* sql, /*!< in: SQL string */
1402
ibool reserve_dict_mutex,
1403
/*!< in: if TRUE, acquire/release
1404
dict_sys->mutex around call to pars_sql. */
1405
trx_t* trx) /*!< in: trx */
1410
ut_a(trx->error_state == DB_SUCCESS);
1412
if (reserve_dict_mutex) {
1413
mutex_enter(&dict_sys->mutex);
1416
graph = pars_sql(info, sql);
1418
if (reserve_dict_mutex) {
1419
mutex_exit(&dict_sys->mutex);
1427
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
1429
ut_a(thr = que_fork_start_command(graph));
1431
que_run_threads(thr);
1433
que_graph_free(graph);
1435
return(trx->error_state);