1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/que0que.h |
22 | Query graph |
23 | |
24 | Created 5/27/1996 Heikki Tuuri |
25 | *******************************************************/ |
26 | |
27 | #ifndef que0que_h |
28 | #define que0que_h |
29 | |
30 | #include "univ.i" |
31 | #include "data0data.h" |
32 | #include "dict0types.h" |
33 | #include "trx0trx.h" |
34 | #include "trx0roll.h" |
35 | #include "srv0srv.h" |
36 | #include "que0types.h" |
37 | #include "row0types.h" |
38 | #include "pars0types.h" |
39 | |
40 | /** Mutex protecting the query threads. */ |
41 | extern ib_mutex_t que_thr_mutex; |
42 | |
43 | /***********************************************************************//** |
44 | Creates a query graph fork node. |
45 | @return own: fork node */ |
46 | que_fork_t* |
47 | que_fork_create( |
48 | /*============*/ |
49 | que_t* graph, /*!< in: graph, if NULL then this |
50 | fork node is assumed to be the |
51 | graph root */ |
52 | que_node_t* parent, /*!< in: parent node */ |
53 | ulint fork_type, /*!< in: fork type */ |
54 | mem_heap_t* heap); /*!< in: memory heap where created */ |
55 | /***********************************************************************//** |
56 | Gets the first thr in a fork. */ |
57 | UNIV_INLINE |
58 | que_thr_t* |
59 | que_fork_get_first_thr( |
60 | /*===================*/ |
61 | que_fork_t* fork); /*!< in: query fork */ |
62 | /***********************************************************************//** |
63 | Gets the child node of the first thr in a fork. */ |
64 | UNIV_INLINE |
65 | que_node_t* |
66 | que_fork_get_child( |
67 | /*===============*/ |
68 | que_fork_t* fork); /*!< in: query fork */ |
69 | /***********************************************************************//** |
70 | Sets the parent of a graph node. */ |
71 | UNIV_INLINE |
72 | void |
73 | que_node_set_parent( |
74 | /*================*/ |
75 | que_node_t* node, /*!< in: graph node */ |
76 | que_node_t* parent);/*!< in: parent */ |
77 | /** Creates a query graph thread node. |
78 | @param[in] parent parent node, i.e., a fork node |
79 | @param[in] heap memory heap where created |
80 | @param[in] prebuilt row prebuilt structure |
81 | @return own: query thread node */ |
82 | que_thr_t* |
83 | que_thr_create( |
84 | que_fork_t* parent, |
85 | mem_heap_t* heap, |
86 | row_prebuilt_t* prebuilt); |
87 | /**********************************************************************//** |
88 | Frees a query graph, but not the heap where it was created. Does not free |
89 | explicit cursor declarations, they are freed in que_graph_free. */ |
90 | void |
91 | que_graph_free_recursive( |
92 | /*=====================*/ |
93 | que_node_t* node); /*!< in: query graph node */ |
94 | /**********************************************************************//** |
95 | Frees a query graph. */ |
96 | void |
97 | que_graph_free( |
98 | /*===========*/ |
99 | que_t* graph); /*!< in: query graph; we assume that the memory |
100 | heap where this graph was created is private |
101 | to this graph: if not, then use |
102 | que_graph_free_recursive and free the heap |
103 | afterwards! */ |
104 | /**********************************************************************//** |
105 | Stops a query thread if graph or trx is in a state requiring it. The |
106 | conditions are tested in the order (1) graph, (2) trx. The lock_sys_t::mutex |
107 | has to be reserved. |
108 | @return TRUE if stopped */ |
109 | ibool |
110 | que_thr_stop( |
111 | /*=========*/ |
112 | que_thr_t* thr); /*!< in: query thread */ |
113 | /**********************************************************************//** |
114 | Moves a thread from another state to the QUE_THR_RUNNING state. Increments |
115 | the n_active_thrs counters of the query graph and transaction. */ |
116 | void |
117 | que_thr_move_to_run_state_for_mysql( |
118 | /*================================*/ |
119 | que_thr_t* thr, /*!< in: an query thread */ |
120 | trx_t* trx); /*!< in: transaction */ |
121 | /**********************************************************************//** |
122 | A patch for MySQL used to 'stop' a dummy query thread used in MySQL |
123 | select, when there is no error or lock wait. */ |
124 | void |
125 | que_thr_stop_for_mysql_no_error( |
126 | /*============================*/ |
127 | que_thr_t* thr, /*!< in: query thread */ |
128 | trx_t* trx); /*!< in: transaction */ |
129 | /**********************************************************************//** |
130 | A patch for MySQL used to 'stop' a dummy query thread used in MySQL. The |
131 | query thread is stopped and made inactive, except in the case where |
132 | it was put to the lock wait state in lock0lock.cc, but the lock has already |
133 | been granted or the transaction chosen as a victim in deadlock resolution. */ |
134 | void |
135 | que_thr_stop_for_mysql( |
136 | /*===================*/ |
137 | que_thr_t* thr); /*!< in: query thread */ |
138 | /**********************************************************************//** |
139 | Run a query thread. Handles lock waits. */ |
140 | void |
141 | que_run_threads( |
142 | /*============*/ |
143 | que_thr_t* thr); /*!< in: query thread */ |
144 | /**********************************************************************//** |
145 | Moves a suspended query thread to the QUE_THR_RUNNING state and release |
146 | a worker thread to execute it. This function should be used to end |
147 | the wait state of a query thread waiting for a lock or a stored procedure |
148 | completion. |
149 | @return query thread instance of thread to wakeup or NULL */ |
150 | que_thr_t* |
151 | que_thr_end_lock_wait( |
152 | /*==================*/ |
153 | trx_t* trx); /*!< in: transaction in the |
154 | QUE_THR_LOCK_WAIT state */ |
155 | /**********************************************************************//** |
156 | Starts execution of a command in a query fork. Picks a query thread which |
157 | is not in the QUE_THR_RUNNING state and moves it to that state. If none |
158 | can be chosen, a situation which may arise in parallelized fetches, NULL |
159 | is returned. |
160 | @return a query thread of the graph moved to QUE_THR_RUNNING state, or |
161 | NULL; the query thread should be executed by que_run_threads by the |
162 | caller */ |
163 | que_thr_t* |
164 | que_fork_start_command( |
165 | /*===================*/ |
166 | que_fork_t* fork); /*!< in: a query fork */ |
167 | /***********************************************************************//** |
168 | Gets the trx of a query thread. */ |
169 | UNIV_INLINE |
170 | trx_t* |
171 | thr_get_trx( |
172 | /*========*/ |
173 | que_thr_t* thr); /*!< in: query thread */ |
174 | /*******************************************************************//** |
175 | Determines if this thread is rolling back an incomplete transaction |
176 | in crash recovery. |
177 | @return TRUE if thr is rolling back an incomplete transaction in crash |
178 | recovery */ |
179 | UNIV_INLINE |
180 | ibool |
181 | thr_is_recv( |
182 | /*========*/ |
183 | const que_thr_t* thr); /*!< in: query thread */ |
184 | /***********************************************************************//** |
185 | Gets the type of a graph node. */ |
186 | UNIV_INLINE |
187 | ulint |
188 | que_node_get_type( |
189 | /*==============*/ |
190 | const que_node_t* node); /*!< in: graph node */ |
191 | /***********************************************************************//** |
192 | Gets pointer to the value data type field of a graph node. */ |
193 | UNIV_INLINE |
194 | dtype_t* |
195 | que_node_get_data_type( |
196 | /*===================*/ |
197 | que_node_t* node); /*!< in: graph node */ |
198 | /***********************************************************************//** |
199 | Gets pointer to the value dfield of a graph node. */ |
200 | UNIV_INLINE |
201 | dfield_t* |
202 | que_node_get_val( |
203 | /*=============*/ |
204 | que_node_t* node); /*!< in: graph node */ |
205 | /***********************************************************************//** |
206 | Gets the value buffer size of a graph node. |
207 | @return val buffer size, not defined if val.data == NULL in node */ |
208 | UNIV_INLINE |
209 | ulint |
210 | que_node_get_val_buf_size( |
211 | /*======================*/ |
212 | que_node_t* node); /*!< in: graph node */ |
213 | /***********************************************************************//** |
214 | Sets the value buffer size of a graph node. */ |
215 | UNIV_INLINE |
216 | void |
217 | que_node_set_val_buf_size( |
218 | /*======================*/ |
219 | que_node_t* node, /*!< in: graph node */ |
220 | ulint size); /*!< in: size */ |
221 | /*********************************************************************//** |
222 | Gets the next list node in a list of query graph nodes. */ |
223 | UNIV_INLINE |
224 | que_node_t* |
225 | que_node_get_next( |
226 | /*==============*/ |
227 | que_node_t* node); /*!< in: node in a list */ |
228 | /*********************************************************************//** |
229 | Gets the parent node of a query graph node. |
230 | @return parent node or NULL */ |
231 | UNIV_INLINE |
232 | que_node_t* |
233 | que_node_get_parent( |
234 | /*================*/ |
235 | que_node_t* node); /*!< in: node */ |
236 | /****************************************************************//** |
237 | Get the first containing loop node (e.g. while_node_t or for_node_t) for the |
238 | given node, or NULL if the node is not within a loop. |
239 | @return containing loop node, or NULL. */ |
240 | que_node_t* |
241 | que_node_get_containing_loop_node( |
242 | /*==============================*/ |
243 | que_node_t* node); /*!< in: node */ |
244 | /*********************************************************************//** |
245 | Catenates a query graph node to a list of them, possible empty list. |
246 | @return one-way list of nodes */ |
247 | UNIV_INLINE |
248 | que_node_t* |
249 | que_node_list_add_last( |
250 | /*===================*/ |
251 | que_node_t* node_list, /*!< in: node list, or NULL */ |
252 | que_node_t* node); /*!< in: node */ |
253 | /************************************************************************* |
254 | Get the last node from the list.*/ |
255 | UNIV_INLINE |
256 | que_node_t* |
257 | que_node_list_get_last( |
258 | /*===================*/ |
259 | /* out: node last node from list.*/ |
260 | que_node_t* node_list); /* in: node list, or NULL */ |
261 | /*********************************************************************//** |
262 | Gets a query graph node list length. |
263 | @return length, for NULL list 0 */ |
264 | UNIV_INLINE |
265 | ulint |
266 | que_node_list_get_len( |
267 | /*==================*/ |
268 | que_node_t* node_list); /*!< in: node list, or NULL */ |
269 | /**********************************************************************//** |
270 | Checks if graph, trx, or session is in a state where the query thread should |
271 | be stopped. |
272 | @return TRUE if should be stopped; NOTE that if the peek is made |
273 | without reserving the trx_t::mutex, then another peek with the mutex |
274 | reserved is necessary before deciding the actual stopping */ |
275 | UNIV_INLINE |
276 | ibool |
277 | que_thr_peek_stop( |
278 | /*==============*/ |
279 | que_thr_t* thr); /*!< in: query thread */ |
280 | /***********************************************************************//** |
281 | Returns TRUE if the query graph is for a SELECT statement. |
282 | @return TRUE if a select */ |
283 | UNIV_INLINE |
284 | ibool |
285 | que_graph_is_select( |
286 | /*================*/ |
287 | que_t* graph); /*!< in: graph */ |
288 | /**********************************************************************//** |
289 | Prints info of an SQL query graph node. */ |
290 | void |
291 | que_node_print_info( |
292 | /*================*/ |
293 | que_node_t* node); /*!< in: query graph node */ |
294 | /*********************************************************************//** |
295 | Evaluate the given SQL |
296 | @return error code or DB_SUCCESS */ |
297 | dberr_t |
298 | que_eval_sql( |
299 | /*=========*/ |
300 | pars_info_t* info, /*!< in: info struct, or NULL */ |
301 | const char* sql, /*!< in: SQL string */ |
302 | ibool reserve_dict_mutex, |
303 | /*!< in: if TRUE, acquire/release |
304 | dict_sys->mutex around call to pars_sql. */ |
305 | trx_t* trx); /*!< in: trx */ |
306 | |
307 | /**********************************************************************//** |
308 | Round robin scheduler. |
309 | @return a query thread of the graph moved to QUE_THR_RUNNING state, or |
310 | NULL; the query thread should be executed by que_run_threads by the |
311 | caller */ |
312 | que_thr_t* |
313 | que_fork_scheduler_round_robin( |
314 | /*===========================*/ |
315 | que_fork_t* fork, /*!< in: a query fork */ |
316 | que_thr_t* thr); /*!< in: current pos */ |
317 | |
318 | /** Query thread states */ |
319 | enum que_thr_state_t { |
320 | QUE_THR_RUNNING, |
321 | QUE_THR_PROCEDURE_WAIT, |
322 | /** in selects this means that the thread is at the end of its |
323 | result set (or start, in case of a scroll cursor); in other |
324 | statements, this means the thread has done its task */ |
325 | QUE_THR_COMPLETED, |
326 | QUE_THR_COMMAND_WAIT, |
327 | QUE_THR_LOCK_WAIT, |
328 | QUE_THR_SUSPENDED |
329 | }; |
330 | |
331 | /** Query thread lock states */ |
332 | enum que_thr_lock_t { |
333 | QUE_THR_LOCK_NOLOCK, |
334 | QUE_THR_LOCK_ROW, |
335 | QUE_THR_LOCK_TABLE |
336 | }; |
337 | |
338 | /* Query graph query thread node: the fields are protected by the |
339 | trx_t::mutex with the exceptions named below */ |
340 | |
341 | struct que_thr_t{ |
342 | que_common_t common; /*!< type: QUE_NODE_THR */ |
343 | ulint magic_n; /*!< magic number to catch memory |
344 | corruption */ |
345 | que_node_t* child; /*!< graph child node */ |
346 | que_t* graph; /*!< graph where this node belongs */ |
347 | que_thr_state_t state; /*!< state of the query thread */ |
348 | ibool is_active; /*!< TRUE if the thread has been set |
349 | to the run state in |
350 | que_thr_move_to_run_state, but not |
351 | deactivated in |
352 | que_thr_dec_reference_count */ |
353 | /*------------------------------*/ |
354 | /* The following fields are private to the OS thread executing the |
355 | query thread, and are not protected by any mutex: */ |
356 | |
357 | que_node_t* run_node; /*!< pointer to the node where the |
358 | subgraph down from this node is |
359 | currently executed */ |
360 | que_node_t* prev_node; /*!< pointer to the node from which |
361 | the control came */ |
362 | ulint resource; /*!< resource usage of the query thread |
363 | thus far */ |
364 | ulint lock_state; /*!< lock state of thread (table or |
365 | row) */ |
366 | struct srv_slot_t* |
367 | slot; /* The thread slot in the wait |
368 | array in srv_sys_t */ |
369 | /*------------------------------*/ |
370 | /* The following fields are links for the various lists that |
371 | this type can be on. */ |
372 | UT_LIST_NODE_T(que_thr_t) |
373 | thrs; /*!< list of thread nodes of the fork |
374 | node */ |
375 | UT_LIST_NODE_T(que_thr_t) |
376 | queue; /*!< list of runnable thread nodes in |
377 | the server task queue */ |
378 | ulint fk_cascade_depth; /*!< maximum cascading call depth |
379 | supported for foreign key constraint |
380 | related delete/updates */ |
381 | row_prebuilt_t* prebuilt; /*!< prebuilt structure processed by |
382 | the query thread */ |
383 | }; |
384 | |
385 | #define QUE_THR_MAGIC_N 8476583 |
386 | #define QUE_THR_MAGIC_FREED 123461526 |
387 | |
388 | /* Query graph fork node: its fields are protected by the query thread mutex */ |
389 | struct que_fork_t{ |
390 | que_common_t common; /*!< type: QUE_NODE_FORK */ |
391 | que_t* graph; /*!< query graph of this node */ |
392 | ulint fork_type; /*!< fork type */ |
393 | ulint n_active_thrs; /*!< if this is the root of a graph, the |
394 | number query threads that have been |
395 | started in que_thr_move_to_run_state |
396 | but for which que_thr_dec_refer_count |
397 | has not yet been called */ |
398 | trx_t* trx; /*!< transaction: this is set only in |
399 | the root node */ |
400 | ulint state; /*!< state of the fork node */ |
401 | que_thr_t* caller; /*!< pointer to a possible calling query |
402 | thread */ |
403 | UT_LIST_BASE_NODE_T(que_thr_t) |
404 | thrs; /*!< list of query threads */ |
405 | /*------------------------------*/ |
406 | /* The fields in this section are defined only in the root node */ |
407 | sym_tab_t* sym_tab; /*!< symbol table of the query, |
408 | generated by the parser, or NULL |
409 | if the graph was created 'by hand' */ |
410 | pars_info_t* info; /*!< info struct, or NULL */ |
411 | |
412 | sel_node_t* last_sel_node; /*!< last executed select node, or NULL |
413 | if none */ |
414 | UT_LIST_NODE_T(que_fork_t) |
415 | graphs; /*!< list of query graphs of a session |
416 | or a stored procedure */ |
417 | /*------------------------------*/ |
418 | mem_heap_t* heap; /*!< memory heap where the fork was |
419 | created */ |
420 | |
421 | }; |
422 | |
423 | /* Query fork (or graph) types */ |
424 | #define QUE_FORK_SELECT_NON_SCROLL 1 /* forward-only cursor */ |
425 | #define QUE_FORK_SELECT_SCROLL 2 /* scrollable cursor */ |
426 | #define QUE_FORK_INSERT 3 |
427 | #define QUE_FORK_UPDATE 4 |
428 | #define QUE_FORK_ROLLBACK 5 |
429 | /* This is really the undo graph used in rollback, |
430 | no signal-sending roll_node in this graph */ |
431 | #define QUE_FORK_PURGE 6 |
432 | #define QUE_FORK_EXECUTE 7 |
433 | #define QUE_FORK_PROCEDURE 8 |
434 | #define QUE_FORK_PROCEDURE_CALL 9 |
435 | #define QUE_FORK_MYSQL_INTERFACE 10 |
436 | #define QUE_FORK_RECOVERY 11 |
437 | |
438 | /* Query fork (or graph) states */ |
439 | #define QUE_FORK_ACTIVE 1 |
440 | #define QUE_FORK_COMMAND_WAIT 2 |
441 | #define QUE_FORK_INVALID 3 |
442 | #define QUE_FORK_BEING_FREED 4 |
443 | |
444 | /* Flag which is ORed to control structure statement node types */ |
445 | #define QUE_NODE_CONTROL_STAT 1024 |
446 | |
447 | /* Query graph node types */ |
448 | #define QUE_NODE_LOCK 1 |
449 | #define QUE_NODE_INSERT 2 |
450 | #define QUE_NODE_UPDATE 4 |
451 | #define QUE_NODE_CURSOR 5 |
452 | #define QUE_NODE_SELECT 6 |
453 | #define QUE_NODE_AGGREGATE 7 |
454 | #define QUE_NODE_FORK 8 |
455 | #define QUE_NODE_THR 9 |
456 | #define QUE_NODE_UNDO 10 |
457 | #define QUE_NODE_COMMIT 11 |
458 | #define QUE_NODE_ROLLBACK 12 |
459 | #define QUE_NODE_PURGE 13 |
460 | #define QUE_NODE_CREATE_TABLE 14 |
461 | #define QUE_NODE_CREATE_INDEX 15 |
462 | #define QUE_NODE_SYMBOL 16 |
463 | #define QUE_NODE_RES_WORD 17 |
464 | #define QUE_NODE_FUNC 18 |
465 | #define QUE_NODE_ORDER 19 |
466 | #define QUE_NODE_PROC (20 + QUE_NODE_CONTROL_STAT) |
467 | #define QUE_NODE_IF (21 + QUE_NODE_CONTROL_STAT) |
468 | #define QUE_NODE_WHILE (22 + QUE_NODE_CONTROL_STAT) |
469 | #define QUE_NODE_ASSIGNMENT 23 |
470 | #define QUE_NODE_FETCH 24 |
471 | #define QUE_NODE_OPEN 25 |
472 | #define QUE_NODE_COL_ASSIGNMENT 26 |
473 | #define QUE_NODE_FOR (27 + QUE_NODE_CONTROL_STAT) |
474 | #define QUE_NODE_RETURN 28 |
475 | #define QUE_NODE_ROW_PRINTF 29 |
476 | #define QUE_NODE_ELSIF 30 |
477 | #define QUE_NODE_CALL 31 |
478 | #define QUE_NODE_EXIT 32 |
479 | |
480 | #include "que0que.ic" |
481 | |
482 | #endif |
483 | |