1/*****************************************************************************
2
3Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24
25*****************************************************************************/
26
27/** @file include/que0que.ic
28 Query graph
29
30 Created 5/27/1996 Heikki Tuuri
31 *******************************************************/
32
33#include "usr0sess.h"
34
35/** Gets the trx of a query thread. */
36UNIV_INLINE
37trx_t *thr_get_trx(que_thr_t *thr) /*!< in: query thread */
38{
39  ut_ad(thr);
40
41  return (thr->graph->trx);
42}
43
44#ifndef UNIV_HOTBACKUP
45/** Determines if this thread is rolling back an incomplete transaction
46 in crash recovery.
47 @return true if thr is rolling back an incomplete transaction in crash
48 recovery */
49UNIV_INLINE
50ibool thr_is_recv(const que_thr_t *thr) /*!< in: query thread */
51{
52  return (trx_is_recv(thr->graph->trx));
53}
54#endif /* !UNIV_HOTBACKUP */
55
56/** Gets the first thr in a fork. */
57UNIV_INLINE
58que_thr_t *que_fork_get_first_thr(que_fork_t *fork) /*!< in: query fork */
59{
60  return (UT_LIST_GET_FIRST(fork->thrs));
61}
62
63/** Gets the child node of the first thr in a fork. */
64UNIV_INLINE
65que_node_t *que_fork_get_child(que_fork_t *fork) /*!< in: query fork */
66{
67  que_thr_t *thr;
68
69  thr = UT_LIST_GET_FIRST(fork->thrs);
70
71  return (thr->child);
72}
73
74/** Gets the type of a graph node. */
75UNIV_INLINE
76ulint que_node_get_type(const que_node_t *node) /*!< in: graph node */
77{
78  return (reinterpret_cast<const que_common_t *>(node)->type);
79}
80
81/** Gets pointer to the value dfield of a graph node. */
82UNIV_INLINE
83dfield_t *que_node_get_val(que_node_t *node) /*!< in: graph node */
84{
85  ut_ad(node);
86
87  return (&(((que_common_t *)node)->val));
88}
89
90/** Gets the value buffer size of a graph node.
91 @return val buffer size, not defined if val.data == NULL in node */
92UNIV_INLINE
93ulint que_node_get_val_buf_size(que_node_t *node) /*!< in: graph node */
94{
95  ut_ad(node);
96
97  return (((que_common_t *)node)->val_buf_size);
98}
99
100/** Sets the value buffer size of a graph node. */
101UNIV_INLINE
102void que_node_set_val_buf_size(que_node_t *node, /*!< in: graph node */
103                               ulint size)       /*!< in: size */
104{
105  ut_ad(node);
106
107  ((que_common_t *)node)->val_buf_size = size;
108}
109
110/** Sets the parent of a graph node. */
111UNIV_INLINE
112void que_node_set_parent(que_node_t *node,   /*!< in: graph node */
113                         que_node_t *parent) /*!< in: parent */
114{
115  ut_ad(node);
116
117  ((que_common_t *)node)->parent = parent;
118}
119
120/** Gets pointer to the value data type field of a graph node. */
121UNIV_INLINE
122dtype_t *que_node_get_data_type(que_node_t *node) /*!< in: graph node */
123{
124  ut_ad(node);
125
126  return (dfield_get_type(&((que_common_t *)node)->val));
127}
128
129/** Catenates a query graph node to a list of them, possible empty list.
130 @return one-way list of nodes */
131UNIV_INLINE
132que_node_t *que_node_list_add_last(
133    que_node_t *node_list, /*!< in: node list, or NULL */
134    que_node_t *node)      /*!< in: node */
135{
136  que_common_t *cnode;
137  que_common_t *cnode2;
138
139  cnode = (que_common_t *)node;
140
141  cnode->brother = nullptr;
142
143  if (node_list == nullptr) {
144    return (node);
145  }
146
147  cnode2 = (que_common_t *)node_list;
148
149  while (cnode2->brother != nullptr) {
150    cnode2 = (que_common_t *)cnode2->brother;
151  }
152
153  cnode2->brother = node;
154
155  return (node_list);
156}
157
158/*************************************************************************
159Removes a query graph node from the list.*/
160UNIV_INLINE
161que_node_t *que_node_list_get_last(
162    /* out: last node in list.*/
163    que_node_t *node_list) /* in: node list */
164{
165  que_common_t *node;
166
167  ut_a(node_list != nullptr);
168
169  node = (que_common_t *)node_list;
170
171  /* We need the last element */
172  while (node->brother != nullptr) {
173    node = (que_common_t *)node->brother;
174  }
175
176  return (node);
177}
178/** Gets the next list node in a list of query graph nodes.
179 @return next node in a list of nodes */
180UNIV_INLINE
181que_node_t *que_node_get_next(que_node_t *node) /*!< in: node in a list */
182{
183  return (((que_common_t *)node)->brother);
184}
185
186/** Gets a query graph node list length.
187 @return length, for NULL list 0 */
188UNIV_INLINE
189ulint que_node_list_get_len(
190    que_node_t *node_list) /*!< in: node list, or NULL */
191{
192  const que_common_t *cnode;
193  ulint len;
194
195  cnode = (const que_common_t *)node_list;
196  len = 0;
197
198  while (cnode != nullptr) {
199    len++;
200    cnode = (const que_common_t *)cnode->brother;
201  }
202
203  return (len);
204}
205
206/** Gets the parent node of a query graph node.
207 @return parent node or NULL */
208UNIV_INLINE
209que_node_t *que_node_get_parent(que_node_t *node) /*!< in: node */
210{
211  return (((que_common_t *)node)->parent);
212}
213
214/** Checks if graph, trx, or session is in a state where the query thread should
215 be stopped.
216 @return true if should be stopped; NOTE that if the peek is made
217 without reserving the trx mutex, then another peek with the mutex
218 reserved is necessary before deciding the actual stopping */
219UNIV_INLINE
220ibool que_thr_peek_stop(que_thr_t *thr) /*!< in: query thread */
221{
222  trx_t *trx;
223  que_t *graph;
224
225  graph = thr->graph;
226  trx = graph->trx;
227
228  if (graph->state != QUE_FORK_ACTIVE ||
229      trx->lock.que_state == TRX_QUE_LOCK_WAIT ||
230      (trx->lock.que_state != TRX_QUE_ROLLING_BACK &&
231       trx->lock.que_state != TRX_QUE_RUNNING)) {
232    return (TRUE);
233  }
234
235  return (FALSE);
236}
237
238/** Returns TRUE if the query graph is for a SELECT statement.
239 @return true if a select */
240UNIV_INLINE
241ibool que_graph_is_select(que_t *graph) /*!< in: graph */
242{
243  if (graph->fork_type == QUE_FORK_SELECT_SCROLL ||
244      graph->fork_type == QUE_FORK_SELECT_NON_SCROLL) {
245    return (TRUE);
246  }
247
248  return (FALSE);
249}
250