~ubuntu-branches/ubuntu/quantal/mysql-5.5/quantal-security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*****************************************************************************

Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA

*****************************************************************************/

/**************************************************//**
@file include/btr0cur.ic
The index tree cursor

Created 10/16/1994 Heikki Tuuri
*******************************************************/

#ifndef UNIV_HOTBACKUP
#include "btr0btr.h"

#ifdef UNIV_DEBUG
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\
if (btr_cur_limit_optimistic_insert_debug\
    && (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\
        CODE;\
}
#else
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)
#endif /* UNIV_DEBUG */

#ifdef UNIV_DEBUG
/*********************************************************//**
Returns the page cursor component of a tree cursor.
@return	pointer to page cursor component */
UNIV_INLINE
page_cur_t*
btr_cur_get_page_cur(
/*=================*/
	const btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	return(&((btr_cur_t*) cursor)->page_cur);
}
#endif /* UNIV_DEBUG */
/*********************************************************//**
Returns the buffer block on which the tree cursor is positioned.
@return	pointer to buffer block */
UNIV_INLINE
buf_block_t*
btr_cur_get_block(
/*==============*/
	btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	return(page_cur_get_block(btr_cur_get_page_cur(cursor)));
}

/*********************************************************//**
Returns the record pointer of a tree cursor.
@return	pointer to record */
UNIV_INLINE
rec_t*
btr_cur_get_rec(
/*============*/
	btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	return(page_cur_get_rec(&(cursor->page_cur)));
}

/*********************************************************//**
Returns the compressed page on which the tree cursor is positioned.
@return	pointer to compressed page, or NULL if the page is not compressed */
UNIV_INLINE
page_zip_des_t*
btr_cur_get_page_zip(
/*=================*/
	btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	return(buf_block_get_page_zip(btr_cur_get_block(cursor)));
}

/*********************************************************//**
Invalidates a tree cursor by setting record pointer to NULL. */
UNIV_INLINE
void
btr_cur_invalidate(
/*===============*/
	btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	page_cur_invalidate(&(cursor->page_cur));
}

/*********************************************************//**
Returns the page of a tree cursor.
@return	pointer to page */
UNIV_INLINE
page_t*
btr_cur_get_page(
/*=============*/
	btr_cur_t*	cursor)	/*!< in: tree cursor */
{
	return(page_align(page_cur_get_rec(&(cursor->page_cur))));
}

/*********************************************************//**
Returns the index of a cursor.
@return	index */
UNIV_INLINE
dict_index_t*
btr_cur_get_index(
/*==============*/
	btr_cur_t*	cursor)	/*!< in: B-tree cursor */
{
	return(cursor->index);
}

/*********************************************************//**
Positions a tree cursor at a given record. */
UNIV_INLINE
void
btr_cur_position(
/*=============*/
	dict_index_t*	index,	/*!< in: index */
	rec_t*		rec,	/*!< in: record in tree */
	buf_block_t*	block,	/*!< in: buffer block of rec */
	btr_cur_t*	cursor)	/*!< out: cursor */
{
	ut_ad(page_align(rec) == block->frame);

	page_cur_position(rec, block, btr_cur_get_page_cur(cursor));

	cursor->index = index;
}

/*********************************************************************//**
Checks if compressing an index page where a btr cursor is placed makes
sense.
@return	TRUE if compression is recommended */
UNIV_INLINE
ibool
btr_cur_compress_recommendation(
/*============================*/
	btr_cur_t*	cursor,	/*!< in: btr cursor */
	mtr_t*		mtr)	/*!< in: mtr */
{
	const page_t*	page;

	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
				MTR_MEMO_PAGE_X_FIX));

	page = btr_cur_get_page(cursor);

	LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page) * 2,
				      return(FALSE));

	if ((page_get_data_size(page) < BTR_CUR_PAGE_COMPRESS_LIMIT)
	    || ((btr_page_get_next(page, mtr) == FIL_NULL)
		&& (btr_page_get_prev(page, mtr) == FIL_NULL))) {

		/* The page fillfactor has dropped below a predefined
		minimum value OR the level in the B-tree contains just
		one page: we recommend compression if this is not the
		root page. */

		return(dict_index_get_page(cursor->index)
		       != page_get_page_no(page));
	}

	return(FALSE);
}

/*********************************************************************//**
Checks if the record on which the cursor is placed can be deleted without
making tree compression necessary (or, recommended).
@return	TRUE if can be deleted without recommended compression */
UNIV_INLINE
ibool
btr_cur_can_delete_without_compress(
/*================================*/
	btr_cur_t*	cursor,	/*!< in: btr cursor */
	ulint		rec_size,/*!< in: rec_get_size(btr_cur_get_rec(cursor))*/
	mtr_t*		mtr)	/*!< in: mtr */
{
	page_t*		page;

	ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
				MTR_MEMO_PAGE_X_FIX));

	page = btr_cur_get_page(cursor);

	if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)
	    || ((btr_page_get_next(page, mtr) == FIL_NULL)
		&& (btr_page_get_prev(page, mtr) == FIL_NULL))
	    || (page_get_n_recs(page) < 2)) {

		/* The page fillfactor will drop below a predefined
		minimum value, OR the level in the B-tree contains just
		one page, OR the page will become empty: we recommend
		compression if this is not the root page. */

		return(dict_index_get_page(cursor->index)
		       == page_get_page_no(page));
	}

	return(TRUE);
}

/*******************************************************************//**
Determine if an operation on off-page columns is an update.
@return TRUE if op != BTR_STORE_INSERT */
UNIV_INLINE
ibool
btr_blob_op_is_update(
/*==================*/
	enum blob_op	op)	/*!< in: operation */
{
	switch (op) {
	case BTR_STORE_INSERT:
		return(FALSE);
	case BTR_STORE_INSERT_UPDATE:
	case BTR_STORE_UPDATE:
		return(TRUE);
	}

	ut_ad(0);
	return(FALSE);
}
#endif /* !UNIV_HOTBACKUP */