| 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 | |