| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | |
| 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. |
| 8 | |
| 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. |
| 12 | |
| 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., |
| 15 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
| 16 | |
| 17 | *****************************************************************************/ |
| 18 | |
| 19 | /**************************************************//** |
| 20 | @file include/que0que.ic |
| 21 | Query graph |
| 22 | |
| 23 | Created 5/27/1996 Heikki Tuuri |
| 24 | *******************************************************/ |
| 25 | |
| 26 | /***********************************************************************//** |
| 27 | Gets the trx of a query thread. */ |
| 28 | UNIV_INLINE |
| 29 | trx_t* |
| 30 | thr_get_trx( |
| 31 | /*========*/ |
| 32 | que_thr_t* thr) /*!< in: query thread */ |
| 33 | { |
| 34 | ut_ad(thr); |
| 35 | |
| 36 | return(thr->graph->trx); |
| 37 | } |
| 38 | |
| 39 | /*******************************************************************//** |
| 40 | Determines if this thread is rolling back an incomplete transaction |
| 41 | in crash recovery. |
| 42 | @return TRUE if thr is rolling back an incomplete transaction in crash |
| 43 | recovery */ |
| 44 | UNIV_INLINE |
| 45 | ibool |
| 46 | thr_is_recv( |
| 47 | /*========*/ |
| 48 | const que_thr_t* thr) /*!< in: query thread */ |
| 49 | { |
| 50 | return(trx_is_recv(thr->graph->trx)); |
| 51 | } |
| 52 | |
| 53 | /***********************************************************************//** |
| 54 | Gets the first thr in a fork. */ |
| 55 | UNIV_INLINE |
| 56 | que_thr_t* |
| 57 | que_fork_get_first_thr( |
| 58 | /*===================*/ |
| 59 | que_fork_t* fork) /*!< in: query fork */ |
| 60 | { |
| 61 | return(UT_LIST_GET_FIRST(fork->thrs)); |
| 62 | } |
| 63 | |
| 64 | /***********************************************************************//** |
| 65 | Gets the child node of the first thr in a fork. */ |
| 66 | UNIV_INLINE |
| 67 | que_node_t* |
| 68 | que_fork_get_child( |
| 69 | /*===============*/ |
| 70 | que_fork_t* fork) /*!< in: query fork */ |
| 71 | { |
| 72 | que_thr_t* thr; |
| 73 | |
| 74 | thr = UT_LIST_GET_FIRST(fork->thrs); |
| 75 | |
| 76 | return(thr->child); |
| 77 | } |
| 78 | |
| 79 | /***********************************************************************//** |
| 80 | Gets the type of a graph node. */ |
| 81 | UNIV_INLINE |
| 82 | ulint |
| 83 | que_node_get_type( |
| 84 | /*==============*/ |
| 85 | const que_node_t* node) /*!< in: graph node */ |
| 86 | { |
| 87 | return(reinterpret_cast<const que_common_t*>(node)->type); |
| 88 | } |
| 89 | |
| 90 | /***********************************************************************//** |
| 91 | Gets pointer to the value dfield of a graph node. */ |
| 92 | UNIV_INLINE |
| 93 | dfield_t* |
| 94 | que_node_get_val( |
| 95 | /*=============*/ |
| 96 | que_node_t* node) /*!< in: graph node */ |
| 97 | { |
| 98 | ut_ad(node); |
| 99 | |
| 100 | return(&(((que_common_t*) node)->val)); |
| 101 | } |
| 102 | |
| 103 | /***********************************************************************//** |
| 104 | Gets the value buffer size of a graph node. |
| 105 | @return val buffer size, not defined if val.data == NULL in node */ |
| 106 | UNIV_INLINE |
| 107 | ulint |
| 108 | que_node_get_val_buf_size( |
| 109 | /*======================*/ |
| 110 | que_node_t* node) /*!< in: graph node */ |
| 111 | { |
| 112 | ut_ad(node); |
| 113 | |
| 114 | return(((que_common_t*) node)->val_buf_size); |
| 115 | } |
| 116 | |
| 117 | /***********************************************************************//** |
| 118 | Sets the value buffer size of a graph node. */ |
| 119 | UNIV_INLINE |
| 120 | void |
| 121 | que_node_set_val_buf_size( |
| 122 | /*======================*/ |
| 123 | que_node_t* node, /*!< in: graph node */ |
| 124 | ulint size) /*!< in: size */ |
| 125 | { |
| 126 | ut_ad(node); |
| 127 | |
| 128 | ((que_common_t*) node)->val_buf_size = size; |
| 129 | } |
| 130 | |
| 131 | /***********************************************************************//** |
| 132 | Sets the parent of a graph node. */ |
| 133 | UNIV_INLINE |
| 134 | void |
| 135 | que_node_set_parent( |
| 136 | /*================*/ |
| 137 | que_node_t* node, /*!< in: graph node */ |
| 138 | que_node_t* parent) /*!< in: parent */ |
| 139 | { |
| 140 | ut_ad(node); |
| 141 | |
| 142 | ((que_common_t*) node)->parent = parent; |
| 143 | } |
| 144 | |
| 145 | /***********************************************************************//** |
| 146 | Gets pointer to the value data type field of a graph node. */ |
| 147 | UNIV_INLINE |
| 148 | dtype_t* |
| 149 | que_node_get_data_type( |
| 150 | /*===================*/ |
| 151 | que_node_t* node) /*!< in: graph node */ |
| 152 | { |
| 153 | ut_ad(node); |
| 154 | |
| 155 | return(dfield_get_type(&((que_common_t*) node)->val)); |
| 156 | } |
| 157 | |
| 158 | /*********************************************************************//** |
| 159 | Catenates a query graph node to a list of them, possible empty list. |
| 160 | @return one-way list of nodes */ |
| 161 | UNIV_INLINE |
| 162 | que_node_t* |
| 163 | que_node_list_add_last( |
| 164 | /*===================*/ |
| 165 | que_node_t* node_list, /*!< in: node list, or NULL */ |
| 166 | que_node_t* node) /*!< in: node */ |
| 167 | { |
| 168 | que_common_t* cnode; |
| 169 | que_common_t* cnode2; |
| 170 | |
| 171 | cnode = (que_common_t*) node; |
| 172 | |
| 173 | cnode->brother = NULL; |
| 174 | |
| 175 | if (node_list == NULL) { |
| 176 | |
| 177 | return(node); |
| 178 | } |
| 179 | |
| 180 | cnode2 = (que_common_t*) node_list; |
| 181 | |
| 182 | while (cnode2->brother != NULL) { |
| 183 | cnode2 = (que_common_t*) cnode2->brother; |
| 184 | } |
| 185 | |
| 186 | cnode2->brother = node; |
| 187 | |
| 188 | return(node_list); |
| 189 | } |
| 190 | |
| 191 | /************************************************************************* |
| 192 | Removes a query graph node from the list.*/ |
| 193 | UNIV_INLINE |
| 194 | que_node_t* |
| 195 | que_node_list_get_last( |
| 196 | /*===================*/ |
| 197 | /* out: last node in list.*/ |
| 198 | que_node_t* node_list) /* in: node list */ |
| 199 | { |
| 200 | que_common_t* node; |
| 201 | |
| 202 | ut_a(node_list != NULL); |
| 203 | |
| 204 | node = (que_common_t*) node_list; |
| 205 | |
| 206 | /* We need the last element */ |
| 207 | while (node->brother != NULL) { |
| 208 | node = (que_common_t*) node->brother; |
| 209 | } |
| 210 | |
| 211 | return(node); |
| 212 | } |
| 213 | /*********************************************************************//** |
| 214 | Gets the next list node in a list of query graph nodes. |
| 215 | @return next node in a list of nodes */ |
| 216 | UNIV_INLINE |
| 217 | que_node_t* |
| 218 | que_node_get_next( |
| 219 | /*==============*/ |
| 220 | que_node_t* node) /*!< in: node in a list */ |
| 221 | { |
| 222 | return(((que_common_t*) node)->brother); |
| 223 | } |
| 224 | |
| 225 | /*********************************************************************//** |
| 226 | Gets a query graph node list length. |
| 227 | @return length, for NULL list 0 */ |
| 228 | UNIV_INLINE |
| 229 | ulint |
| 230 | que_node_list_get_len( |
| 231 | /*==================*/ |
| 232 | que_node_t* node_list) /*!< in: node list, or NULL */ |
| 233 | { |
| 234 | const que_common_t* cnode; |
| 235 | ulint len; |
| 236 | |
| 237 | cnode = (const que_common_t*) node_list; |
| 238 | len = 0; |
| 239 | |
| 240 | while (cnode != NULL) { |
| 241 | len++; |
| 242 | cnode = (const que_common_t*) cnode->brother; |
| 243 | } |
| 244 | |
| 245 | return(len); |
| 246 | } |
| 247 | |
| 248 | /*********************************************************************//** |
| 249 | Gets the parent node of a query graph node. |
| 250 | @return parent node or NULL */ |
| 251 | UNIV_INLINE |
| 252 | que_node_t* |
| 253 | que_node_get_parent( |
| 254 | /*================*/ |
| 255 | que_node_t* node) /*!< in: node */ |
| 256 | { |
| 257 | return(((que_common_t*) node)->parent); |
| 258 | } |
| 259 | |
| 260 | /**********************************************************************//** |
| 261 | Checks if graph, trx, or session is in a state where the query thread should |
| 262 | be stopped. |
| 263 | @return TRUE if should be stopped; NOTE that if the peek is made |
| 264 | without reserving the trx mutex, then another peek with the mutex |
| 265 | reserved is necessary before deciding the actual stopping */ |
| 266 | UNIV_INLINE |
| 267 | ibool |
| 268 | que_thr_peek_stop( |
| 269 | /*==============*/ |
| 270 | que_thr_t* thr) /*!< in: query thread */ |
| 271 | { |
| 272 | trx_t* trx; |
| 273 | que_t* graph; |
| 274 | |
| 275 | graph = thr->graph; |
| 276 | trx = graph->trx; |
| 277 | |
| 278 | if (graph->state != QUE_FORK_ACTIVE |
| 279 | || trx->lock.que_state == TRX_QUE_LOCK_WAIT |
| 280 | || (trx->lock.que_state != TRX_QUE_ROLLING_BACK |
| 281 | && trx->lock.que_state != TRX_QUE_RUNNING)) { |
| 282 | |
| 283 | return(TRUE); |
| 284 | } |
| 285 | |
| 286 | return(FALSE); |
| 287 | } |
| 288 | |
| 289 | /***********************************************************************//** |
| 290 | Returns TRUE if the query graph is for a SELECT statement. |
| 291 | @return TRUE if a select */ |
| 292 | UNIV_INLINE |
| 293 | ibool |
| 294 | que_graph_is_select( |
| 295 | /*================*/ |
| 296 | que_t* graph) /*!< in: graph */ |
| 297 | { |
| 298 | if (graph->fork_type == QUE_FORK_SELECT_SCROLL |
| 299 | || graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) { |
| 300 | |
| 301 | return(TRUE); |
| 302 | } |
| 303 | |
| 304 | return(FALSE); |
| 305 | } |
| 306 | |
| 307 | |