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., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/**************************************************//**
23
Created 5/27/1996 Heikki Tuuri
24
*******************************************************/
39
#include "row0purge.h"
40
#include "dict0crea.h"
42
#include "eval0proc.h"
43
#include "eval0eval.h"
44
#include "pars0types.h"
46
#define QUE_PARALLELIZE_LIMIT (64 * 256 * 256 * 256)
47
#define QUE_ROUND_ROBIN_LIMIT (64 * 256 * 256 * 256)
48
#define QUE_MAX_LOOPS_WITHOUT_CHECK 16
51
/* If the following flag is set TRUE, the module will print trace info
52
of SQL execution in the UNIV_SQL_DEBUG version */
53
UNIV_INTERN ibool que_trace_on = FALSE;
54
#endif /* UNIV_DEBUG */
56
/* Short introduction to query graphs
57
==================================
59
A query graph consists of nodes linked to each other in various ways. The
60
execution starts at que_run_threads() which takes a que_thr_t parameter.
61
que_thr_t contains two fields that control query graph execution: run_node
62
and prev_node. run_node is the next node to execute and prev_node is the
65
Each node has a pointer to a 'next' statement, i.e., its brother, and a
66
pointer to its parent node. The next pointer is NULL in the last statement
69
Loop nodes contain a link to the first statement of the enclosed statement
70
list. While the loop runs, que_thr_step() checks if execution to the loop
71
node came from its parent or from one of the statement nodes in the loop. If
72
it came from the parent of the loop node it starts executing the first
73
statement node in the loop. If it came from one of the statement nodes in
74
the loop, then it checks if the statement node has another statement node
75
following it, and runs it if so.
77
To signify loop ending, the loop statements (see e.g. while_step()) set
78
que_thr_t->run_node to the loop node's parent node. This is noticed on the
79
next call of que_thr_step() and execution proceeds to the node pointed to by
80
the loop node's 'next' pointer.
82
For example, the code:
90
will result in the following node hierarchy, with the X-axis indicating
91
'next' links and the Y-axis indicating parent/child links:
98
A = assign_node_t, W = while_node_t. */
100
/* How a stored procedure containing COMMIT or ROLLBACK commands
103
The commit or rollback can be seen as a subprocedure call.
104
The problem is that if there are several query threads
105
currently running within the transaction, their action could
106
mess the commit or rollback operation. Or, at the least, the
107
operation would be difficult to visualize and keep in control.
109
Therefore the query thread requesting a commit or a rollback
110
sends to the transaction a signal, which moves the transaction
111
to TRX_QUE_SIGNALED state. All running query threads of the
112
transaction will eventually notice that the transaction is now in
113
this state and voluntarily suspend themselves. Only the last
114
query thread which suspends itself will trigger handling of
117
When the transaction starts to handle a rollback or commit
118
signal, it builds a query graph which, when executed, will
119
roll back or commit the incomplete transaction. The transaction
120
is moved to the TRX_QUE_ROLLING_BACK or TRX_QUE_COMMITTING state.
121
If specified, the SQL cursors opened by the transaction are closed.
122
When the execution of the graph completes, it is like returning
123
from a subprocedure: the query thread which requested the operation
124
starts running again. */
126
/**********************************************************************//**
127
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
128
the n_active_thrs counters of the query graph and transaction.
129
***NOTE***: This is the only function in which such a transition is allowed
133
que_thr_move_to_run_state(
134
/*======================*/
135
que_thr_t* thr); /*!< in: an query thread */
137
/***********************************************************************//**
138
Adds a query graph to the session's list of graphs. */
143
que_t* graph, /*!< in: graph */
144
sess_t* sess) /*!< in: session */
146
ut_ad(mutex_own(&kernel_mutex));
148
UT_LIST_ADD_LAST(graphs, sess->graphs, graph);
151
/***********************************************************************//**
152
Creates a query graph fork node.
153
@return own: fork node */
158
que_t* graph, /*!< in: graph, if NULL then this
159
fork node is assumed to be the
161
que_node_t* parent, /*!< in: parent node */
162
ulint fork_type, /*!< in: fork type */
163
mem_heap_t* heap) /*!< in: memory heap where created */
169
fork = static_cast<que_fork_t *>(mem_heap_alloc(heap, sizeof(que_fork_t)));
171
fork->common.type = QUE_NODE_FORK;
172
fork->n_active_thrs = 0;
174
fork->state = QUE_FORK_COMMAND_WAIT;
182
fork->common.parent = parent;
183
fork->fork_type = fork_type;
187
UT_LIST_INIT(fork->thrs);
189
fork->sym_tab = NULL;
197
/***********************************************************************//**
198
Creates a query graph thread node.
199
@return own: query thread node */
204
que_fork_t* parent, /*!< in: parent node, i.e., a fork node */
205
mem_heap_t* heap) /*!< in: memory heap where created */
209
ut_ad(parent && heap);
211
thr = static_cast<que_thr_t *>(mem_heap_alloc(heap, sizeof(que_thr_t)));
213
thr->common.type = QUE_NODE_THR;
214
thr->common.parent = parent;
216
thr->magic_n = QUE_THR_MAGIC_N;
218
thr->graph = parent->graph;
220
thr->state = QUE_THR_COMMAND_WAIT;
222
thr->is_active = FALSE;
224
thr->run_node = NULL;
226
thr->lock_state = QUE_THR_LOCK_NOLOCK;
228
UT_LIST_ADD_LAST(thrs, parent->thrs, thr);
233
/**********************************************************************//**
234
Moves a suspended query thread to the QUE_THR_RUNNING state and may release
235
a single worker thread to execute it. This function should be used to end
236
the wait state of a query thread waiting for a lock or a stored procedure
242
que_thr_t* thr, /*!< in: query thread in the
244
or QUE_THR_PROCEDURE_WAIT, or
245
QUE_THR_SIG_REPLY_WAIT state */
246
que_thr_t** next_thr) /*!< in/out: next query thread to run;
247
if the value which is passed in is
248
a pointer to a NULL pointer, then the
249
calling function can start running
250
a new query thread; if NULL is passed
251
as the parameter, it is ignored */
255
ut_ad(mutex_own(&kernel_mutex));
257
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
258
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
259
|| (thr->state == QUE_THR_SIG_REPLY_WAIT));
260
ut_ad(thr->run_node);
262
thr->prev_node = thr->run_node;
264
was_active = thr->is_active;
266
que_thr_move_to_run_state(thr);
273
if (next_thr && *next_thr == NULL) {
277
srv_que_task_enqueue_low(thr);
281
/**********************************************************************//**
282
Same as que_thr_end_wait, but no parameter next_thr available. */
285
que_thr_end_wait_no_next_thr(
286
/*=========================*/
287
que_thr_t* thr) /*!< in: query thread in the QUE_THR_LOCK_WAIT,
288
or QUE_THR_PROCEDURE_WAIT, or
289
QUE_THR_SIG_REPLY_WAIT state */
293
ut_a(thr->state == QUE_THR_LOCK_WAIT); /* In MySQL this is the
294
only possible state here */
295
ut_ad(mutex_own(&kernel_mutex));
297
ut_ad((thr->state == QUE_THR_LOCK_WAIT)
298
|| (thr->state == QUE_THR_PROCEDURE_WAIT)
299
|| (thr->state == QUE_THR_SIG_REPLY_WAIT));
301
was_active = thr->is_active;
303
que_thr_move_to_run_state(thr);
310
/* In MySQL we let the OS thread (not just the query thread) to wait
311
for the lock to be released: */
313
srv_release_mysql_thread_if_suspended(thr);
315
/* srv_que_task_enqueue_low(thr); */
318
/**********************************************************************//**
319
Inits a query thread for a command. */
322
que_thr_init_command(
323
/*=================*/
324
que_thr_t* thr) /*!< in: query thread */
327
thr->prev_node = thr->common.parent;
329
que_thr_move_to_run_state(thr);
332
/**********************************************************************//**
333
Starts execution of a command in a query fork. Picks a query thread which
334
is not in the QUE_THR_RUNNING state and moves it to that state. If none
335
can be chosen, a situation which may arise in parallelized fetches, NULL
337
@return a query thread of the graph moved to QUE_THR_RUNNING state, or
338
NULL; the query thread should be executed by que_run_threads by the
342
que_fork_start_command(
343
/*===================*/
344
que_fork_t* fork) /*!< in: a query fork */
347
que_thr_t* suspended_thr = NULL;
348
que_thr_t* completed_thr = NULL;
350
fork->state = QUE_FORK_ACTIVE;
352
fork->last_sel_node = NULL;
354
suspended_thr = NULL;
355
completed_thr = NULL;
357
/* Choose the query thread to run: usually there is just one thread,
358
but in a parallelized select, which necessarily is non-scrollable,
359
there may be several to choose from */
361
/* First we try to find a query thread in the QUE_THR_COMMAND_WAIT
362
state. Then we try to find a query thread in the QUE_THR_SUSPENDED
363
state, finally we try to find a query thread in the QUE_THR_COMPLETED
366
thr = UT_LIST_GET_FIRST(fork->thrs);
368
/* We make a single pass over the thr list within which we note which
369
threads are ready to run. */
371
switch (thr->state) {
372
case QUE_THR_COMMAND_WAIT:
374
/* We have to send the initial message to query thread
377
que_thr_init_command(thr);
381
case QUE_THR_SUSPENDED:
382
/* In this case the execution of the thread was
383
suspended: no initial message is needed because
384
execution can continue from where it was left */
385
if (!suspended_thr) {
391
case QUE_THR_COMPLETED:
392
if (!completed_thr) {
398
case QUE_THR_LOCK_WAIT:
403
thr = UT_LIST_GET_NEXT(thrs, thr);
409
que_thr_move_to_run_state(thr);
411
} else if (completed_thr) {
414
que_thr_init_command(thr);
420
/**********************************************************************//**
421
After signal handling is finished, returns control to a query graph error
422
handling routine. (Currently, just returns the control to the root of the
423
graph so that the graph can communicate an error message to the client.) */
426
que_fork_error_handle(
427
/*==================*/
428
trx_t* /*trx __attribute__((unused))*/, /*!< in: trx */
429
que_t* fork) /*!< in: query graph which was run before signal
430
handling started, NULL not allowed */
434
ut_ad(mutex_own(&kernel_mutex));
435
ut_ad(trx->sess->state == SESS_ERROR);
436
ut_ad(UT_LIST_GET_LEN(trx->reply_signals) == 0);
437
ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
439
thr = UT_LIST_GET_FIRST(fork->thrs);
441
while (thr != NULL) {
442
ut_ad(!thr->is_active);
443
ut_ad(thr->state != QUE_THR_SIG_REPLY_WAIT);
444
ut_ad(thr->state != QUE_THR_LOCK_WAIT);
447
thr->prev_node = thr->child;
448
thr->state = QUE_THR_COMPLETED;
450
thr = UT_LIST_GET_NEXT(thrs, thr);
453
thr = UT_LIST_GET_FIRST(fork->thrs);
455
que_thr_move_to_run_state(thr);
458
srv_que_task_enqueue_low(thr);
461
/****************************************************************//**
462
Tests if all the query threads in the same fork have a given state.
463
@return TRUE if all the query threads in the same fork were in the
467
que_fork_all_thrs_in_state(
468
/*=======================*/
469
que_fork_t* fork, /*!< in: query fork */
470
ulint state) /*!< in: state */
474
thr_node = UT_LIST_GET_FIRST(fork->thrs);
476
while (thr_node != NULL) {
477
if (thr_node->state != state) {
482
thr_node = UT_LIST_GET_NEXT(thrs, thr_node);
488
/**********************************************************************//**
489
Calls que_graph_free_recursive for statements in a statement list. */
492
que_graph_free_stat_list(
493
/*=====================*/
494
que_node_t* node) /*!< in: first query graph node in the list */
497
que_graph_free_recursive(node);
499
node = que_node_get_next(node);
503
/**********************************************************************//**
504
Frees a query graph, but not the heap where it was created. Does not free
505
explicit cursor declarations, they are freed in que_graph_free. */
508
que_graph_free_recursive(
509
/*=====================*/
510
que_node_t* node) /*!< in: query graph node */
527
switch (que_node_get_type(node)) {
530
fork = static_cast<que_fork_t *>(node);
532
thr = UT_LIST_GET_FIRST(fork->thrs);
535
que_graph_free_recursive(thr);
537
thr = UT_LIST_GET_NEXT(thrs, thr);
543
thr = static_cast<que_thr_t *>(node);
545
if (thr->magic_n != QUE_THR_MAGIC_N) {
547
"que_thr struct appears corrupt;"
549
(unsigned long) thr->magic_n);
550
mem_analyze_corruption(thr);
554
thr->magic_n = QUE_THR_MAGIC_FREED;
556
que_graph_free_recursive(thr->child);
561
undo = static_cast<undo_node_t *>(node);
563
mem_heap_free(undo->heap);
566
case QUE_NODE_SELECT:
568
sel = static_cast<sel_node_t *>(node);
570
sel_node_free_private(sel);
573
case QUE_NODE_INSERT:
575
ins = static_cast<ins_node_t *>(node);
577
que_graph_free_recursive(ins->select);
579
mem_heap_free(ins->entry_sys_heap);
583
purge = static_cast<purge_node_t *>(node);
585
mem_heap_free(purge->heap);
589
case QUE_NODE_UPDATE:
591
upd = static_cast<upd_node_t *>(node);
593
if (upd->in_mysql_interface) {
595
btr_pcur_free_for_mysql(upd->pcur);
598
que_graph_free_recursive(upd->cascade_node);
600
if (upd->cascade_heap) {
601
mem_heap_free(upd->cascade_heap);
604
que_graph_free_recursive(upd->select);
606
mem_heap_free(upd->heap);
609
case QUE_NODE_CREATE_TABLE:
610
cre_tab = static_cast<tab_node_t *>(node);
612
que_graph_free_recursive(cre_tab->tab_def);
613
que_graph_free_recursive(cre_tab->col_def);
614
que_graph_free_recursive(cre_tab->commit_node);
616
mem_heap_free(cre_tab->heap);
619
case QUE_NODE_CREATE_INDEX:
620
cre_ind = static_cast<ind_node_t *>(node);
622
que_graph_free_recursive(cre_ind->ind_def);
623
que_graph_free_recursive(cre_ind->field_def);
624
que_graph_free_recursive(cre_ind->commit_node);
626
mem_heap_free(cre_ind->heap);
630
que_graph_free_stat_list(((proc_node_t*)node)->stat_list);
634
que_graph_free_stat_list(((if_node_t*)node)->stat_list);
635
que_graph_free_stat_list(((if_node_t*)node)->else_part);
636
que_graph_free_stat_list(((if_node_t*)node)->elsif_list);
640
que_graph_free_stat_list(((elsif_node_t*)node)->stat_list);
644
que_graph_free_stat_list(((while_node_t*)node)->stat_list);
648
que_graph_free_stat_list(((for_node_t*)node)->stat_list);
652
case QUE_NODE_ASSIGNMENT:
654
case QUE_NODE_RETURN:
655
case QUE_NODE_COMMIT:
656
case QUE_NODE_ROLLBACK:
660
case QUE_NODE_ROW_PRINTF:
663
/* No need to do anything */
668
"que_node struct appears corrupt; type %lu\n",
669
(unsigned long) que_node_get_type(node));
670
mem_analyze_corruption(node);
675
/**********************************************************************//**
676
Frees a query graph. */
681
que_t* graph) /*!< in: query graph; we assume that the memory
682
heap where this graph was created is private
683
to this graph: if not, then use
684
que_graph_free_recursive and free the heap
689
if (graph->sym_tab) {
690
/* The following call frees dynamic memory allocated
691
for variables etc. during execution. Frees also explicit
692
cursor definitions. */
694
sym_tab_free_private(graph->sym_tab);
697
if (graph->info && graph->info->graph_owns_us) {
698
pars_info_free(graph->info);
701
que_graph_free_recursive(graph);
703
mem_heap_free(graph->heap);
706
/****************************************************************//**
707
Performs an execution step on a thr node.
708
@return query thread to run next, or NULL if none */
713
que_thr_t* thr) /*!< in: query thread where run_node must
714
be the thread node itself */
716
ut_ad(thr->run_node == thr);
718
if (thr->prev_node == thr->common.parent) {
719
/* If control to the node came from above, it is just passed
722
thr->run_node = thr->child;
727
mutex_enter(&kernel_mutex);
729
if (que_thr_peek_stop(thr)) {
731
mutex_exit(&kernel_mutex);
736
/* Thread execution completed */
738
thr->state = QUE_THR_COMPLETED;
740
mutex_exit(&kernel_mutex);
745
/**********************************************************************//**
746
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
747
the n_active_thrs counters of the query graph and transaction if thr was
749
***NOTE***: This and ..._mysql are the only functions in which such a
750
transition is allowed to happen! */
753
que_thr_move_to_run_state(
754
/*======================*/
755
que_thr_t* thr) /*!< in: an query thread */
759
ut_ad(thr->state != QUE_THR_RUNNING);
761
trx = thr_get_trx(thr);
763
if (!thr->is_active) {
765
(thr->graph)->n_active_thrs++;
767
trx->n_active_thrs++;
769
thr->is_active = TRUE;
771
ut_ad((thr->graph)->n_active_thrs == 1);
772
ut_ad(trx->n_active_thrs == 1);
775
thr->state = QUE_THR_RUNNING;
778
/**********************************************************************//**
779
Decrements the query thread reference counts in the query graph and the
780
transaction. May start signal handling, e.g., a rollback.
782
This and que_thr_stop_for_mysql are the only functions where the reference
783
count can be decremented and this function may only be called from inside
784
que_run_threads or que_thr_check_if_switch! These restrictions exist to make
785
the rollback code easier to maintain. */
788
que_thr_dec_refer_count(
789
/*====================*/
790
que_thr_t* thr, /*!< in: query thread */
791
que_thr_t** next_thr) /*!< in/out: next query thread to run;
792
if the value which is passed in is
793
a pointer to a NULL pointer, then the
794
calling function can start running
795
a new query thread */
802
fork = static_cast<que_fork_t *>(thr->common.parent);
803
trx = thr_get_trx(thr);
805
mutex_enter(&kernel_mutex);
807
ut_a(thr->is_active);
809
if (thr->state == QUE_THR_RUNNING) {
811
stopped = que_thr_stop(thr);
814
/* The reason for the thr suspension or wait was
815
already canceled before we came here: continue
816
running the thread */
818
/* fputs("!!!!!!!! Wait already ended: continue thr\n",
821
if (next_thr && *next_thr == NULL) {
822
/* Normally srv_suspend_mysql_thread resets
823
the state to DB_SUCCESS before waiting, but
824
in this case we have to do it here,
825
otherwise nobody does it. */
826
trx->error_state = DB_SUCCESS;
831
srv_que_task_enqueue_low(thr);
834
mutex_exit(&kernel_mutex);
840
ut_ad(fork->n_active_thrs == 1);
841
ut_ad(trx->n_active_thrs == 1);
843
fork->n_active_thrs--;
844
trx->n_active_thrs--;
846
thr->is_active = FALSE;
848
if (trx->n_active_thrs > 0) {
850
mutex_exit(&kernel_mutex);
855
fork_type = fork->fork_type;
857
/* Check if all query threads in the same fork are completed */
859
if (que_fork_all_thrs_in_state(fork, QUE_THR_COMPLETED)) {
862
case QUE_FORK_ROLLBACK:
863
/* This is really the undo graph used in rollback,
864
no roll_node in this graph */
866
ut_ad(UT_LIST_GET_LEN(trx->signals) > 0);
867
ut_ad(trx->handling_signals == TRUE);
869
trx_finish_rollback_off_kernel(fork, trx, next_thr);
873
case QUE_FORK_RECOVERY:
874
case QUE_FORK_MYSQL_INTERFACE:
880
ut_error; /*!< not used in MySQL */
884
if (UT_LIST_GET_LEN(trx->signals) > 0 && trx->n_active_thrs == 0) {
886
/* If the trx is signaled and its query thread count drops to
887
zero, then we start processing a signal; from it we may get
888
a new query thread to run */
890
trx_sig_start_handle(trx, next_thr);
893
if (trx->handling_signals && UT_LIST_GET_LEN(trx->signals) == 0) {
895
trx_end_signal_handling(trx);
898
mutex_exit(&kernel_mutex);
901
/**********************************************************************//**
902
Stops a query thread if graph or trx is in a state requiring it. The
903
conditions are tested in the order (1) graph, (2) trx. The kernel mutex has
905
@return TRUE if stopped */
910
que_thr_t* thr) /*!< in: query thread */
916
ut_ad(mutex_own(&kernel_mutex));
921
if (graph->state == QUE_FORK_COMMAND_WAIT) {
922
thr->state = QUE_THR_SUSPENDED;
924
} else if (trx->que_state == TRX_QUE_LOCK_WAIT) {
926
UT_LIST_ADD_FIRST(trx_thrs, trx->wait_thrs, thr);
927
thr->state = QUE_THR_LOCK_WAIT;
929
} else if (trx->error_state != DB_SUCCESS
930
&& trx->error_state != DB_LOCK_WAIT) {
932
/* Error handling built for the MySQL interface */
933
thr->state = QUE_THR_COMPLETED;
935
} else if (UT_LIST_GET_LEN(trx->signals) > 0
936
&& graph->fork_type != QUE_FORK_ROLLBACK) {
938
thr->state = QUE_THR_SUSPENDED;
940
ut_ad(graph->state == QUE_FORK_ACTIVE);
948
/**********************************************************************//**
949
A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The
950
query thread is stopped and made inactive, except in the case where
951
it was put to the lock wait state in lock0lock.c, but the lock has already
952
been granted or the transaction chosen as a victim in deadlock resolution. */
955
que_thr_stop_for_mysql(
956
/*===================*/
957
que_thr_t* thr) /*!< in: query thread */
961
trx = thr_get_trx(thr);
963
mutex_enter(&kernel_mutex);
965
if (thr->state == QUE_THR_RUNNING) {
967
if (trx->error_state != DB_SUCCESS
968
&& trx->error_state != DB_LOCK_WAIT) {
970
/* Error handling built for the MySQL interface */
971
thr->state = QUE_THR_COMPLETED;
973
/* It must have been a lock wait but the lock was
974
already released, or this transaction was chosen
975
as a victim in selective deadlock resolution */
977
mutex_exit(&kernel_mutex);
983
ut_ad(thr->is_active == TRUE);
984
ut_ad(trx->n_active_thrs == 1);
985
ut_ad(thr->graph->n_active_thrs == 1);
987
thr->is_active = FALSE;
988
(thr->graph)->n_active_thrs--;
990
trx->n_active_thrs--;
992
mutex_exit(&kernel_mutex);
995
/**********************************************************************//**
996
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
997
the n_active_thrs counters of the query graph and transaction if thr was
1001
que_thr_move_to_run_state_for_mysql(
1002
/*================================*/
1003
que_thr_t* thr, /*!< in: an query thread */
1004
trx_t* trx) /*!< in: transaction */
1006
if (thr->magic_n != QUE_THR_MAGIC_N) {
1008
"que_thr struct appears corrupt; magic n %lu\n",
1009
(unsigned long) thr->magic_n);
1011
mem_analyze_corruption(thr);
1016
if (!thr->is_active) {
1018
thr->graph->n_active_thrs++;
1020
trx->n_active_thrs++;
1022
thr->is_active = TRUE;
1025
thr->state = QUE_THR_RUNNING;
1028
/**********************************************************************//**
1029
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
1030
select, when there is no error or lock wait. */
1033
que_thr_stop_for_mysql_no_error(
1034
/*============================*/
1035
que_thr_t* thr, /*!< in: query thread */
1036
trx_t* trx) /*!< in: transaction */
1038
ut_ad(thr->state == QUE_THR_RUNNING);
1039
ut_ad(thr->is_active == TRUE);
1040
ut_ad(trx->n_active_thrs == 1);
1041
ut_ad(thr->graph->n_active_thrs == 1);
1043
if (thr->magic_n != QUE_THR_MAGIC_N) {
1045
"que_thr struct appears corrupt; magic n %lu\n",
1046
(unsigned long) thr->magic_n);
1048
mem_analyze_corruption(thr);
1053
thr->state = QUE_THR_COMPLETED;
1055
thr->is_active = FALSE;
1056
(thr->graph)->n_active_thrs--;
1058
trx->n_active_thrs--;
1061
/****************************************************************//**
1062
Get the first containing loop node (e.g. while_node_t or for_node_t) for the
1063
given node, or NULL if the node is not within a loop.
1064
@return containing loop node, or NULL. */
1067
que_node_get_containing_loop_node(
1068
/*==============================*/
1069
que_node_t* node) /*!< in: node */
1076
node = que_node_get_parent(node);
1082
type = que_node_get_type(node);
1084
if ((type == QUE_NODE_FOR) || (type == QUE_NODE_WHILE)) {
1092
/**********************************************************************//**
1093
Prints info of an SQL query graph node. */
1096
que_node_print_info(
1097
/*================*/
1098
que_node_t* node) /*!< in: query graph node */
1103
type = que_node_get_type(node);
1105
if (type == QUE_NODE_SELECT) {
1107
} else if (type == QUE_NODE_INSERT) {
1109
} else if (type == QUE_NODE_UPDATE) {
1111
} else if (type == QUE_NODE_WHILE) {
1113
} else if (type == QUE_NODE_ASSIGNMENT) {
1115
} else if (type == QUE_NODE_IF) {
1117
} else if (type == QUE_NODE_FETCH) {
1119
} else if (type == QUE_NODE_OPEN) {
1121
} else if (type == QUE_NODE_PROC) {
1122
str = "STORED PROCEDURE";
1123
} else if (type == QUE_NODE_FUNC) {
1125
} else if (type == QUE_NODE_LOCK) {
1127
} else if (type == QUE_NODE_THR) {
1128
str = "QUERY THREAD";
1129
} else if (type == QUE_NODE_COMMIT) {
1131
} else if (type == QUE_NODE_UNDO) {
1133
} else if (type == QUE_NODE_PURGE) {
1135
} else if (type == QUE_NODE_ROLLBACK) {
1137
} else if (type == QUE_NODE_CREATE_TABLE) {
1138
str = "CREATE TABLE";
1139
} else if (type == QUE_NODE_CREATE_INDEX) {
1140
str = "CREATE INDEX";
1141
} else if (type == QUE_NODE_FOR) {
1143
} else if (type == QUE_NODE_RETURN) {
1145
} else if (type == QUE_NODE_EXIT) {
1148
str = "UNKNOWN NODE TYPE";
1151
fprintf(stderr, "Node type %lu: %s, address %p\n",
1152
(ulong) type, str, (void*) node);
1155
/**********************************************************************//**
1156
Performs an execution step on a query thread.
1157
@return query thread to run next: it may differ from the input
1158
parameter if, e.g., a subprocedure call is made */
1163
que_thr_t* thr) /*!< in: query thread */
1170
trx = thr_get_trx(thr);
1172
ut_ad(thr->state == QUE_THR_RUNNING);
1173
ut_a(trx->error_state == DB_SUCCESS);
1177
node = thr->run_node;
1178
type = que_node_get_type(node);
1184
fputs("To execute: ", stderr);
1185
que_node_print_info(node);
1188
if (type & QUE_NODE_CONTROL_STAT) {
1189
if ((thr->prev_node != que_node_get_parent(node))
1190
&& que_node_get_next(thr->prev_node)) {
1192
/* The control statements, like WHILE, always pass the
1193
control to the next child statement if there is any
1196
thr->run_node = que_node_get_next(thr->prev_node);
1198
} else if (type == QUE_NODE_IF) {
1200
} else if (type == QUE_NODE_FOR) {
1202
} else if (type == QUE_NODE_PROC) {
1204
/* We can access trx->undo_no without reserving
1205
trx->undo_mutex, because there cannot be active query
1206
threads doing updating or inserting at the moment! */
1208
if (thr->prev_node == que_node_get_parent(node)) {
1209
trx->last_sql_stat_start.least_undo_no
1214
} else if (type == QUE_NODE_WHILE) {
1219
} else if (type == QUE_NODE_ASSIGNMENT) {
1221
} else if (type == QUE_NODE_SELECT) {
1222
thr = row_sel_step(thr);
1223
} else if (type == QUE_NODE_INSERT) {
1224
thr = row_ins_step(thr);
1225
} else if (type == QUE_NODE_UPDATE) {
1226
thr = row_upd_step(thr);
1227
} else if (type == QUE_NODE_FETCH) {
1228
thr = fetch_step(thr);
1229
} else if (type == QUE_NODE_OPEN) {
1230
thr = open_step(thr);
1231
} else if (type == QUE_NODE_FUNC) {
1232
proc_eval_step(thr);
1234
} else if (type == QUE_NODE_LOCK) {
1238
thr = que_lock_step(thr);
1240
} else if (type == QUE_NODE_THR) {
1241
thr = que_thr_node_step(thr);
1242
} else if (type == QUE_NODE_COMMIT) {
1243
thr = trx_commit_step(thr);
1244
} else if (type == QUE_NODE_UNDO) {
1245
thr = row_undo_step(thr);
1246
} else if (type == QUE_NODE_PURGE) {
1247
thr = row_purge_step(thr);
1248
} else if (type == QUE_NODE_RETURN) {
1249
thr = return_step(thr);
1250
} else if (type == QUE_NODE_EXIT) {
1251
thr = exit_step(thr);
1252
} else if (type == QUE_NODE_ROLLBACK) {
1253
thr = trx_rollback_step(thr);
1254
} else if (type == QUE_NODE_CREATE_TABLE) {
1255
thr = dict_create_table_step(thr);
1256
} else if (type == QUE_NODE_CREATE_INDEX) {
1257
thr = dict_create_index_step(thr);
1258
} else if (type == QUE_NODE_ROW_PRINTF) {
1259
thr = row_printf_step(thr);
1264
if (type == QUE_NODE_EXIT) {
1265
old_thr->prev_node = que_node_get_containing_loop_node(node);
1267
old_thr->prev_node = node;
1271
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1277
/**********************************************************************//**
1278
Run a query thread until it finishes or encounters e.g. a lock wait. */
1281
que_run_threads_low(
1282
/*================*/
1283
que_thr_t* thr) /*!< in: query thread */
1285
que_thr_t* next_thr;
1288
ut_ad(thr->state == QUE_THR_RUNNING);
1289
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1290
ut_ad(!mutex_own(&kernel_mutex));
1292
loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK;
1294
/* Check that there is enough space in the log to accommodate
1295
possible log entries by this query step; if the operation can touch
1296
more than about 4 pages, checks must be made also within the query
1301
/* Perform the actual query step: note that the query thread
1302
may change if, e.g., a subprocedure call is made */
1304
/*-------------------------*/
1305
next_thr = que_thr_step(thr);
1306
/*-------------------------*/
1308
ut_a(!next_thr || (thr_get_trx(next_thr)->error_state == DB_SUCCESS));
1312
if (next_thr != thr) {
1313
ut_a(next_thr == NULL);
1315
/* This can change next_thr to a non-NULL value if there was
1316
a lock wait that already completed. */
1317
que_thr_dec_refer_count(thr, &next_thr);
1319
if (next_thr == NULL) {
1324
loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK;
1332
/**********************************************************************//**
1333
Run a query thread. Handles lock waits. */
1338
que_thr_t* thr) /*!< in: query thread */
1341
ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS);
1342
que_run_threads_low(thr);
1344
mutex_enter(&kernel_mutex);
1346
switch (thr->state) {
1348
case QUE_THR_RUNNING:
1349
/* There probably was a lock wait, but it already ended
1350
before we came here: continue running thr */
1352
mutex_exit(&kernel_mutex);
1356
case QUE_THR_LOCK_WAIT:
1357
mutex_exit(&kernel_mutex);
1359
/* The ..._mysql_... function works also for InnoDB's
1360
internal threads. Let us wait that the lock wait ends. */
1362
srv_suspend_mysql_thread(thr);
1364
if (thr_get_trx(thr)->error_state != DB_SUCCESS) {
1365
/* thr was chosen as a deadlock victim or there was
1366
a lock wait timeout */
1368
que_thr_dec_refer_count(thr, NULL);
1375
case QUE_THR_COMPLETED:
1376
case QUE_THR_COMMAND_WAIT:
1384
mutex_exit(&kernel_mutex);
1387
/*********************************************************************//**
1388
Evaluate the given SQL.
1389
@return error code or DB_SUCCESS */
1394
pars_info_t* info, /*!< in: info struct, or NULL */
1395
const char* sql, /*!< in: SQL string */
1396
ibool reserve_dict_mutex,
1397
/*!< in: if TRUE, acquire/release
1398
dict_sys->mutex around call to pars_sql. */
1399
trx_t* trx) /*!< in: trx */
1404
ut_a(trx->error_state == DB_SUCCESS);
1406
if (reserve_dict_mutex) {
1407
mutex_enter(&dict_sys->mutex);
1410
graph = pars_sql(info, sql);
1412
if (reserve_dict_mutex) {
1413
mutex_exit(&dict_sys->mutex);
1421
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
1423
ut_a(thr = que_fork_start_command(graph));
1425
que_run_threads(thr);
1427
que_graph_free(graph);
1429
return(trx->error_state);