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