~mysql/mysql-server/mysql-5.1

551.1.1 by monty at mysql
Added Innobase to source distribution
1
/*******************************************************
2
Select
3
4
(c) 1997 Innobase Oy
5
6
Created 12/19/1997 Heikki Tuuri
7
*******************************************************/
8
9
#include "row0sel.h"
10
11
#ifdef UNIV_NONINL
12
#include "row0sel.ic"
13
#endif
14
15
#include "dict0dict.h"
16
#include "dict0boot.h"
17
#include "trx0undo.h"
18
#include "trx0trx.h"
19
#include "btr0btr.h"
20
#include "btr0cur.h"
21
#include "btr0sea.h"
22
#include "mach0data.h"
23
#include "que0que.h"
24
#include "row0upd.h"
25
#include "row0row.h"
26
#include "row0vers.h"
27
#include "rem0cmp.h"
28
#include "lock0lock.h"
29
#include "eval0eval.h"
30
#include "pars0sym.h"
31
#include "pars0pars.h"
32
#include "row0mysql.h"
1290 by heikki at mysql
Many files:
33
#include "read0read.h"
1616.1281.16 by heikki at mysql
row0sel.c:
34
#include "buf0lru.h"
551.1.1 by monty at mysql
Added Innobase to source distribution
35
36
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
37
#define SEL_MAX_N_PREFETCH	16
38
39
/* Number of rows fetched, after which to start prefetching; MySQL interface
40
has another parameter */
41
#define SEL_PREFETCH_LIMIT	1
42
43
/* When a select has accessed about this many pages, it returns control back
44
to que_run_threads: this is to allow canceling runaway queries */
45
46
#define SEL_COST_LIMIT	100
47
48
/* Flags for search shortcut */
49
#define SEL_FOUND	0
50
#define	SEL_EXHAUSTED	1
51
#define SEL_RETRY	2
52
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
53
/************************************************************************
54
Returns TRUE if the user-defined column values in a secondary index record
1346.425.27 by heikki at mysql
Many files:
55
are alphabetically the same as the corresponding columns in the clustered
56
index record.
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
57
NOTE: the comparison is NOT done as a binary comparison, but character
58
fields are compared with collation! */
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
59
static
60
ibool
61
row_sel_sec_rec_is_for_clust_rec(
62
/*=============================*/
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
63
					/* out: TRUE if the secondary
64
					record is equal to the corresponding
65
					fields in the clustered record,
66
					when compared with collation */
67
	rec_t*		sec_rec,	/* in: secondary index record */
68
	dict_index_t*	sec_index,	/* in: secondary index */
69
	rec_t*		clust_rec,	/* in: clustered index record */
1346.236.10 by heikki at mysql
Many files:
70
	dict_index_t*	clust_index)	/* in: clustered index */
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
71
{
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
72
	byte*		sec_field;
73
	ulint		sec_len;
74
	byte*		clust_field;
75
	ulint		clust_len;
76
	ulint		n;
77
	ulint		i;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
78
	mem_heap_t*	heap		= NULL;
1773.10.2 by marko at mysql
InnoDB: Introduce the symbols REC_OFFS_NORMAL_SIZE and
79
	ulint		clust_offsets_[REC_OFFS_NORMAL_SIZE];
80
	ulint		sec_offsets_[REC_OFFS_SMALL_SIZE];
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
81
	ulint*		clust_offs	= clust_offsets_;
82
	ulint*		sec_offs	= sec_offsets_;
83
	ibool		is_equal	= TRUE;
1346.236.10 by heikki at mysql
Many files:
84
1773.10.1 by marko at mysql
InnoDB: Improve performance by about 10% by removing implicit
85
	*clust_offsets_ = (sizeof clust_offsets_) / sizeof *clust_offsets_;
86
	*sec_offsets_ = (sizeof sec_offsets_) / sizeof *sec_offsets_;
87
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
88
	clust_offs = rec_get_offsets(clust_rec, clust_index, clust_offs,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
89
				     ULINT_UNDEFINED, &heap);
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
90
	sec_offs = rec_get_offsets(sec_rec, sec_index, sec_offs,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
91
				   ULINT_UNDEFINED, &heap);
1346.236.10 by heikki at mysql
Many files:
92
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
93
	n = dict_index_get_n_ordering_defined_by_user(sec_index);
1346.236.10 by heikki at mysql
Many files:
94
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
95
	for (i = 0; i < n; i++) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
96
		const dict_field_t*	ifield;
97
		const dict_col_t*	col;
98
1346.236.10 by heikki at mysql
Many files:
99
		ifield = dict_index_get_nth_field(sec_index, i);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
100
		col = dict_field_get_col(ifield);
101
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
102
		clust_field = rec_get_nth_field(
103
			clust_rec, clust_offs,
104
			dict_col_get_clust_pos(col, clust_index), &clust_len);
1659.1.48 by marko at mysql
Many files:
105
		sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
1346.236.10 by heikki at mysql
Many files:
106
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
107
		if (ifield->prefix_len > 0 && clust_len != UNIV_SQL_NULL) {
108
109
			clust_len = dtype_get_at_most_n_mbchars(
110
				col->prtype, col->mbminlen, col->mbmaxlen,
111
				ifield->prefix_len,
112
				clust_len, (char*) clust_field);
1346.236.10 by heikki at mysql
Many files:
113
		}
114
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
115
		if (0 != cmp_data_data(col->mtype, col->prtype,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
116
				       clust_field, clust_len,
117
				       sec_field, sec_len)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
118
			is_equal = FALSE;
119
			goto func_exit;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
120
		}
121
	}
1346.236.10 by heikki at mysql
Many files:
122
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
123
func_exit:
1773.330.3 by marko at mysql
InnoDB: Define some macros around GCC's __builtin_expect()
124
	if (UNIV_LIKELY_NULL(heap)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
125
		mem_heap_free(heap);
126
	}
127
	return(is_equal);
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
128
}
129
551.1.1 by monty at mysql
Added Innobase to source distribution
130
/*************************************************************************
131
Creates a select node struct. */
132
133
sel_node_t*
134
sel_node_create(
135
/*============*/
136
				/* out, own: select node struct */
137
	mem_heap_t*	heap)	/* in: memory heap where created */
138
{
139
	sel_node_t*	node;
140
141
	node = mem_heap_alloc(heap, sizeof(sel_node_t));
142
	node->common.type = QUE_NODE_SELECT;
143
	node->state = SEL_NODE_OPEN;
144
145
	node->select_will_do_update = FALSE;
146
	node->latch_mode = BTR_SEARCH_LEAF;
147
148
	node->plans = NULL;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
149
551.1.1 by monty at mysql
Added Innobase to source distribution
150
	return(node);
151
}
152
153
/*************************************************************************
154
Frees the memory private to a select node when a query graph is freed,
155
does not free the heap where the node was originally created. */
156
157
void
158
sel_node_free_private(
159
/*==================*/
160
	sel_node_t*	node)	/* in: select node struct */
161
{
162
	ulint	i;
163
	plan_t*	plan;
164
165
	if (node->plans != NULL) {
166
		for (i = 0; i < node->n_tables; i++) {
167
			plan = sel_node_get_nth_plan(node, i);
168
169
			btr_pcur_close(&(plan->pcur));
170
			btr_pcur_close(&(plan->clust_pcur));
171
172
			if (plan->old_vers_heap) {
173
				mem_heap_free(plan->old_vers_heap);
174
			}
175
		}
176
	}
177
}
178
179
/*************************************************************************
180
Evaluates the values in a select list. If there are aggregate functions,
181
their argument value is added to the aggregate total. */
182
UNIV_INLINE
183
void
184
sel_eval_select_list(
185
/*=================*/
186
	sel_node_t*	node)	/* in: select node */
187
{
188
	que_node_t*	exp;
189
190
	exp = node->select_list;
191
192
	while (exp) {
193
		eval_exp(exp);
194
195
		exp = que_node_get_next(exp);
196
	}
197
}
198
199
/*************************************************************************
200
Assigns the values in the select list to the possible into-variables in
201
SELECT ... INTO ... */
202
UNIV_INLINE
203
void
204
sel_assign_into_var_values(
205
/*=======================*/
206
	sym_node_t*	var,	/* in: first variable in a list of variables */
207
	sel_node_t*	node)	/* in: select node */
208
{
209
	que_node_t*	exp;
210
211
	if (var == NULL) {
212
213
		return;
214
	}
215
216
	exp = node->select_list;
217
218
	while (var) {
219
		ut_ad(exp);
220
221
		eval_node_copy_val(var->alias, exp);
222
223
		exp = que_node_get_next(exp);
224
		var = que_node_get_next(var);
225
	}
226
}
227
228
/*************************************************************************
229
Resets the aggregate value totals in the select list of an aggregate type
230
query. */
231
UNIV_INLINE
232
void
233
sel_reset_aggregate_vals(
234
/*=====================*/
235
	sel_node_t*	node)	/* in: select node */
236
{
237
	func_node_t*	func_node;
238
239
	ut_ad(node->is_aggregate);
240
241
	func_node = node->select_list;
242
243
	while (func_node) {
244
		eval_node_set_int_val(func_node, 0);
245
246
		func_node = que_node_get_next(func_node);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
247
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
248
249
	node->aggregate_already_fetched = FALSE;
250
}
251
252
/*************************************************************************
253
Copies the input variable values when an explicit cursor is opened. */
254
UNIV_INLINE
255
void
256
row_sel_copy_input_variable_vals(
257
/*=============================*/
258
	sel_node_t*	node)	/* in: select node */
259
{
260
	sym_node_t*	var;
261
262
	var = UT_LIST_GET_FIRST(node->copy_variables);
263
264
	while (var) {
265
		eval_node_copy_val(var, var->alias);
266
267
		var->indirection = NULL;
268
269
		var = UT_LIST_GET_NEXT(col_var_list, var);
270
	}
271
}
272
273
/*************************************************************************
274
Fetches the column values from a record. */
275
static
276
void
277
row_sel_fetch_columns(
278
/*==================*/
279
	dict_index_t*	index,	/* in: record index */
280
	rec_t*		rec,	/* in: record in a clustered or non-clustered
281
				index */
1659.1.48 by marko at mysql
Many files:
282
	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */
551.1.1 by monty at mysql
Added Innobase to source distribution
283
	sym_node_t*	column)	/* in: first column in a column list, or
284
				NULL */
285
{
286
	dfield_t*	val;
287
	ulint		index_type;
288
	ulint		field_no;
289
	byte*		data;
290
	ulint		len;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
291
1659.1.48 by marko at mysql
Many files:
292
	ut_ad(rec_offs_validate(rec, index, offsets));
293
551.1.1 by monty at mysql
Added Innobase to source distribution
294
	if (index->type & DICT_CLUSTERED) {
295
		index_type = SYM_CLUST_FIELD_NO;
296
	} else {
297
		index_type = SYM_SEC_FIELD_NO;
298
	}
299
300
	while (column) {
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
301
		mem_heap_t*	heap = NULL;
302
		ibool		needs_copy;
303
551.1.1 by monty at mysql
Added Innobase to source distribution
304
		field_no = column->field_nos[index_type];
305
306
		if (field_no != ULINT_UNDEFINED) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
307
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
308
			if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
309
							      field_no))) {
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
310
311
				/* Copy an externally stored field to the
312
				temporary heap */
313
314
				heap = mem_heap_create(1);
315
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
316
				data = btr_rec_copy_externally_stored_field(
317
					rec, offsets, field_no, &len, heap);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
318
319
				ut_a(len != UNIV_SQL_NULL);
320
321
				needs_copy = TRUE;
322
			} else {
323
				data = rec_get_nth_field(rec, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
324
							 field_no, &len);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
325
326
				needs_copy = column->copy_val;
327
			}
328
329
			if (needs_copy) {
551.1.1 by monty at mysql
Added Innobase to source distribution
330
				eval_node_copy_and_alloc_val(column, data,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
331
							     len);
551.1.1 by monty at mysql
Added Innobase to source distribution
332
			} else {
333
				val = que_node_get_val(column);
334
				dfield_set_data(val, data, len);
335
			}
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
336
337
			if (UNIV_LIKELY_NULL(heap)) {
338
				mem_heap_free(heap);
339
			}
551.1.1 by monty at mysql
Added Innobase to source distribution
340
		}
341
342
		column = UT_LIST_GET_NEXT(col_var_list, column);
343
	}
344
}
345
346
/*************************************************************************
347
Allocates a prefetch buffer for a column when prefetch is first time done. */
348
static
349
void
350
sel_col_prefetch_buf_alloc(
351
/*=======================*/
352
	sym_node_t*	column)	/* in: symbol table node for a column */
353
{
354
	sel_buf_t*	sel_buf;
355
	ulint		i;
356
357
	ut_ad(que_node_get_type(column) == QUE_NODE_SYMBOL);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
358
551.1.1 by monty at mysql
Added Innobase to source distribution
359
	column->prefetch_buf = mem_alloc(SEL_MAX_N_PREFETCH
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
360
					 * sizeof(sel_buf_t));
551.1.1 by monty at mysql
Added Innobase to source distribution
361
	for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
362
		sel_buf = column->prefetch_buf + i;
363
364
		sel_buf->data = NULL;
365
366
		sel_buf->val_buf_size = 0;
367
	}
368
}
369
370
/*************************************************************************
371
Frees a prefetch buffer for a column, including the dynamically allocated
372
memory for data stored there. */
373
374
void
375
sel_col_prefetch_buf_free(
376
/*======================*/
377
	sel_buf_t*	prefetch_buf)	/* in, own: prefetch buffer */
378
{
379
	sel_buf_t*	sel_buf;
380
	ulint		i;
381
382
	for (i = 0; i < SEL_MAX_N_PREFETCH; i++) {
383
		sel_buf = prefetch_buf + i;
384
385
		if (sel_buf->val_buf_size > 0) {
386
387
			mem_free(sel_buf->data);
388
		}
389
	}
390
}
391
392
/*************************************************************************
393
Pops the column values for a prefetched, cached row from the column prefetch
394
buffers and places them to the val fields in the column nodes. */
395
static
396
void
397
sel_pop_prefetched_row(
398
/*===================*/
399
	plan_t*	plan)	/* in: plan node for a table */
400
{
401
	sym_node_t*	column;
402
	sel_buf_t*	sel_buf;
403
	dfield_t*	val;
404
	byte*		data;
405
	ulint		len;
406
	ulint		val_buf_size;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
407
551.1.1 by monty at mysql
Added Innobase to source distribution
408
	ut_ad(plan->n_rows_prefetched > 0);
409
410
	column = UT_LIST_GET_FIRST(plan->columns);
411
412
	while (column) {
413
		val = que_node_get_val(column);
414
415
		if (!column->copy_val) {
416
			/* We did not really push any value for the
417
			column */
418
419
			ut_ad(!column->prefetch_buf);
420
			ut_ad(que_node_get_val_buf_size(column) == 0);
421
#ifdef UNIV_DEBUG
422
			dfield_set_data(val, NULL, 0);
423
#endif
424
			goto next_col;
425
		}
426
427
		ut_ad(column->prefetch_buf);
428
429
		sel_buf = column->prefetch_buf + plan->first_prefetched;
430
431
		data = sel_buf->data;
432
		len = sel_buf->len;
433
		val_buf_size = sel_buf->val_buf_size;
434
435
		/* We must keep track of the allocated memory for
436
		column values to be able to free it later: therefore
437
		we swap the values for sel_buf and val */
438
439
		sel_buf->data = dfield_get_data(val);
440
		sel_buf->len = dfield_get_len(val);
441
		sel_buf->val_buf_size = que_node_get_val_buf_size(column);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
442
551.1.1 by monty at mysql
Added Innobase to source distribution
443
		dfield_set_data(val, data, len);
444
		que_node_set_val_buf_size(column, val_buf_size);
445
next_col:
446
		column = UT_LIST_GET_NEXT(col_var_list, column);
447
	}
448
449
	plan->n_rows_prefetched--;
450
451
	plan->first_prefetched++;
452
}
453
454
/*************************************************************************
455
Pushes the column values for a prefetched, cached row to the column prefetch
456
buffers from the val fields in the column nodes. */
457
UNIV_INLINE
458
void
459
sel_push_prefetched_row(
460
/*====================*/
461
	plan_t*	plan)	/* in: plan node for a table */
462
{
463
	sym_node_t*	column;
464
	sel_buf_t*	sel_buf;
465
	dfield_t*	val;
466
	byte*		data;
467
	ulint		len;
468
	ulint		pos;
469
	ulint		val_buf_size;
470
471
	if (plan->n_rows_prefetched == 0) {
472
		pos = 0;
473
		plan->first_prefetched = 0;
474
	} else {
475
		pos = plan->n_rows_prefetched;
476
477
		/* We have the convention that pushing new rows starts only
478
		after the prefetch stack has been emptied: */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
479
551.1.1 by monty at mysql
Added Innobase to source distribution
480
		ut_ad(plan->first_prefetched == 0);
481
	}
482
483
	plan->n_rows_prefetched++;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
484
551.1.1 by monty at mysql
Added Innobase to source distribution
485
	ut_ad(pos < SEL_MAX_N_PREFETCH);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
486
551.1.1 by monty at mysql
Added Innobase to source distribution
487
	column = UT_LIST_GET_FIRST(plan->columns);
488
489
	while (column) {
490
		if (!column->copy_val) {
491
			/* There is no sense to push pointers to database
492
			page fields when we do not keep latch on the page! */
493
494
			goto next_col;
495
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
496
551.1.1 by monty at mysql
Added Innobase to source distribution
497
		if (!column->prefetch_buf) {
498
			/* Allocate a new prefetch buffer */
499
500
			sel_col_prefetch_buf_alloc(column);
501
		}
502
503
		sel_buf = column->prefetch_buf + pos;
504
505
		val = que_node_get_val(column);
506
507
		data = dfield_get_data(val);
508
		len = dfield_get_len(val);
509
		val_buf_size = que_node_get_val_buf_size(column);
510
511
		/* We must keep track of the allocated memory for
512
		column values to be able to free it later: therefore
513
		we swap the values for sel_buf and val */
514
515
		dfield_set_data(val, sel_buf->data, sel_buf->len);
516
		que_node_set_val_buf_size(column, sel_buf->val_buf_size);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
517
551.1.1 by monty at mysql
Added Innobase to source distribution
518
		sel_buf->data = data;
519
		sel_buf->len = len;
520
		sel_buf->val_buf_size = val_buf_size;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
521
next_col:
551.1.1 by monty at mysql
Added Innobase to source distribution
522
		column = UT_LIST_GET_NEXT(col_var_list, column);
523
	}
524
}
525
526
/*************************************************************************
527
Builds a previous version of a clustered index record for a consistent read */
528
static
529
ulint
530
row_sel_build_prev_vers(
531
/*====================*/
532
					/* out: DB_SUCCESS or error code */
533
	read_view_t*	read_view,	/* in: read view */
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
534
	dict_index_t*	index,		/* in: plan node for table */
551.1.1 by monty at mysql
Added Innobase to source distribution
535
	rec_t*		rec,		/* in: record in a clustered index */
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
536
	ulint**		offsets,	/* in/out: offsets returned by
537
					rec_get_offsets(rec, plan->index) */
538
	mem_heap_t**	offset_heap,	/* in/out: memory heap from which
539
					the offsets are allocated */
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
540
	mem_heap_t**    old_vers_heap,  /* out: old version heap to use */
551.1.1 by monty at mysql
Added Innobase to source distribution
541
	rec_t**		old_vers,	/* out: old version, or NULL if the
542
					record does not exist in the view:
543
					i.e., it was freshly inserted
544
					afterwards */
545
	mtr_t*		mtr)		/* in: mtr */
546
{
547
	ulint	err;
548
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
549
	if (*old_vers_heap) {
550
		mem_heap_empty(*old_vers_heap);
551.1.1 by monty at mysql
Added Innobase to source distribution
551
	} else {
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
552
		*old_vers_heap = mem_heap_create(512);
551.1.1 by monty at mysql
Added Innobase to source distribution
553
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
554
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
555
	err = row_vers_build_for_consistent_read(
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
556
		rec, mtr, index, offsets, read_view, offset_heap,
557
		*old_vers_heap, old_vers);
551.1.1 by monty at mysql
Added Innobase to source distribution
558
	return(err);
559
}
560
561
/*************************************************************************
1979 by lars at mysql
WL#1012: All changes as one single changeset.
562
Builds the last committed version of a clustered index record for a
563
semi-consistent read. */
564
static
565
ulint
566
row_sel_build_committed_vers_for_mysql(
567
/*===================================*/
568
					/* out: DB_SUCCESS or error code */
569
	dict_index_t*	clust_index,	/* in: clustered index */
570
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
571
	rec_t*		rec,		/* in: record in a clustered index */
572
	ulint**		offsets,	/* in/out: offsets returned by
573
					rec_get_offsets(rec, clust_index) */
574
	mem_heap_t**	offset_heap,	/* in/out: memory heap from which
575
					the offsets are allocated */
576
	rec_t**		old_vers,	/* out: old version, or NULL if the
577
					record does not exist in the view:
578
					i.e., it was freshly inserted
579
					afterwards */
580
	mtr_t*		mtr)		/* in: mtr */
581
{
582
	ulint	err;
583
584
	if (prebuilt->old_vers_heap) {
585
		mem_heap_empty(prebuilt->old_vers_heap);
586
	} else {
587
		prebuilt->old_vers_heap = mem_heap_create(200);
588
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
589
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
590
	err = row_vers_build_for_semi_consistent_read(
591
		rec, mtr, clust_index, offsets, offset_heap,
592
		prebuilt->old_vers_heap, old_vers);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
593
	return(err);
594
}
595
596
/*************************************************************************
551.1.1 by monty at mysql
Added Innobase to source distribution
597
Tests the conditions which determine when the index segment we are searching
598
through has been exhausted. */
599
UNIV_INLINE
600
ibool
601
row_sel_test_end_conds(
602
/*===================*/
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
603
			/* out: TRUE if row passed the tests */
551.1.1 by monty at mysql
Added Innobase to source distribution
604
	plan_t*	plan)	/* in: plan for the table; the column values must
605
			already have been retrieved and the right sides of
606
			comparisons evaluated */
607
{
608
	func_node_t*	cond;
609
610
	/* All conditions in end_conds are comparisons of a column to an
611
	expression */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
612
551.1.1 by monty at mysql
Added Innobase to source distribution
613
	cond = UT_LIST_GET_FIRST(plan->end_conds);
614
615
	while (cond) {
616
		/* Evaluate the left side of the comparison, i.e., get the
617
		column value if there is an indirection */
618
619
		eval_sym(cond->args);
620
621
		/* Do the comparison */
622
623
		if (!eval_cmp(cond)) {
624
625
			return(FALSE);
626
		}
627
628
		cond = UT_LIST_GET_NEXT(cond_list, cond);
629
	}
630
631
	return(TRUE);
632
}
633
634
/*************************************************************************
635
Tests the other conditions. */
636
UNIV_INLINE
637
ibool
638
row_sel_test_other_conds(
639
/*=====================*/
640
			/* out: TRUE if row passed the tests */
641
	plan_t*	plan)	/* in: plan for the table; the column values must
642
			already have been retrieved */
643
{
644
	func_node_t*	cond;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
645
551.1.1 by monty at mysql
Added Innobase to source distribution
646
	cond = UT_LIST_GET_FIRST(plan->other_conds);
647
648
	while (cond) {
649
		eval_exp(cond);
650
651
		if (!eval_node_get_ibool_val(cond)) {
652
653
			return(FALSE);
654
		}
655
656
		cond = UT_LIST_GET_NEXT(cond_list, cond);
657
	}
658
659
	return(TRUE);
660
}
661
662
/*************************************************************************
663
Retrieves the clustered index record corresponding to a record in a
664
non-clustered index. Does the necessary locking. */
665
static
666
ulint
667
row_sel_get_clust_rec(
668
/*==================*/
669
				/* out: DB_SUCCESS or error code */
670
	sel_node_t*	node,	/* in: select_node */
671
	plan_t*		plan,	/* in: plan node for table */
672
	rec_t*		rec,	/* in: record in a non-clustered index */
673
	que_thr_t*	thr,	/* in: query thread */
674
	rec_t**		out_rec,/* out: clustered record or an old version of
675
				it, NULL if the old version did not exist
676
				in the read view, i.e., it was a fresh
677
				inserted version */
678
	mtr_t*		mtr)	/* in: mtr used to get access to the
679
				non-clustered record; the same mtr is used to
680
				access the clustered index */
681
{
682
	dict_index_t*	index;
683
	rec_t*		clust_rec;
684
	rec_t*		old_vers;
685
	ulint		err;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
686
	mem_heap_t*	heap		= NULL;
1773.10.2 by marko at mysql
InnoDB: Introduce the symbols REC_OFFS_NORMAL_SIZE and
687
	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
688
	ulint*		offsets		= offsets_;
1773.10.1 by marko at mysql
InnoDB: Improve performance by about 10% by removing implicit
689
	*offsets_ = (sizeof offsets_) / sizeof *offsets_;
1659.1.48 by marko at mysql
Many files:
690
1773.330.30 by marko at mysql
InnoDB: Remove warnings detected by GCC 4.0.0
691
	*out_rec = NULL;
692
1659.1.48 by marko at mysql
Many files:
693
	offsets = rec_get_offsets(rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
694
				  btr_pcur_get_btr_cur(&plan->pcur)->index,
695
				  offsets, ULINT_UNDEFINED, &heap);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
696
1659.1.48 by marko at mysql
Many files:
697
	row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
551.1.1 by monty at mysql
Added Innobase to source distribution
698
699
	index = dict_table_get_first_index(plan->table);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
700
551.1.1 by monty at mysql
Added Innobase to source distribution
701
	btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
702
				   node->latch_mode, &(plan->clust_pcur),
703
				   0, mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
704
705
	clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
706
1346.226.33 by heikki at mysql
row0sel.c, row0ins.c:
707
	/* Note: only if the search ends up on a non-infimum record is the
708
	low_match value the real match to the search tuple */
709
710
	if (!page_rec_is_user_rec(clust_rec)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
711
	    || btr_pcur_get_low_match(&(plan->clust_pcur))
712
	    < dict_index_get_n_unique(index)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
713
714
		ut_a(rec_get_deleted_flag(rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
715
					  dict_table_is_comp(plan->table)));
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
716
		ut_a(node->read_view);
717
718
		/* In a rare case it is possible that no clust rec is found
719
		for a delete-marked secondary index record: if in row0umod.c
720
		in row_undo_mod_remove_clust_low() we have already removed
721
		the clust rec, while purge is still cleaning and removing
722
		secondary index records associated with earlier versions of
723
		the clustered index record. In that case we know that the
724
		clustered index record did not exist in the read view of
725
		trx. */
726
727
		goto func_exit;
728
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
729
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
730
	offsets = rec_get_offsets(clust_rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
731
				  ULINT_UNDEFINED, &heap);
1659.1.48 by marko at mysql
Many files:
732
551.1.1 by monty at mysql
Added Innobase to source distribution
733
	if (!node->read_view) {
734
		/* Try to place a lock on the index record */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
735
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
736
		/* If innodb_locks_unsafe_for_binlog option is used
737
		or this session is using READ COMMITTED isolation level
1659.1.48 by marko at mysql
Many files:
738
		we lock only the record, i.e., next-key locking is
739
		not used. */
740
		ulint	lock_type;
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
741
		trx_t*	trx;
742
743
		trx = thr_get_trx(thr);
744
745
		if (srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
746
		    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
1659.1.48 by marko at mysql
Many files:
747
			lock_type = LOCK_REC_NOT_GAP;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
748
		} else {
1659.1.48 by marko at mysql
Many files:
749
			lock_type = LOCK_ORDINARY;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
750
		}
751
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
752
		err = lock_clust_rec_read_check_and_lock(
753
			0, clust_rec, index, offsets,
754
			node->row_lock_mode, lock_type, thr);
1659.1.48 by marko at mysql
Many files:
755
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
756
		if (err != DB_SUCCESS) {
551.1.1 by monty at mysql
Added Innobase to source distribution
757
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
758
			goto err_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
759
		}
760
	} else {
761
		/* This is a non-locking consistent read: if necessary, fetch
762
		a previous version of the record */
763
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
764
		old_vers = NULL;
765
1659.1.48 by marko at mysql
Many files:
766
		if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
767
						   node->read_view)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
768
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
769
			err = row_sel_build_prev_vers(
770
				node->read_view, index, clust_rec,
771
				&offsets, &heap, &plan->old_vers_heap,
772
				&old_vers, mtr);
773
551.1.1 by monty at mysql
Added Innobase to source distribution
774
			if (err != DB_SUCCESS) {
775
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
776
				goto err_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
777
			}
778
779
			clust_rec = old_vers;
780
781
			if (clust_rec == NULL) {
1659.1.48 by marko at mysql
Many files:
782
				goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
783
			}
784
		}
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
785
786
		/* If we had to go to an earlier version of row or the
787
		secondary index record is delete marked, then it may be that
788
		the secondary index record corresponding to clust_rec
789
		(or old_vers) is not rec; in that case we must ignore
790
		such row because in our snapshot rec would not have existed.
791
		Remember that from rec we cannot see directly which transaction
792
		id corresponds to it: we have to go to the clustered index
793
		record. A query where we want to fetch all rows where
794
		the secondary index value is in some interval would return
795
		a wrong result if we would not drop rows which we come to
796
		visit through secondary index records that would not really
797
		exist in our snapshot. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
798
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
799
		if ((old_vers
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
800
		     || rec_get_deleted_flag(rec, dict_table_is_comp(
801
						     plan->table)))
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
802
		    && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
803
							 clust_rec, index)) {
1659.1.48 by marko at mysql
Many files:
804
			goto func_exit;
1346.236.10 by heikki at mysql
Many files:
805
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
806
	}
807
808
	/* Fetch the columns needed in test conditions */
1659.1.48 by marko at mysql
Many files:
809
810
	row_sel_fetch_columns(index, clust_rec, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
811
			      UT_LIST_GET_FIRST(plan->columns));
1773.330.30 by marko at mysql
InnoDB: Remove warnings detected by GCC 4.0.0
812
	*out_rec = clust_rec;
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
813
func_exit:
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
814
	err = DB_SUCCESS;
815
err_exit:
1773.330.3 by marko at mysql
InnoDB: Define some macros around GCC's __builtin_expect()
816
	if (UNIV_LIKELY_NULL(heap)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
817
		mem_heap_free(heap);
818
	}
819
	return(err);
551.1.1 by monty at mysql
Added Innobase to source distribution
820
}
821
822
/*************************************************************************
823
Sets a lock on a record. */
824
UNIV_INLINE
825
ulint
826
sel_set_rec_lock(
827
/*=============*/
828
				/* out: DB_SUCCESS or error code */
829
	rec_t*		rec,	/* in: record */
830
	dict_index_t*	index,	/* in: index */
1659.1.48 by marko at mysql
Many files:
831
	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */
551.1.1 by monty at mysql
Added Innobase to source distribution
832
	ulint		mode,	/* in: lock mode */
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
833
	ulint		type,	/* in: LOCK_ORDINARY, LOCK_GAP, or
834
				LOC_REC_NOT_GAP */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
835
	que_thr_t*	thr)	/* in: query thread */
551.1.1 by monty at mysql
Added Innobase to source distribution
836
{
1616.1262.30 by heikki at mysql
Many files:
837
	trx_t*	trx;
551.1.1 by monty at mysql
Added Innobase to source distribution
838
	ulint	err;
839
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
840
	trx = thr_get_trx(thr);
1616.1262.30 by heikki at mysql
Many files:
841
842
	if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) {
843
		if (buf_LRU_buf_pool_running_out()) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
844
1616.1262.30 by heikki at mysql
Many files:
845
			return(DB_LOCK_TABLE_FULL);
846
		}
847
	}
848
551.1.1 by monty at mysql
Added Innobase to source distribution
849
	if (index->type & DICT_CLUSTERED) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
850
		err = lock_clust_rec_read_check_and_lock(
851
			0, rec, index, offsets, mode, type, thr);
551.1.1 by monty at mysql
Added Innobase to source distribution
852
	} else {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
853
		err = lock_sec_rec_read_check_and_lock(
854
			0, rec, index, offsets, mode, type, thr);
551.1.1 by monty at mysql
Added Innobase to source distribution
855
	}
856
857
	return(err);
858
}
859
860
/*************************************************************************
861
Opens a pcur to a table index. */
862
static
863
void
864
row_sel_open_pcur(
865
/*==============*/
866
	sel_node_t*	node,		/* in: select node */
867
	plan_t*		plan,		/* in: table plan */
868
	ibool		search_latch_locked,
869
					/* in: TRUE if the thread currently
870
					has the search latch locked in
871
					s-mode */
872
	mtr_t*		mtr)		/* in: mtr */
873
{
874
	dict_index_t*	index;
875
	func_node_t*	cond;
876
	que_node_t*	exp;
877
	ulint		n_fields;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
878
	ulint		has_search_latch = 0;	/* RW_S_LATCH or 0 */
551.1.1 by monty at mysql
Added Innobase to source distribution
879
	ulint		i;
880
881
	if (search_latch_locked) {
882
		has_search_latch = RW_S_LATCH;
883
	}
884
885
	index = plan->index;
886
887
	/* Calculate the value of the search tuple: the exact match columns
888
	get their expressions evaluated when we evaluate the right sides of
889
	end_conds */
890
891
	cond = UT_LIST_GET_FIRST(plan->end_conds);
892
893
	while (cond) {
894
		eval_exp(que_node_get_next(cond->args));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
895
551.1.1 by monty at mysql
Added Innobase to source distribution
896
		cond = UT_LIST_GET_NEXT(cond_list, cond);
897
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
898
551.1.1 by monty at mysql
Added Innobase to source distribution
899
	if (plan->tuple) {
900
		n_fields = dtuple_get_n_fields(plan->tuple);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
901
551.1.1 by monty at mysql
Added Innobase to source distribution
902
		if (plan->n_exact_match < n_fields) {
903
			/* There is a non-exact match field which must be
904
			evaluated separately */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
905
551.1.1 by monty at mysql
Added Innobase to source distribution
906
			eval_exp(plan->tuple_exps[n_fields - 1]);
907
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
908
551.1.1 by monty at mysql
Added Innobase to source distribution
909
		for (i = 0; i < n_fields; i++) {
910
			exp = plan->tuple_exps[i];
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
911
551.1.1 by monty at mysql
Added Innobase to source distribution
912
			dfield_copy_data(dtuple_get_nth_field(plan->tuple, i),
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
913
					 que_node_get_val(exp));
551.1.1 by monty at mysql
Added Innobase to source distribution
914
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
915
551.1.1 by monty at mysql
Added Innobase to source distribution
916
		/* Open pcur to the index */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
917
551.1.1 by monty at mysql
Added Innobase to source distribution
918
		btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
919
					   node->latch_mode, &(plan->pcur),
920
					   has_search_latch, mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
921
	} else {
922
		/* Open the cursor to the start or the end of the index
923
		(FALSE: no init) */
924
925
		btr_pcur_open_at_index_side(plan->asc, index, node->latch_mode,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
926
					    &(plan->pcur), FALSE, mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
927
	}
928
929
	ut_ad(plan->n_rows_prefetched == 0);
930
	ut_ad(plan->n_rows_fetched == 0);
931
	ut_ad(plan->cursor_at_end == FALSE);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
932
551.1.1 by monty at mysql
Added Innobase to source distribution
933
	plan->pcur_is_open = TRUE;
934
}
935
936
/*************************************************************************
937
Restores a stored pcur position to a table index. */
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
938
static
551.1.1 by monty at mysql
Added Innobase to source distribution
939
ibool
940
row_sel_restore_pcur_pos(
941
/*=====================*/
942
				/* out: TRUE if the cursor should be moved to
943
				the next record after we return from this
944
				function (moved to the previous, in the case
945
				of a descending cursor) without processing
946
				again the current cursor record */
947
	sel_node_t*	node,	/* in: select node */
948
	plan_t*		plan,	/* in: table plan */
949
	mtr_t*		mtr)	/* in: mtr */
950
{
951
	ibool	equal_position;
952
	ulint	relative_position;
953
954
	ut_ad(!plan->cursor_at_end);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
955
551.1.1 by monty at mysql
Added Innobase to source distribution
956
	relative_position = btr_pcur_get_rel_pos(&(plan->pcur));
957
958
	equal_position = btr_pcur_restore_position(node->latch_mode,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
959
						   &(plan->pcur), mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
960
961
	/* If the cursor is traveling upwards, and relative_position is
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
962
551.1.1 by monty at mysql
Added Innobase to source distribution
963
	(1) BTR_PCUR_BEFORE: this is not allowed, as we did not have a lock
964
	yet on the successor of the page infimum;
965
	(2) BTR_PCUR_AFTER: btr_pcur_restore_position placed the cursor on the
966
	first record GREATER than the predecessor of a page supremum; we have
967
	not yet processed the cursor record: no need to move the cursor to the
968
	next record;
969
	(3) BTR_PCUR_ON: btr_pcur_restore_position placed the cursor on the
970
	last record LESS or EQUAL to the old stored user record; (a) if
971
	equal_position is FALSE, this means that the cursor is now on a record
972
	less than the old user record, and we must move to the next record;
973
	(b) if equal_position is TRUE, then if
974
	plan->stored_cursor_rec_processed is TRUE, we must move to the next
975
	record, else there is no need to move the cursor. */
976
977
	if (plan->asc) {
978
		if (relative_position == BTR_PCUR_ON) {
979
980
			if (equal_position) {
981
982
				return(plan->stored_cursor_rec_processed);
983
			}
984
985
			return(TRUE);
986
		}
987
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
988
		ut_ad(relative_position == BTR_PCUR_AFTER
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
989
		      || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
551.1.1 by monty at mysql
Added Innobase to source distribution
990
991
		return(FALSE);
992
	}
993
994
	/* If the cursor is traveling downwards, and relative_position is
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
995
551.1.1 by monty at mysql
Added Innobase to source distribution
996
	(1) BTR_PCUR_BEFORE: btr_pcur_restore_position placed the cursor on
997
	the last record LESS than the successor of a page infimum; we have not
998
	processed the cursor record: no need to move the cursor;
999
	(2) BTR_PCUR_AFTER: btr_pcur_restore_position placed the cursor on the
1000
	first record GREATER than the predecessor of a page supremum; we have
1001
	processed the cursor record: we should move the cursor to the previous
1002
	record;
1003
	(3) BTR_PCUR_ON: btr_pcur_restore_position placed the cursor on the
1004
	last record LESS or EQUAL to the old stored user record; (a) if
1005
	equal_position is FALSE, this means that the cursor is now on a record
1006
	less than the old user record, and we need not move to the previous
1007
	record; (b) if equal_position is TRUE, then if
1008
	plan->stored_cursor_rec_processed is TRUE, we must move to the previous
1009
	record, else there is no need to move the cursor. */
1010
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
1011
	if (relative_position == BTR_PCUR_BEFORE
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1012
	    || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1013
1014
		return(FALSE);
1015
	}
1016
1017
	if (relative_position == BTR_PCUR_ON) {
1018
1019
		if (equal_position) {
1020
1021
			return(plan->stored_cursor_rec_processed);
1022
		}
1023
1024
		return(FALSE);
1025
	}
1026
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
1027
	ut_ad(relative_position == BTR_PCUR_AFTER
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1028
	      || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE);
551.1.1 by monty at mysql
Added Innobase to source distribution
1029
1030
	return(TRUE);
1031
}
1032
1033
/*************************************************************************
1034
Resets a plan cursor to a closed state. */
1035
UNIV_INLINE
1036
void
1037
plan_reset_cursor(
1038
/*==============*/
1039
	plan_t*	plan)	/* in: plan */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1040
{
551.1.1 by monty at mysql
Added Innobase to source distribution
1041
	plan->pcur_is_open = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1042
	plan->cursor_at_end = FALSE;
551.1.1 by monty at mysql
Added Innobase to source distribution
1043
	plan->n_rows_fetched = 0;
1044
	plan->n_rows_prefetched = 0;
1045
}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1046
551.1.1 by monty at mysql
Added Innobase to source distribution
1047
/*************************************************************************
1048
Tries to do a shortcut to fetch a clustered index record with a unique key,
1049
using the hash index if possible (not always). */
1050
static
1051
ulint
1052
row_sel_try_search_shortcut(
1053
/*========================*/
1054
				/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
1055
	sel_node_t*	node,	/* in: select node for a consistent read */
1056
	plan_t*		plan,	/* in: plan for a unique search in clustered
1057
				index */
1058
	mtr_t*		mtr)	/* in: mtr */
1059
{
1060
	dict_index_t*	index;
1061
	rec_t*		rec;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1062
	mem_heap_t*	heap		= NULL;
1773.10.2 by marko at mysql
InnoDB: Introduce the symbols REC_OFFS_NORMAL_SIZE and
1063
	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1064
	ulint*		offsets		= offsets_;
1065
	ulint		ret;
1773.10.1 by marko at mysql
InnoDB: Improve performance by about 10% by removing implicit
1066
	*offsets_ = (sizeof offsets_) / sizeof *offsets_;
551.1.1 by monty at mysql
Added Innobase to source distribution
1067
1068
	index = plan->index;
1069
1070
	ut_ad(node->read_view);
1071
	ut_ad(plan->unique_search);
1072
	ut_ad(!plan->must_get_clust);
1346.524.50 by marko at mysql
Allow UNIV_SYNC_DEBUG to be disabled while UNIV_DEBUG is enabled
1073
#ifdef UNIV_SYNC_DEBUG
551.1.1 by monty at mysql
Added Innobase to source distribution
1074
	ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1346.524.50 by marko at mysql
Allow UNIV_SYNC_DEBUG to be disabled while UNIV_DEBUG is enabled
1075
#endif /* UNIV_SYNC_DEBUG */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1076
551.1.1 by monty at mysql
Added Innobase to source distribution
1077
	row_sel_open_pcur(node, plan, TRUE, mtr);
1078
1079
	rec = btr_pcur_get_rec(&(plan->pcur));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1080
551.1.1 by monty at mysql
Added Innobase to source distribution
1081
	if (!page_rec_is_user_rec(rec)) {
1082
1083
		return(SEL_RETRY);
1084
	}
1085
1086
	ut_ad(plan->mode == PAGE_CUR_GE);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1087
551.1.1 by monty at mysql
Added Innobase to source distribution
1088
	/* As the cursor is now placed on a user record after a search with
1089
	the mode PAGE_CUR_GE, the up_match field in the cursor tells how many
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1090
	fields in the user record matched to the search tuple */
551.1.1 by monty at mysql
Added Innobase to source distribution
1091
1092
	if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) {
1093
1094
		return(SEL_EXHAUSTED);
1095
	}
1096
1097
	/* This is a non-locking consistent read: if necessary, fetch
1098
	a previous version of the record */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1099
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1100
	offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1659.1.48 by marko at mysql
Many files:
1101
551.1.1 by monty at mysql
Added Innobase to source distribution
1102
	if (index->type & DICT_CLUSTERED) {
1659.1.48 by marko at mysql
Many files:
1103
		if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1104
						   node->read_view)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1105
			ret = SEL_RETRY;
1106
			goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1107
		}
1108
	} else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
1109
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1110
		ret = SEL_RETRY;
1111
		goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1112
	}
1113
1114
	/* Test deleted flag. Fetch the columns needed in test conditions. */
1659.1.48 by marko at mysql
Many files:
1115
1116
	row_sel_fetch_columns(index, rec, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1117
			      UT_LIST_GET_FIRST(plan->columns));
1659.1.48 by marko at mysql
Many files:
1118
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1119
	if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1120
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1121
		ret = SEL_EXHAUSTED;
1122
		goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1123
	}
1124
1125
	/* Test the rest of search conditions */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1126
551.1.1 by monty at mysql
Added Innobase to source distribution
1127
	if (!row_sel_test_other_conds(plan)) {
1128
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1129
		ret = SEL_EXHAUSTED;
1130
		goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1131
	}
1132
1133
	ut_ad(plan->pcur.latch_mode == node->latch_mode);
1134
1135
	plan->n_rows_fetched++;
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1136
	ret = SEL_FOUND;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1137
func_exit:
1773.330.3 by marko at mysql
InnoDB: Define some macros around GCC's __builtin_expect()
1138
	if (UNIV_LIKELY_NULL(heap)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1139
		mem_heap_free(heap);
1140
	}
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1141
	return(ret);
551.1.1 by monty at mysql
Added Innobase to source distribution
1142
}
1143
1144
/*************************************************************************
1145
Performs a select step. */
1146
static
1147
ulint
1148
row_sel(
1149
/*====*/
1150
				/* out: DB_SUCCESS or error code */
1151
	sel_node_t*	node,	/* in: select node */
1152
	que_thr_t*	thr)	/* in: query thread */
1153
{
1154
	dict_index_t*	index;
1155
	plan_t*		plan;
1156
	mtr_t		mtr;
1157
	ibool		moved;
1158
	rec_t*		rec;
1159
	rec_t*		old_vers;
1160
	rec_t*		clust_rec;
1161
	ibool		search_latch_locked;
1162
	ibool		consistent_read;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1163
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1164
	/* The following flag becomes TRUE when we are doing a
1165
	consistent read from a non-clustered index and we must look
1166
	at the clustered index to find out the previous delete mark
1167
	state of the non-clustered record: */
551.1.1 by monty at mysql
Added Innobase to source distribution
1168
1169
	ibool		cons_read_requires_clust_rec	= FALSE;
1170
	ulint		cost_counter			= 0;
1171
	ibool		cursor_just_opened;
1172
	ibool		must_go_to_next;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1173
	ibool		leaf_contains_updates		= FALSE;
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1174
	/* TRUE if select_will_do_update is
1175
	TRUE and the current clustered index
1176
	leaf page has been updated during
1177
	the current mtr: mtr must be committed
1178
	at the same time as the leaf x-latch
1179
	is released */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1180
	ibool		mtr_has_extra_clust_latch	= FALSE;
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1181
	/* TRUE if the search was made using
1182
	a non-clustered index, and we had to
1183
	access the clustered record: now &mtr
1184
	contains a clustered index latch, and
1185
	&mtr must be committed before we move
1186
	to the next non-clustered record */
551.1.1 by monty at mysql
Added Innobase to source distribution
1187
	ulint		found_flag;
1188
	ulint		err;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1189
	mem_heap_t*	heap				= NULL;
1773.10.2 by marko at mysql
InnoDB: Introduce the symbols REC_OFFS_NORMAL_SIZE and
1190
	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1191
	ulint*		offsets				= offsets_;
1773.10.1 by marko at mysql
InnoDB: Improve performance by about 10% by removing implicit
1192
	*offsets_ = (sizeof offsets_) / sizeof *offsets_;
1659.1.48 by marko at mysql
Many files:
1193
551.1.1 by monty at mysql
Added Innobase to source distribution
1194
	ut_ad(thr->run_node == node);
1195
1196
	search_latch_locked = FALSE;
1197
1198
	if (node->read_view) {
1199
		/* In consistent reads, we try to do with the hash index and
1200
		not to use the buffer page get. This is to reduce memory bus
1201
		load resulting from semaphore operations. The search latch
1202
		will be s-locked when we access an index with a unique search
1203
		condition, but not locked when we access an index with a
1204
		less selective search condition. */
1205
1206
		consistent_read = TRUE;
1207
	} else {
1208
		consistent_read = FALSE;
1209
	}
1210
1211
table_loop:
1212
	/* TABLE LOOP
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1213
	----------
551.1.1 by monty at mysql
Added Innobase to source distribution
1214
	This is the outer major loop in calculating a join. We come here when
1215
	node->fetch_table changes, and after adding a row to aggregate totals
1216
	and, of course, when this function is called. */
1217
1218
	ut_ad(leaf_contains_updates == FALSE);
1219
	ut_ad(mtr_has_extra_clust_latch == FALSE);
1220
1221
	plan = sel_node_get_nth_plan(node, node->fetch_table);
1222
	index = plan->index;
1223
1224
	if (plan->n_rows_prefetched > 0) {
1225
		sel_pop_prefetched_row(plan);
1226
1227
		goto next_table_no_mtr;
1228
	}
1229
1230
	if (plan->cursor_at_end) {
1231
		/* The cursor has already reached the result set end: no more
1232
		rows to process for this table cursor, as also the prefetch
1233
		stack was empty */
1234
1235
		ut_ad(plan->pcur_is_open);
1236
1237
		goto table_exhausted_no_mtr;
1238
	}
1239
1240
	/* Open a cursor to index, or restore an open cursor position */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1241
551.1.1 by monty at mysql
Added Innobase to source distribution
1242
	mtr_start(&mtr);
1243
1244
	if (consistent_read && plan->unique_search && !plan->pcur_is_open
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1245
	    && !plan->must_get_clust
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
1246
	    && !plan->table->big_rows) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1247
		if (!search_latch_locked) {
1248
			rw_lock_s_lock(&btr_search_latch);
1249
1250
			search_latch_locked = TRUE;
1251
		} else if (btr_search_latch.writer_is_wait_ex) {
1252
1253
			/* There is an x-latch request waiting: release the
1254
			s-latch for a moment; as an s-latch here is often
1255
			kept for some 10 searches before being released,
1256
			a waiting x-latch request would block other threads
1257
			from acquiring an s-latch for a long time, lowering
1258
			performance significantly in multiprocessors. */
1259
1260
			rw_lock_s_unlock(&btr_search_latch);
1261
			rw_lock_s_lock(&btr_search_latch);
1262
		}
1263
1264
		found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1265
1266
		if (found_flag == SEL_FOUND) {
1267
1268
			goto next_table;
1269
1270
		} else if (found_flag == SEL_EXHAUSTED) {
1271
1272
			goto table_exhausted;
1273
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1274
551.1.1 by monty at mysql
Added Innobase to source distribution
1275
		ut_ad(found_flag == SEL_RETRY);
1276
1277
		plan_reset_cursor(plan);
1278
1279
		mtr_commit(&mtr);
1280
		mtr_start(&mtr);
1281
	}
1282
1283
	if (search_latch_locked) {
1284
		rw_lock_s_unlock(&btr_search_latch);
1285
1286
		search_latch_locked = FALSE;
1287
	}
1288
1289
	if (!plan->pcur_is_open) {
1290
		/* Evaluate the expressions to build the search tuple and
1291
		open the cursor */
1292
1293
		row_sel_open_pcur(node, plan, search_latch_locked, &mtr);
1294
1295
		cursor_just_opened = TRUE;
1296
1297
		/* A new search was made: increment the cost counter */
1298
		cost_counter++;
1299
	} else {
1300
		/* Restore pcur position to the index */
1301
1302
		must_go_to_next = row_sel_restore_pcur_pos(node, plan, &mtr);
1303
1304
		cursor_just_opened = FALSE;
1305
1306
		if (must_go_to_next) {
1307
			/* We have already processed the cursor record: move
1308
			to the next */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1309
551.1.1 by monty at mysql
Added Innobase to source distribution
1310
			goto next_rec;
1311
		}
1312
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1313
551.1.1 by monty at mysql
Added Innobase to source distribution
1314
rec_loop:
1315
	/* RECORD LOOP
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1316
	-----------
551.1.1 by monty at mysql
Added Innobase to source distribution
1317
	In this loop we use pcur and try to fetch a qualifying row, and
1318
	also fill the prefetch buffer for this table if n_rows_fetched has
1319
	exceeded a threshold. While we are inside this loop, the following
1320
	holds:
1321
	(1) &mtr is started,
1322
	(2) pcur is positioned and open.
1323
1324
	NOTE that if cursor_just_opened is TRUE here, it means that we came
1325
	to this point right after row_sel_open_pcur. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1326
551.1.1 by monty at mysql
Added Innobase to source distribution
1327
	ut_ad(mtr_has_extra_clust_latch == FALSE);
1328
1329
	rec = btr_pcur_get_rec(&(plan->pcur));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1330
551.1.1 by monty at mysql
Added Innobase to source distribution
1331
	/* PHASE 1: Set a lock if specified */
1332
1333
	if (!node->asc && cursor_just_opened
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1334
	    && !page_rec_is_supremum(rec)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1335
1336
		/* When we open a cursor for a descending search, we must set
1337
		a next-key lock on the successor record: otherwise it would
1338
		be possible to insert new records next to the cursor position,
1339
		and it might be that these new records should appear in the
1340
		search result set, resulting in the phantom problem. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1341
551.1.1 by monty at mysql
Added Innobase to source distribution
1342
		if (!consistent_read) {
1616.657.1 by jan at mysql
Added innodb_locks_unsafe_for_binlog option. This option turns off Innodb
1343
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1344
			/* If innodb_locks_unsafe_for_binlog option is used
1345
			or this session is using READ COMMITTED isolation
1346
			level, we lock only the record, i.e., next-key
1347
			locking is not used. */
1659.1.48 by marko at mysql
Many files:
1348
1349
			rec_t*	next_rec = page_rec_get_next(rec);
1350
			ulint	lock_type;
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1351
			trx_t*	trx;
1352
1353
			trx = thr_get_trx(thr);
1354
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1355
			offsets = rec_get_offsets(next_rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1356
						  ULINT_UNDEFINED, &heap);
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1357
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1358
			if (srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1359
			    || trx->isolation_level
1360
			    == TRX_ISO_READ_COMMITTED) {
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1361
1362
				if (page_rec_is_supremum(next_rec)) {
1363
1364
					goto skip_lock;
1365
				}
1366
1659.1.48 by marko at mysql
Many files:
1367
				lock_type = LOCK_REC_NOT_GAP;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1368
			} else {
1659.1.48 by marko at mysql
Many files:
1369
				lock_type = LOCK_ORDINARY;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1370
			}
1371
1659.1.48 by marko at mysql
Many files:
1372
			err = sel_set_rec_lock(next_rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1373
					       node->row_lock_mode,
1374
					       lock_type, thr);
1659.1.48 by marko at mysql
Many files:
1375
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1376
			if (err != DB_SUCCESS) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1377
				/* Note that in this case we will store in pcur
1378
				the PREDECESSOR of the record we are waiting
1379
				the lock for */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1380
551.1.1 by monty at mysql
Added Innobase to source distribution
1381
				goto lock_wait_or_error;
1382
			}
1383
		}
1384
	}
1385
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1386
skip_lock:
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
1387
	if (page_rec_is_infimum(rec)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1388
1389
		/* The infimum record on a page cannot be in the result set,
1390
		and neither can a record lock be placed on it: we skip such
1391
		a record. We also increment the cost counter as we may have
1392
		processed yet another page of index. */
1393
1394
		cost_counter++;
1395
1396
		goto next_rec;
1397
	}
1398
1399
	if (!consistent_read) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1400
		/* Try to place a lock on the index record */
551.1.1 by monty at mysql
Added Innobase to source distribution
1401
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1402
		/* If innodb_locks_unsafe_for_binlog option is used
1403
		or this session is using READ COMMITTED isolation level,
1659.1.48 by marko at mysql
Many files:
1404
		we lock only the record, i.e., next-key locking is
1405
		not used. */
1406
1407
		ulint	lock_type;
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1408
		trx_t*	trx;
1409
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1410
		offsets = rec_get_offsets(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1411
					  ULINT_UNDEFINED, &heap);
1616.657.1 by jan at mysql
Added innodb_locks_unsafe_for_binlog option. This option turns off Innodb
1412
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
1413
		trx = thr_get_trx(thr);
1414
1415
		if (srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1416
		    || trx->isolation_level == TRX_ISO_READ_COMMITTED) {
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1417
1418
			if (page_rec_is_supremum(rec)) {
1419
1420
				goto next_rec;
1421
			}
1422
1659.1.48 by marko at mysql
Many files:
1423
			lock_type = LOCK_REC_NOT_GAP;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1424
		} else {
1659.1.48 by marko at mysql
Many files:
1425
			lock_type = LOCK_ORDINARY;
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
1426
		}
1616.657.1 by jan at mysql
Added innodb_locks_unsafe_for_binlog option. This option turns off Innodb
1427
1659.1.48 by marko at mysql
Many files:
1428
		err = sel_set_rec_lock(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1429
				       node->row_lock_mode, lock_type, thr);
1659.1.48 by marko at mysql
Many files:
1430
551.1.1 by monty at mysql
Added Innobase to source distribution
1431
		if (err != DB_SUCCESS) {
1432
1433
			goto lock_wait_or_error;
1434
		}
1435
	}
1436
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
1437
	if (page_rec_is_supremum(rec)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1438
1439
		/* A page supremum record cannot be in the result set: skip
1440
		it now when we have placed a possible lock on it */
1441
1442
		goto next_rec;
1443
	}
1444
1445
	ut_ad(page_rec_is_user_rec(rec));
1446
1447
	if (cost_counter > SEL_COST_LIMIT) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1448
551.1.1 by monty at mysql
Added Innobase to source distribution
1449
		/* Now that we have placed the necessary locks, we can stop
1450
		for a while and store the cursor position; NOTE that if we
1451
		would store the cursor position BEFORE placing a record lock,
1452
		it might happen that the cursor would jump over some records
1453
		that another transaction could meanwhile insert adjacent to
1454
		the cursor: this would result in the phantom problem. */
1455
1456
		goto stop_for_a_while;
1457
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1458
551.1.1 by monty at mysql
Added Innobase to source distribution
1459
	/* PHASE 2: Check a mixed index mix id if needed */
1460
1461
	if (plan->unique_search && cursor_just_opened) {
1462
1463
		ut_ad(plan->mode == PAGE_CUR_GE);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1464
551.1.1 by monty at mysql
Added Innobase to source distribution
1465
		/* As the cursor is now placed on a user record after a search
1466
		with the mode PAGE_CUR_GE, the up_match field in the cursor
1467
		tells how many fields in the user record matched to the search
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1468
		tuple */
551.1.1 by monty at mysql
Added Innobase to source distribution
1469
1470
		if (btr_pcur_get_up_match(&(plan->pcur))
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1471
		    < plan->n_exact_match) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1472
			goto table_exhausted;
1473
		}
1474
1475
		/* Ok, no need to test end_conds or mix id */
1476
1477
	}
1478
1479
	/* We are ready to look at a possible new index entry in the result
1480
	set: the cursor is now placed on a user record */
1481
1482
	/* PHASE 3: Get previous version in a consistent read */
1483
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
1484
	cons_read_requires_clust_rec = FALSE;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1485
	offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
1486
551.1.1 by monty at mysql
Added Innobase to source distribution
1487
	if (consistent_read) {
1488
		/* This is a non-locking consistent read: if necessary, fetch
1489
		a previous version of the record */
1490
1491
		if (index->type & DICT_CLUSTERED) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1492
1659.1.48 by marko at mysql
Many files:
1493
			if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1494
							   node->read_view)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1495
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
1496
				err = row_sel_build_prev_vers(
1497
					node->read_view, index, rec,
1498
					&offsets, &heap, &plan->old_vers_heap,
1499
					&old_vers, &mtr);
1500
551.1.1 by monty at mysql
Added Innobase to source distribution
1501
				if (err != DB_SUCCESS) {
1502
1503
					goto lock_wait_or_error;
1504
				}
1505
1506
				if (old_vers == NULL) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
1507
					offsets = rec_get_offsets(
1508
						rec, index, offsets,
1509
						ULINT_UNDEFINED, &heap);
1510
					row_sel_fetch_columns(
1511
						index, rec, offsets,
1512
						UT_LIST_GET_FIRST(
1513
							plan->columns));
551.1.1 by monty at mysql
Added Innobase to source distribution
1514
1515
					if (!row_sel_test_end_conds(plan)) {
1516
1517
						goto table_exhausted;
1518
					}
1519
1520
					goto next_rec;
1521
				}
1522
1523
				rec = old_vers;
1524
			}
1525
		} else if (!lock_sec_rec_cons_read_sees(rec, index,
1526
							node->read_view)) {
1527
			cons_read_requires_clust_rec = TRUE;
1528
		}
1529
	}
1530
1531
	/* PHASE 4: Test search end conditions and deleted flag */
1532
1533
	/* Fetch the columns needed in test conditions */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1534
1659.1.48 by marko at mysql
Many files:
1535
	row_sel_fetch_columns(index, rec, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1536
			      UT_LIST_GET_FIRST(plan->columns));
551.1.1 by monty at mysql
Added Innobase to source distribution
1537
1538
	/* Test the selection end conditions: these can only contain columns
1539
	which already are found in the index, even though the index might be
1540
	non-clustered */
1541
1542
	if (plan->unique_search && cursor_just_opened) {
1543
1544
		/* No test necessary: the test was already made above */
1545
1546
	} else if (!row_sel_test_end_conds(plan)) {
1547
1548
		goto table_exhausted;
1549
	}
1550
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1551
	if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1552
	    && !cons_read_requires_clust_rec) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1553
1554
		/* The record is delete marked: we can skip it if this is
1555
		not a consistent read which might see an earlier version
1556
		of a non-clustered index record */
1557
1558
		if (plan->unique_search) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1559
551.1.1 by monty at mysql
Added Innobase to source distribution
1560
			goto table_exhausted;
1561
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1562
551.1.1 by monty at mysql
Added Innobase to source distribution
1563
		goto next_rec;
1564
	}
1565
1566
	/* PHASE 5: Get the clustered index record, if needed and if we did
1567
	not do the search using the clustered index */
1568
1569
	if (plan->must_get_clust || cons_read_requires_clust_rec) {
1570
1571
		/* It was a non-clustered index and we must fetch also the
1572
		clustered index record */
1573
1574
		err = row_sel_get_clust_rec(node, plan, rec, thr, &clust_rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1575
					    &mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
1576
		mtr_has_extra_clust_latch = TRUE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1577
551.1.1 by monty at mysql
Added Innobase to source distribution
1578
		if (err != DB_SUCCESS) {
1579
1580
			goto lock_wait_or_error;
1581
		}
1582
1583
		/* Retrieving the clustered record required a search:
1584
		increment the cost counter */
1585
1586
		cost_counter++;
1587
1588
		if (clust_rec == NULL) {
1589
			/* The record did not exist in the read view */
1590
			ut_ad(consistent_read);
1591
1592
			goto next_rec;
1593
		}
1594
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1595
		if (rec_get_deleted_flag(clust_rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1596
					 dict_table_is_comp(plan->table))) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1597
1598
			/* The record is delete marked: we can skip it */
1599
1600
			goto next_rec;
1601
		}
1602
1603
		if (node->can_get_updated) {
1604
1605
			btr_pcur_store_position(&(plan->clust_pcur), &mtr);
1606
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1607
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
1608
1609
	/* PHASE 6: Test the rest of search conditions */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1610
551.1.1 by monty at mysql
Added Innobase to source distribution
1611
	if (!row_sel_test_other_conds(plan)) {
1612
1613
		if (plan->unique_search) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1614
551.1.1 by monty at mysql
Added Innobase to source distribution
1615
			goto table_exhausted;
1616
		}
1617
1618
		goto next_rec;
1619
	}
1620
1621
	/* PHASE 7: We found a new qualifying row for the current table; push
1622
	the row if prefetch is on, or move to the next table in the join */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1623
551.1.1 by monty at mysql
Added Innobase to source distribution
1624
	plan->n_rows_fetched++;
1625
1626
	ut_ad(plan->pcur.latch_mode == node->latch_mode);
1627
1628
	if (node->select_will_do_update) {
1629
		/* This is a searched update and we can do the update in-place,
1630
		saving CPU time */
1631
1632
		row_upd_in_place_in_select(node, thr, &mtr);
1633
1634
		leaf_contains_updates = TRUE;
1635
1636
		/* When the database is in the online backup mode, the number
1637
		of log records for a single mtr should be small: increment the
1638
		cost counter to ensure it */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1639
551.1.1 by monty at mysql
Added Innobase to source distribution
1640
		cost_counter += 1 + (SEL_COST_LIMIT / 8);
1641
1642
		if (plan->unique_search) {
1643
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1644
			goto table_exhausted;
551.1.1 by monty at mysql
Added Innobase to source distribution
1645
		}
1646
1647
		goto next_rec;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1648
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
1649
1650
	if ((plan->n_rows_fetched <= SEL_PREFETCH_LIMIT)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1651
	    || plan->unique_search || plan->no_prefetch
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
1652
	    || plan->table->big_rows) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1653
1654
		/* No prefetch in operation: go to the next table */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1655
551.1.1 by monty at mysql
Added Innobase to source distribution
1656
		goto next_table;
1657
	}
1658
1659
	sel_push_prefetched_row(plan);
1660
1661
	if (plan->n_rows_prefetched == SEL_MAX_N_PREFETCH) {
1662
1663
		/* The prefetch buffer is now full */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1664
551.1.1 by monty at mysql
Added Innobase to source distribution
1665
		sel_pop_prefetched_row(plan);
1666
1667
		goto next_table;
1668
	}
1669
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1670
next_rec:
551.1.1 by monty at mysql
Added Innobase to source distribution
1671
	ut_ad(!search_latch_locked);
1672
1673
	if (mtr_has_extra_clust_latch) {
1674
1675
		/* We must commit &mtr if we are moving to the next
1676
		non-clustered index record, because we could break the
1677
		latching order if we would access a different clustered
1678
		index page right away without releasing the previous. */
1679
1680
		goto commit_mtr_for_a_while;
1681
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1682
551.1.1 by monty at mysql
Added Innobase to source distribution
1683
	if (leaf_contains_updates
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1684
	    && btr_pcur_is_after_last_on_page(&(plan->pcur), &mtr)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1685
1686
		/* We must commit &mtr if we are moving to a different page,
1687
		because we have done updates to the x-latched leaf page, and
1688
		the latch would be released in btr_pcur_move_to_next, without
1689
		&mtr getting committed there */
1690
1691
		ut_ad(node->asc);
1692
1693
		goto commit_mtr_for_a_while;
1694
	}
1695
1696
	if (node->asc) {
1697
		moved = btr_pcur_move_to_next(&(plan->pcur), &mtr);
1698
	} else {
1699
		moved = btr_pcur_move_to_prev(&(plan->pcur), &mtr);
1700
	}
1701
1702
	if (!moved) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1703
551.1.1 by monty at mysql
Added Innobase to source distribution
1704
		goto table_exhausted;
1705
	}
1706
1707
	cursor_just_opened = FALSE;
1708
1709
	/* END OF RECORD LOOP
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1710
	------------------ */
551.1.1 by monty at mysql
Added Innobase to source distribution
1711
	goto rec_loop;
1712
1713
next_table:
1714
	/* We found a record which satisfies the conditions: we can move to
1715
	the next table or return a row in the result set */
1716
1717
	ut_ad(btr_pcur_is_on_user_rec(&(plan->pcur), &mtr));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1718
551.1.1 by monty at mysql
Added Innobase to source distribution
1719
	if (plan->unique_search && !node->can_get_updated) {
1720
1721
		plan->cursor_at_end = TRUE;
1722
	} else {
1723
		ut_ad(!search_latch_locked);
1724
1725
		plan->stored_cursor_rec_processed = TRUE;
1726
1727
		btr_pcur_store_position(&(plan->pcur), &mtr);
1728
	}
1729
1730
	mtr_commit(&mtr);
1731
1732
	leaf_contains_updates = FALSE;
1733
	mtr_has_extra_clust_latch = FALSE;
1734
1735
next_table_no_mtr:
1736
	/* If we use 'goto' to this label, it means that the row was popped
1737
	from the prefetched rows stack, and &mtr is already committed */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1738
551.1.1 by monty at mysql
Added Innobase to source distribution
1739
	if (node->fetch_table + 1 == node->n_tables) {
1740
1741
		sel_eval_select_list(node);
1742
1743
		if (node->is_aggregate) {
1744
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1745
			goto table_loop;
551.1.1 by monty at mysql
Added Innobase to source distribution
1746
		}
1747
1748
		sel_assign_into_var_values(node->into_list, node);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1749
551.1.1 by monty at mysql
Added Innobase to source distribution
1750
		thr->run_node = que_node_get_parent(node);
1751
1752
		if (search_latch_locked) {
1753
			rw_lock_s_unlock(&btr_search_latch);
1754
		}
1659.1.48 by marko at mysql
Many files:
1755
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1756
		err = DB_SUCCESS;
1757
		goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1758
	}
1759
1760
	node->fetch_table++;
1761
1762
	/* When we move to the next table, we first reset the plan cursor:
1763
	we do not care about resetting it when we backtrack from a table */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1764
551.1.1 by monty at mysql
Added Innobase to source distribution
1765
	plan_reset_cursor(sel_node_get_nth_plan(node, node->fetch_table));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1766
551.1.1 by monty at mysql
Added Innobase to source distribution
1767
	goto table_loop;
1768
1769
table_exhausted:
1770
	/* The table cursor pcur reached the result set end: backtrack to the
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1771
	previous table in the join if we do not have cached prefetched rows */
551.1.1 by monty at mysql
Added Innobase to source distribution
1772
1773
	plan->cursor_at_end = TRUE;
1774
1775
	mtr_commit(&mtr);
1776
1777
	leaf_contains_updates = FALSE;
1778
	mtr_has_extra_clust_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1779
551.1.1 by monty at mysql
Added Innobase to source distribution
1780
	if (plan->n_rows_prefetched > 0) {
1781
		/* The table became exhausted during a prefetch */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1782
551.1.1 by monty at mysql
Added Innobase to source distribution
1783
		sel_pop_prefetched_row(plan);
1784
1785
		goto next_table_no_mtr;
1786
	}
1787
1788
table_exhausted_no_mtr:
1789
	if (node->fetch_table == 0) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1790
		err = DB_SUCCESS;
551.1.1 by monty at mysql
Added Innobase to source distribution
1791
1792
		if (node->is_aggregate && !node->aggregate_already_fetched) {
1793
1794
			node->aggregate_already_fetched = TRUE;
1795
1796
			sel_assign_into_var_values(node->into_list, node);
1797
1798
			thr->run_node = que_node_get_parent(node);
1799
1800
			if (search_latch_locked) {
1801
				rw_lock_s_unlock(&btr_search_latch);
1802
			}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1803
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1804
			goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1805
		}
1806
1807
		node->state = SEL_NODE_NO_MORE_ROWS;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1808
551.1.1 by monty at mysql
Added Innobase to source distribution
1809
		thr->run_node = que_node_get_parent(node);
1810
1811
		if (search_latch_locked) {
1812
			rw_lock_s_unlock(&btr_search_latch);
1813
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1814
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1815
		goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1816
	}
1817
1818
	node->fetch_table--;
1819
1820
	goto table_loop;
1821
1822
stop_for_a_while:
1823
	/* Return control for a while to que_run_threads, so that runaway
1824
	queries can be canceled. NOTE that when we come here, we must, in a
1825
	locking read, have placed the necessary (possibly waiting request)
1826
	record lock on the cursor record or its successor: when we reposition
1827
	the cursor, this record lock guarantees that nobody can meanwhile have
1828
	inserted new records which should have appeared in the result set,
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1829
	which would result in the phantom problem. */
551.1.1 by monty at mysql
Added Innobase to source distribution
1830
1831
	ut_ad(!search_latch_locked);
1832
1833
	plan->stored_cursor_rec_processed = FALSE;
1834
	btr_pcur_store_position(&(plan->pcur), &mtr);
1835
1836
	mtr_commit(&mtr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1837
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1838
#ifdef UNIV_SYNC_DEBUG
551.1.1 by monty at mysql
Added Innobase to source distribution
1839
	ut_ad(sync_thread_levels_empty_gen(TRUE));
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1840
#endif /* UNIV_SYNC_DEBUG */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1841
	err = DB_SUCCESS;
1842
	goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
1843
1844
commit_mtr_for_a_while:
1845
	/* Stores the cursor position and commits &mtr; this is used if
1846
	&mtr may contain latches which would break the latching order if
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1847
	&mtr would not be committed and the latches released. */
551.1.1 by monty at mysql
Added Innobase to source distribution
1848
1849
	plan->stored_cursor_rec_processed = TRUE;
1850
1851
	ut_ad(!search_latch_locked);
1852
	btr_pcur_store_position(&(plan->pcur), &mtr);
1853
1854
	mtr_commit(&mtr);
1855
1856
	leaf_contains_updates = FALSE;
1857
	mtr_has_extra_clust_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1858
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1859
#ifdef UNIV_SYNC_DEBUG
551.1.1 by monty at mysql
Added Innobase to source distribution
1860
	ut_ad(sync_thread_levels_empty_gen(TRUE));
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1861
#endif /* UNIV_SYNC_DEBUG */
551.1.1 by monty at mysql
Added Innobase to source distribution
1862
1863
	goto table_loop;
1864
1865
lock_wait_or_error:
1866
	/* See the note at stop_for_a_while: the same holds for this case */
1867
1868
	ut_ad(!btr_pcur_is_before_first_on_page(&(plan->pcur), &mtr)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1869
	      || !node->asc);
551.1.1 by monty at mysql
Added Innobase to source distribution
1870
	ut_ad(!search_latch_locked);
1871
1872
	plan->stored_cursor_rec_processed = FALSE;
1873
	btr_pcur_store_position(&(plan->pcur), &mtr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1874
551.1.1 by monty at mysql
Added Innobase to source distribution
1875
	mtr_commit(&mtr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1876
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1877
#ifdef UNIV_SYNC_DEBUG
551.1.1 by monty at mysql
Added Innobase to source distribution
1878
	ut_ad(sync_thread_levels_empty_gen(TRUE));
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
1879
#endif /* UNIV_SYNC_DEBUG */
551.1.1 by monty at mysql
Added Innobase to source distribution
1880
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1881
func_exit:
1773.330.3 by marko at mysql
InnoDB: Define some macros around GCC's __builtin_expect()
1882
	if (UNIV_LIKELY_NULL(heap)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
1883
		mem_heap_free(heap);
1884
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
1885
	return(err);
1886
}
1887
1888
/**************************************************************************
1889
Performs a select step. This is a high-level function used in SQL execution
1890
graphs. */
1891
1892
que_thr_t*
1893
row_sel_step(
1894
/*=========*/
1895
				/* out: query thread to run next or NULL */
1896
	que_thr_t*	thr)	/* in: query thread */
1897
{
1898
	ulint		i_lock_mode;
1899
	sym_node_t*	table_node;
1900
	sel_node_t*	node;
1901
	ulint		err;
1902
1903
	ut_ad(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1904
551.1.1 by monty at mysql
Added Innobase to source distribution
1905
	node = thr->run_node;
1906
1907
	ut_ad(que_node_get_type(node) == QUE_NODE_SELECT);
1908
1909
	/* If this is a new time this node is executed (or when execution
1910
	resumes after wait for a table intention lock), set intention locks
1911
	on the tables, or assign a read view */
1912
1913
	if (node->into_list && (thr->prev_node == que_node_get_parent(node))) {
1914
1915
		node->state = SEL_NODE_OPEN;
1916
	}
1917
1918
	if (node->state == SEL_NODE_OPEN) {
1919
1920
		/* It may be that the current session has not yet started
1921
		its transaction, or it has been committed: */
1922
1923
		trx_start_if_not_started(thr_get_trx(thr));
1924
1925
		plan_reset_cursor(sel_node_get_nth_plan(node, 0));
1926
1927
		if (node->consistent_read) {
1928
			/* Assign a read view for the query */
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
1929
			node->read_view = trx_assign_read_view(
1930
				thr_get_trx(thr));
551.1.1 by monty at mysql
Added Innobase to source distribution
1931
		} else {
1932
			if (node->set_x_locks) {
1933
				i_lock_mode = LOCK_IX;
1934
			} else {
1935
				i_lock_mode = LOCK_IS;
1936
			}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1937
551.1.1 by monty at mysql
Added Innobase to source distribution
1938
			table_node = node->table_list;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1939
551.1.1 by monty at mysql
Added Innobase to source distribution
1940
			while (table_node) {
1941
				err = lock_table(0, table_node->table,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1942
						 i_lock_mode, thr);
551.1.1 by monty at mysql
Added Innobase to source distribution
1943
				if (err != DB_SUCCESS) {
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1944
					thr_get_trx(thr)->error_state = err;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1945
551.1.1 by monty at mysql
Added Innobase to source distribution
1946
					return(NULL);
1947
				}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1948
551.1.1 by monty at mysql
Added Innobase to source distribution
1949
				table_node = que_node_get_next(table_node);
1950
			}
1951
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1952
551.1.1 by monty at mysql
Added Innobase to source distribution
1953
		/* If this is an explicit cursor, copy stored procedure
1954
		variable values, so that the values cannot change between
1955
		fetches (currently, we copy them also for non-explicit
1956
		cursors) */
1957
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
1958
		if (node->explicit_cursor
1959
		    && UT_LIST_GET_FIRST(node->copy_variables)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
1960
1961
			row_sel_copy_input_variable_vals(node);
1962
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1963
551.1.1 by monty at mysql
Added Innobase to source distribution
1964
		node->state = SEL_NODE_FETCH;
1965
		node->fetch_table = 0;
1966
1967
		if (node->is_aggregate) {
1968
			/* Reset the aggregate total values */
1969
			sel_reset_aggregate_vals(node);
1970
		}
1971
	}
1972
1973
	err = row_sel(node, thr);
1974
1975
	/* NOTE! if queries are parallelized, the following assignment may
1976
	have problems; the assignment should be made only if thr is the
1977
	only top-level thr in the graph: */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1978
551.1.1 by monty at mysql
Added Innobase to source distribution
1979
	thr->graph->last_sel_node = node;
1980
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
1981
	if (err != DB_SUCCESS) {
1982
		thr_get_trx(thr)->error_state = err;
551.1.1 by monty at mysql
Added Innobase to source distribution
1983
1984
		return(NULL);
1985
	}
1986
1987
	return(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
1988
}
551.1.1 by monty at mysql
Added Innobase to source distribution
1989
1990
/**************************************************************************
1991
Performs a fetch for a cursor. */
1992
1993
que_thr_t*
1994
fetch_step(
1995
/*=======*/
1996
				/* out: query thread to run next or NULL */
1997
	que_thr_t*	thr)	/* in: query thread */
1998
{
1999
	sel_node_t*	sel_node;
2000
	fetch_node_t*	node;
2001
2002
	ut_ad(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2003
551.1.1 by monty at mysql
Added Innobase to source distribution
2004
	node = thr->run_node;
2005
	sel_node = node->cursor_def;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2006
551.1.1 by monty at mysql
Added Innobase to source distribution
2007
	ut_ad(que_node_get_type(node) == QUE_NODE_FETCH);
2008
2009
	if (thr->prev_node != que_node_get_parent(node)) {
2010
2011
		if (sel_node->state != SEL_NODE_NO_MORE_ROWS) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2012
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2013
			if (node->into_list) {
2014
				sel_assign_into_var_values(node->into_list,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2015
							   sel_node);
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2016
			} else {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2017
				void* ret = (*node->func->func)(
2018
					sel_node, node->func->arg);
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2019
2020
				if (!ret) {
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2021
					sel_node->state
2022
						= SEL_NODE_NO_MORE_ROWS;
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2023
				}
2024
			}
551.1.1 by monty at mysql
Added Innobase to source distribution
2025
		}
2026
2027
		thr->run_node = que_node_get_parent(node);
2028
2029
		return(thr);
2030
	}
2031
2032
	/* Make the fetch node the parent of the cursor definition for
2033
	the time of the fetch, so that execution knows to return to this
2034
	fetch node after a row has been selected or we know that there is
2035
	no row left */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2036
551.1.1 by monty at mysql
Added Innobase to source distribution
2037
	sel_node->common.parent = node;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2038
551.1.1 by monty at mysql
Added Innobase to source distribution
2039
	if (sel_node->state == SEL_NODE_CLOSED) {
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2040
		fprintf(stderr,
2041
			"InnoDB: Error: fetch called on a closed cursor\n");
551.1.1 by monty at mysql
Added Innobase to source distribution
2042
2181.166.2 by alexi at mysql
Applied innodb-5.1-ss660 snapshot.
2043
		thr_get_trx(thr)->error_state = DB_ERROR;
551.1.1 by monty at mysql
Added Innobase to source distribution
2044
2045
		return(NULL);
2046
	}
2047
2048
	thr->run_node = sel_node;
2049
2050
	return(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2051
}
551.1.1 by monty at mysql
Added Innobase to source distribution
2052
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2053
/********************************************************************
2054
Sample callback function for fetch that prints each row.*/
2055
2056
void*
2057
row_fetch_print(
2058
/*============*/
2059
				/* out: always returns non-NULL */
2060
	void*	row,		/* in:  sel_node_t* */
2061
	void*	user_arg)	/* in:  not used */
2062
{
2063
	sel_node_t*	node = row;
2064
	que_node_t*	exp;
2065
	ulint		i = 0;
2066
2067
	UT_NOT_USED(user_arg);
2068
2069
	fprintf(stderr, "row_fetch_print: row %p\n", row);
2070
2071
	exp = node->select_list;
2072
2073
	while (exp) {
2074
		dfield_t*	dfield = que_node_get_val(exp);
2075
		dtype_t*	type = dfield_get_type(dfield);
2076
2077
		fprintf(stderr, " column %lu:\n", (ulong)i);
2078
2079
		dtype_print(type);
2080
		fprintf(stderr, "\n");
2081
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2082
		if (dfield_get_len(dfield) != UNIV_SQL_NULL) {
2083
			ut_print_buf(stderr, dfield_get_data(dfield),
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2084
				     dfield_get_len(dfield));
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2085
		} else {
2086
			fprintf(stderr, " <NULL>;");
2087
		}
2088
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2089
		fprintf(stderr, "\n");
2090
2091
		exp = que_node_get_next(exp);
2092
		i++;
2093
	}
2094
2095
	return((void*)42);
2096
}
2097
2098
/********************************************************************
2099
Callback function for fetch that stores an unsigned 4 byte integer to the
2100
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
2101
= 4. */
2102
2103
void*
2104
row_fetch_store_uint4(
2105
/*==================*/
2106
				/* out: always returns NULL */
2107
	void*	row,		/* in:  sel_node_t* */
2108
	void*	user_arg)	/* in:  data pointer */
2109
{
2110
	sel_node_t*	node = row;
2111
	ib_uint32_t*	val = user_arg;
2112
	ulint		tmp;
2113
2114
	dfield_t*	dfield = que_node_get_val(node->select_list);
2115
	dtype_t*	type = dfield_get_type(dfield);
2116
	ulint		len = dfield_get_len(dfield);
2117
2118
	ut_a(dtype_get_mtype(type) == DATA_INT);
2119
	ut_a(dtype_get_prtype(type) & DATA_UNSIGNED);
2120
	ut_a(len == 4);
2121
2122
	tmp = mach_read_from_4(dfield_get_data(dfield));
2409.1.43 by monty at mysql
Fixed compiler warnings
2123
	*val = (ib_uint32_t) tmp;
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2124
2125
	return(NULL);
2126
}
2127
551.1.1 by monty at mysql
Added Innobase to source distribution
2128
/***************************************************************
2129
Prints a row in a select result. */
2130
2131
que_thr_t*
2132
row_printf_step(
2133
/*============*/
2134
				/* out: query thread to run next or NULL */
2135
	que_thr_t*	thr)	/* in: query thread */
2136
{
2137
	row_printf_node_t*	node;
2138
	sel_node_t*		sel_node;
2139
	que_node_t*		arg;
2140
2141
	ut_ad(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2142
551.1.1 by monty at mysql
Added Innobase to source distribution
2143
	node = thr->run_node;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2144
551.1.1 by monty at mysql
Added Innobase to source distribution
2145
	sel_node = node->sel_node;
2146
2147
	ut_ad(que_node_get_type(node) == QUE_NODE_ROW_PRINTF);
2148
2149
	if (thr->prev_node == que_node_get_parent(node)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2150
551.1.1 by monty at mysql
Added Innobase to source distribution
2151
		/* Reset the cursor */
2152
		sel_node->state = SEL_NODE_OPEN;
2153
2154
		/* Fetch next row to print */
2155
2156
		thr->run_node = sel_node;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2157
551.1.1 by monty at mysql
Added Innobase to source distribution
2158
		return(thr);
2159
	}
2160
2161
	if (sel_node->state != SEL_NODE_FETCH) {
2162
2163
		ut_ad(sel_node->state == SEL_NODE_NO_MORE_ROWS);
2164
2165
		/* No more rows to print */
2166
2167
		thr->run_node = que_node_get_parent(node);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2168
551.1.1 by monty at mysql
Added Innobase to source distribution
2169
		return(thr);
2170
	}
2171
2172
	arg = sel_node->select_list;
2173
2174
	while (arg) {
2175
		dfield_print_also_hex(que_node_get_val(arg));
2176
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2177
		fputs(" ::: ", stderr);
551.1.1 by monty at mysql
Added Innobase to source distribution
2178
2179
		arg = que_node_get_next(arg);
2180
	}
2181
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2182
	putc('\n', stderr);
551.1.1 by monty at mysql
Added Innobase to source distribution
2183
2184
	/* Fetch next row to print */
2185
2186
	thr->run_node = sel_node;
2187
2188
	return(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2189
}
551.1.1 by monty at mysql
Added Innobase to source distribution
2190
2191
/********************************************************************
1346.236.10 by heikki at mysql
Many files:
2192
Converts a key value stored in MySQL format to an Innobase dtuple. The last
2193
field of the key value may be just a prefix of a fixed length field: hence
2194
the parameter key_len. But currently we do not allow search keys where the
2195
last field is only a prefix of the full key field len and print a warning if
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2196
such appears. A counterpart of this function is
2197
ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
551.1.1 by monty at mysql
Added Innobase to source distribution
2198
2199
void
2200
row_sel_convert_mysql_key_to_innobase(
2201
/*==================================*/
2202
	dtuple_t*	tuple,		/* in: tuple where to build;
2203
					NOTE: we assume that the type info
2204
					in the tuple is already according
2205
					to index! */
2206
	byte*		buf,		/* in: buffer to use in field
2207
					conversions */
1346.236.10 by heikki at mysql
Many files:
2208
	ulint		buf_len,	/* in: buffer length */
551.1.1 by monty at mysql
Added Innobase to source distribution
2209
	dict_index_t*	index,		/* in: index of the key value */
2210
	byte*		key_ptr,	/* in: MySQL key value */
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2211
	ulint		key_len,	/* in: MySQL key value length */
2212
	trx_t*		trx)		/* in: transaction */
551.1.1 by monty at mysql
Added Innobase to source distribution
2213
{
1346.236.10 by heikki at mysql
Many files:
2214
	byte*		original_buf	= buf;
1572.1.5 by heikki at mysql
Many files:
2215
	byte*		original_key_ptr = key_ptr;
1346.236.10 by heikki at mysql
Many files:
2216
	dict_field_t*	field;
551.1.1 by monty at mysql
Added Innobase to source distribution
2217
	dfield_t*	dfield;
1346.236.10 by heikki at mysql
Many files:
2218
	ulint		data_offset;
2219
	ulint		data_len;
2220
	ulint		data_field_len;
2221
	ibool		is_null;
551.1.1 by monty at mysql
Added Innobase to source distribution
2222
	byte*		key_end;
2223
	ulint		n_fields = 0;
1346.236.10 by heikki at mysql
Many files:
2224
	ulint		type;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2225
1346.236.10 by heikki at mysql
Many files:
2226
	/* For documentation of the key value storage format in MySQL, see
2227
	ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
571.1.1 by heikki at mysql
ut0ut.c Fixes for 64-bit Linux, bug fixes, compiler warning fixes
2228
551.1.1 by monty at mysql
Added Innobase to source distribution
2229
	key_end = key_ptr + key_len;
2230
2231
	/* Permit us to access any field in the tuple (ULINT_MAX): */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2232
551.1.1 by monty at mysql
Added Innobase to source distribution
2233
	dtuple_set_n_fields(tuple, ULINT_MAX);
2234
2235
	dfield = dtuple_get_nth_field(tuple, 0);
1346.236.10 by heikki at mysql
Many files:
2236
	field = dict_index_get_nth_field(index, 0);
551.1.1 by monty at mysql
Added Innobase to source distribution
2237
2238
	if (dfield_get_type(dfield)->mtype == DATA_SYS) {
1346.236.10 by heikki at mysql
Many files:
2239
		/* A special case: we are looking for a position in the
2240
		generated clustered index which InnoDB automatically added
2241
		to a table with no primary key: the first and the only
2242
		ordering column is ROW_ID which InnoDB stored to the key_ptr
2243
		buffer. */
551.1.1 by monty at mysql
Added Innobase to source distribution
2244
2245
		ut_a(key_len == DATA_ROW_ID_LEN);
2246
2247
		dfield_set_data(dfield, key_ptr, DATA_ROW_ID_LEN);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2248
551.1.1 by monty at mysql
Added Innobase to source distribution
2249
		dtuple_set_n_fields(tuple, 1);
2250
2251
		return;
2252
	}
2253
1346.236.10 by heikki at mysql
Many files:
2254
	while (key_ptr < key_end) {
2255
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2256
		ut_a(field->col->mtype == dfield_get_type(dfield)->mtype);
1346.236.10 by heikki at mysql
Many files:
2257
2258
		data_offset = 0;
2259
		is_null = FALSE;
551.1.1 by monty at mysql
Added Innobase to source distribution
2260
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2261
		if (!(dfield_get_type(dfield)->prtype & DATA_NOT_NULL)) {
2262
			/* The first byte in the field tells if this is
2263
			an SQL NULL value */
2264
1346.236.10 by heikki at mysql
Many files:
2265
			data_offset = 1;
551.1.1 by monty at mysql
Added Innobase to source distribution
2266
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2267
			if (*key_ptr != 0) {
2268
				dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
551.1.1 by monty at mysql
Added Innobase to source distribution
2269
1346.236.10 by heikki at mysql
Many files:
2270
				is_null = TRUE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2271
			}
2272
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
2273
1346.236.10 by heikki at mysql
Many files:
2274
		type = dfield_get_type(dfield)->mtype;
2275
2276
		/* Calculate data length and data field total length */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2277
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2278
		if (type == DATA_BLOB) {
2279
			/* The key field is a column prefix of a BLOB or
2280
			TEXT */
1346.236.10 by heikki at mysql
Many files:
2281
2282
			ut_a(field->prefix_len > 0);
2283
2284
			/* MySQL stores the actual data length to the first 2
2285
			bytes after the optional SQL NULL marker byte. The
1616.1027.1 by heikki at mysql
row0sel.c, row0row.c:
2286
			storage format is little-endian, that is, the most
2287
			significant byte at a higher address. In UTF-8, MySQL
2288
			seems to reserve field->prefix_len bytes for
2289
			storing this field in the key value buffer, even
2290
			though the actual value only takes data_len bytes
2291
			from the start. */
2292
2293
			data_len = key_ptr[data_offset]
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2294
				+ 256 * key_ptr[data_offset + 1];
1346.236.10 by heikki at mysql
Many files:
2295
			data_field_len = data_offset + 2 + field->prefix_len;
1773.8.34 by jan at mysql
Fixed a core dump bug after VARCHAR push in InnoDB.
2296
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2297
			data_offset += 2;
1773.8.30 by heikki at mysql
Many files:
2298
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2299
			/* Now that we know the length, we store the column
1773.8.30 by heikki at mysql
Many files:
2300
			value like it would be a fixed char field */
2301
1346.236.10 by heikki at mysql
Many files:
2302
		} else if (field->prefix_len > 0) {
1616.1027.1 by heikki at mysql
row0sel.c, row0row.c:
2303
			/* Looks like MySQL pads unused end bytes in the
2304
			prefix with space. Therefore, also in UTF-8, it is ok
2305
			to compare with a prefix containing full prefix_len
2306
			bytes, and no need to take at most prefix_len / 3
2307
			UTF-8 characters from the start.
2308
			If the prefix is used as the upper end of a LIKE
2309
			'abc%' query, then MySQL pads the end with chars
2310
			0xff. TODO: in that case does it any harm to compare
2311
			with the full prefix_len bytes. How do characters
2312
			0xff in UTF-8 behave? */
2313
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2314
			data_len = field->prefix_len;
1346.236.10 by heikki at mysql
Many files:
2315
			data_field_len = data_offset + data_len;
2316
		} else {
2317
			data_len = dfield_get_type(dfield)->len;
2318
			data_field_len = data_offset + data_len;
2319
		}
2320
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2321
		if (dtype_get_mysql_type(dfield_get_type(dfield))
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2322
		    == DATA_MYSQL_TRUE_VARCHAR
2323
		    && dfield_get_type(dfield)->mtype != DATA_INT) {
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2324
			/* In a MySQL key value format, a true VARCHAR is
2325
			always preceded by 2 bytes of a length field.
2326
			dfield_get_type(dfield)->len returns the maximum
2327
			'payload' len in bytes. That does not include the
1773.121.2 by heikki at mysql
ha_innodb.cc, row0sel.c:
2328
			2 bytes that tell the actual data length.
2329
2330
			We added the check != DATA_INT to make sure we do
2331
			not treat MySQL ENUM or SET as a true VARCHAR! */
1773.8.37 by heikki at mysql
data0type.h, row0sel.c:
2332
2333
			data_len += 2;
2334
			data_field_len += 2;
2335
		}
2336
1346.236.10 by heikki at mysql
Many files:
2337
		/* Storing may use at most data_len bytes of buf */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2338
1346.236.10 by heikki at mysql
Many files:
2339
		if (!is_null) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2340
			row_mysql_store_col_in_innobase_format(
2341
				dfield, buf,
2342
				FALSE, /* MySQL key value format col */
2343
				key_ptr + data_offset, data_len,
2344
				dict_table_is_comp(index->table));
1346.236.10 by heikki at mysql
Many files:
2345
			buf += data_len;
2346
		}
2347
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2348
		key_ptr += data_field_len;
551.1.1 by monty at mysql
Added Innobase to source distribution
2349
2350
		if (key_ptr > key_end) {
1346.236.10 by heikki at mysql
Many files:
2351
			/* The last field in key was not a complete key field
2352
			but a prefix of it.
1346.118.1 by heikki at mysql
row0sel.c:
2353
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2354
			Print a warning about this! HA_READ_PREFIX_LAST does
1346.236.10 by heikki at mysql
Many files:
2355
			not currently work in InnoDB with partial-field key
2356
			value prefixes. Since MySQL currently uses a padding
2357
			trick to calculate LIKE 'abc%' type queries there
2358
			should never be partial-field prefixes in searches. */
1346.118.1 by heikki at mysql
row0sel.c:
2359
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2360
			ut_print_timestamp(stderr);
2361
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2362
			fputs("  InnoDB: Warning: using a partial-field"
2363
			      " key prefix in search.\n"
2364
			      "InnoDB: ", stderr);
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2365
			dict_index_name_print(stderr, trx, index);
2366
			fprintf(stderr, ". Last data field length %lu bytes,\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2367
				"InnoDB: key ptr now exceeds"
2368
				" key end by %lu bytes.\n"
2369
				"InnoDB: Key value in the MySQL format:\n",
2370
				(ulong) data_field_len,
2371
				(ulong) (key_ptr - key_end));
1572.1.5 by heikki at mysql
Many files:
2372
			fflush(stderr);
1616.318.2 by monty at mishka
After merge fixes
2373
			ut_print_buf(stderr, original_key_ptr, key_len);
1572.1.5 by heikki at mysql
Many files:
2374
			fprintf(stderr, "\n");
551.1.1 by monty at mysql
Added Innobase to source distribution
2375
1346.236.10 by heikki at mysql
Many files:
2376
			if (!is_null) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2377
				dfield->len -= (ulint)(key_ptr - key_end);
1346.236.10 by heikki at mysql
Many files:
2378
			}
551.1.1 by monty at mysql
Added Innobase to source distribution
2379
		}
2380
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2381
		n_fields++;
2382
		field++;
551.1.1 by monty at mysql
Added Innobase to source distribution
2383
		dfield++;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2384
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
2385
1346.236.10 by heikki at mysql
Many files:
2386
	ut_a(buf <= original_buf + buf_len);
2387
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2388
	/* We set the length of tuple to n_fields: we assume that the memory
1346.236.10 by heikki at mysql
Many files:
2389
	area allocated for it is big enough (usually bigger than n_fields). */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2390
2391
	dtuple_set_n_fields(tuple, n_fields);
551.1.1 by monty at mysql
Added Innobase to source distribution
2392
}
2393
2394
/******************************************************************
2395
Stores the row id to the prebuilt struct. */
1346.236.10 by heikki at mysql
Many files:
2396
static
551.1.1 by monty at mysql
Added Innobase to source distribution
2397
void
2398
row_sel_store_row_id_to_prebuilt(
2399
/*=============================*/
2400
	row_prebuilt_t*	prebuilt,	/* in: prebuilt */
2401
	rec_t*		index_rec,	/* in: record */
1659.1.48 by marko at mysql
Many files:
2402
	dict_index_t*	index,		/* in: index of the record */
2403
	const ulint*	offsets)	/* in: rec_get_offsets
2404
					(index_rec, index) */
551.1.1 by monty at mysql
Added Innobase to source distribution
2405
{
2406
	byte*	data;
2407
	ulint	len;
1659.1.48 by marko at mysql
Many files:
2408
2409
	ut_ad(rec_offs_validate(index_rec, index, offsets));
2410
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2411
	data = rec_get_nth_field(
2412
		index_rec, offsets,
2413
		dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
551.1.1 by monty at mysql
Added Innobase to source distribution
2414
1346.236.10 by heikki at mysql
Many files:
2415
	if (len != DATA_ROW_ID_LEN) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2416
		fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2417
			"InnoDB: Error: Row id field is"
2418
			" wrong length %lu in ", (ulong) len);
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2419
		dict_index_name_print(stderr, prebuilt->trx, index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2420
		fprintf(stderr, "\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2421
			"InnoDB: Field number %lu, record:\n",
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2422
			(ulong) dict_index_get_sys_col_pos(index,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2423
							   DATA_ROW_ID));
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2424
		rec_print_new(stderr, index_rec, offsets);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2425
		putc('\n', stderr);
1346.556.1 by marko at mysql
InnoDB: Replace ut_a(0) with ut_error
2426
		ut_error;
1346.236.10 by heikki at mysql
Many files:
2427
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
2428
2429
	ut_memcpy(prebuilt->row_id, data, len);
2430
}
2431
2432
/******************************************************************
1773.8.30 by heikki at mysql
Many files:
2433
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
2434
function is row_mysql_store_col_in_innobase_format() in row0mysql.c. */
2435
static
551.1.1 by monty at mysql
Added Innobase to source distribution
2436
void
2437
row_sel_field_store_in_mysql_format(
2438
/*================================*/
2439
	byte*	dest,	/* in/out: buffer where to store; NOTE that BLOBs
2440
			are not in themselves stored here: the caller must
2441
			allocate and copy the BLOB into buffer before, and pass
2442
			the pointer to the BLOB in 'data' */
1700.245.2 by marko at mysql
After review fixes (Bug #5682)
2443
	const mysql_row_templ_t* templ,	/* in: MySQL column template.
2444
			Its following fields are referenced:
2445
			type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */
551.1.1 by monty at mysql
Added Innobase to source distribution
2446
	byte*	data,	/* in: data to store */
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2447
	ulint	len)	/* in: length of the data */
551.1.1 by monty at mysql
Added Innobase to source distribution
2448
{
2449
	byte*	ptr;
1773.8.30 by heikki at mysql
Many files:
2450
	byte*	field_end;
2451
	byte*	pad_ptr;
551.1.1 by monty at mysql
Added Innobase to source distribution
2452
2453
	ut_ad(len != UNIV_SQL_NULL);
2454
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2455
	if (templ->type == DATA_INT) {
551.1.1 by monty at mysql
Added Innobase to source distribution
2456
		/* Convert integer data from Innobase to a little-endian
2457
		format, sign bit restored to normal */
2458
2459
		ptr = dest + len;
2460
2461
		for (;;) {
2462
			ptr--;
2463
			*ptr = *data;
2464
			if (ptr == dest) {
2465
				break;
2466
			}
2467
			data++;
2468
		}
2469
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2470
		if (!templ->is_unsigned) {
571.1.1 by heikki at mysql
ut0ut.c Fixes for 64-bit Linux, bug fixes, compiler warning fixes
2471
			dest[len - 1] = (byte) (dest[len - 1] ^ 128);
551.1.1 by monty at mysql
Added Innobase to source distribution
2472
		}
2473
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2474
		ut_ad(templ->mysql_col_len == len);
1773.8.30 by heikki at mysql
Many files:
2475
	} else if (templ->type == DATA_VARCHAR
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2476
		   || templ->type == DATA_VARMYSQL
1773.8.30 by heikki at mysql
Many files:
2477
		   || templ->type == DATA_BINARY) {
2478
2479
		field_end = dest + templ->mysql_col_len;
2480
2481
		if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
2482
			/* This is a >= 5.0.3 type true VARCHAR. Store the
2483
			length of the data to the first byte or the first
2484
			two bytes of dest. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2485
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2486
			dest = row_mysql_store_true_var_len(
2487
				dest, len, templ->mysql_length_bytes);
1773.8.30 by heikki at mysql
Many files:
2488
		}
2489
2490
		/* Copy the actual data */
551.1.1 by monty at mysql
Added Innobase to source distribution
2491
		ut_memcpy(dest, data, len);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2492
1773.8.30 by heikki at mysql
Many files:
2493
		/* Pad with trailing spaces. We pad with spaces also the
2494
		unused end of a >= 5.0.3 true VARCHAR column, just in case
2495
		MySQL expects its contents to be deterministic. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2496
1773.8.30 by heikki at mysql
Many files:
2497
		pad_ptr = dest + len;
2498
2499
		ut_ad(templ->mbminlen <= templ->mbmaxlen);
2500
2501
		/* We handle UCS2 charset strings differently. */
2502
		if (templ->mbminlen == 2) {
2503
			/* A space char is two bytes, 0x0020 in UCS2 */
2504
2505
			if (len & 1) {
2506
				/* A 0x20 has been stripped from the column.
2507
				Pad it back. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2508
1773.8.30 by heikki at mysql
Many files:
2509
				if (pad_ptr < field_end) {
2510
					*pad_ptr = 0x20;
2511
					pad_ptr++;
2512
				}
2513
			}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2514
1773.8.30 by heikki at mysql
Many files:
2515
			/* Pad the rest of the string with 0x0020 */
2516
2517
			while (pad_ptr < field_end) {
2518
				*pad_ptr = 0x00;
2519
				pad_ptr++;
2520
				*pad_ptr = 0x20;
2521
				pad_ptr++;
2522
			}
2523
		} else {
2524
			ut_ad(templ->mbminlen == 1);
2525
			/* space=0x20 */
2526
2527
			memset(pad_ptr, 0x20, field_end - pad_ptr);
2528
		}
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2529
	} else if (templ->type == DATA_BLOB) {
551.1.1 by monty at mysql
Added Innobase to source distribution
2530
		/* Store a pointer to the BLOB buffer to dest: the BLOB was
2531
		already copied to the buffer in row_sel_store_mysql_rec */
2532
1773.8.30 by heikki at mysql
Many files:
2533
		row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2534
					 len);
1700.245.2 by marko at mysql
After review fixes (Bug #5682)
2535
	} else if (templ->type == DATA_MYSQL) {
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2536
		memcpy(dest, data, len);
2537
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2538
		ut_ad(templ->mysql_col_len >= len);
2539
		ut_ad(templ->mbmaxlen >= templ->mbminlen);
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2540
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2541
		ut_ad(templ->mbmaxlen > templ->mbminlen
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2542
		      || templ->mysql_col_len == len);
1773.124.5 by marko at mysql
InnoDB: Disable an assertion that fails on old data due to Bug #9526
2543
		/* The following assertion would fail for old tables
2544
		containing UTF-8 ENUM columns due to Bug #9526. */
2545
		ut_ad(!templ->mbmaxlen
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2546
		      || !(templ->mysql_col_len % templ->mbmaxlen));
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2547
		ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2548
2549
		if (templ->mbminlen != templ->mbmaxlen) {
1773.8.30 by heikki at mysql
Many files:
2550
			/* Pad with spaces. This undoes the stripping
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2551
			done in row0mysql.ic, function
2552
			row_mysql_store_col_in_innobase_format(). */
1773.8.30 by heikki at mysql
Many files:
2553
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
2554
			memset(dest + len, 0x20, templ->mysql_col_len - len);
2555
		}
1700.245.2 by marko at mysql
After review fixes (Bug #5682)
2556
	} else {
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
2557
		ut_ad(templ->type == DATA_CHAR
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2558
		      || templ->type == DATA_FIXBINARY
2559
		      /*|| templ->type == DATA_SYS_CHILD
2560
		      || templ->type == DATA_SYS*/
2561
		      || templ->type == DATA_FLOAT
2562
		      || templ->type == DATA_DOUBLE
2563
		      || templ->type == DATA_DECIMAL);
1700.245.2 by marko at mysql
After review fixes (Bug #5682)
2564
		ut_ad(templ->mysql_col_len == len);
1773.8.30 by heikki at mysql
Many files:
2565
1700.245.2 by marko at mysql
After review fixes (Bug #5682)
2566
		memcpy(dest, data, len);
551.1.1 by monty at mysql
Added Innobase to source distribution
2567
	}
2568
}
2569
2570
/******************************************************************
2571
Convert a row in the Innobase format to a row in the MySQL format.
2572
Note that the template in prebuilt may advise us to copy only a few
2573
columns to mysql_rec, other columns are left blank. All columns may not
2574
be needed in the query. */
2575
static
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
2576
ibool
551.1.1 by monty at mysql
Added Innobase to source distribution
2577
row_sel_store_mysql_rec(
2578
/*====================*/
1572.1.5 by heikki at mysql
Many files:
2579
					/* out: TRUE if success, FALSE if
2580
					could not allocate memory for a BLOB
2581
					(though we may also assert in that
2582
					case) */
551.1.1 by monty at mysql
Added Innobase to source distribution
2583
	byte*		mysql_rec,	/* out: row in the MySQL format */
2584
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
1659.1.48 by marko at mysql
Many files:
2585
	rec_t*		rec,		/* in: Innobase record in the index
551.1.1 by monty at mysql
Added Innobase to source distribution
2586
					which was described in prebuilt's
2587
					template */
1659.1.48 by marko at mysql
Many files:
2588
	const ulint*	offsets)	/* in: array returned by
2589
					rec_get_offsets() */
551.1.1 by monty at mysql
Added Innobase to source distribution
2590
{
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2591
	mysql_row_templ_t*	templ;
2592
	mem_heap_t*		extern_field_heap	= NULL;
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2593
	mem_heap_t*		heap;
551.1.1 by monty at mysql
Added Innobase to source distribution
2594
	byte*			data;
2595
	ulint			len;
2596
	ulint			i;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2597
551.1.1 by monty at mysql
Added Innobase to source distribution
2598
	ut_ad(prebuilt->mysql_template);
1659.1.48 by marko at mysql
Many files:
2599
	ut_ad(rec_offs_validate(rec, NULL, offsets));
2600
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2601
	if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
2602
		mem_heap_free(prebuilt->blob_heap);
2603
		prebuilt->blob_heap = NULL;
2604
	}
2605
2606
	for (i = 0; i < prebuilt->n_template; i++) {
2607
2608
		templ = prebuilt->mysql_template + i;
2609
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2610
		if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2611
						      templ->rec_field_no))) {
676.177.36 by heikki at mysql
row0mysql.c:
2612
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2613
			/* Copy an externally stored field to the temporary
2614
			heap */
2615
676.177.36 by heikki at mysql
row0mysql.c:
2616
			ut_a(!prebuilt->trx->has_search_latch);
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2617
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2618
			if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
2619
				if (prebuilt->blob_heap == NULL) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2620
					prebuilt->blob_heap = mem_heap_create(
2621
						UNIV_PAGE_SIZE);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2622
				}
2623
2624
				heap = prebuilt->blob_heap;
2625
			} else {
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2626
				extern_field_heap
2627
					= mem_heap_create(UNIV_PAGE_SIZE);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2628
2629
				heap = extern_field_heap;
2630
			}
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2631
1572.1.5 by heikki at mysql
Many files:
2632
			/* NOTE: if we are retrieving a big BLOB, we may
2633
			already run out of memory in the next call, which
2634
			causes an assert */
2635
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2636
			data = btr_rec_copy_externally_stored_field(
2637
				rec, offsets, templ->rec_field_no,
2638
				&len, heap);
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2639
2640
			ut_a(len != UNIV_SQL_NULL);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
2641
		} else {
2642
			/* Field is stored in the row. */
2643
2644
			data = rec_get_nth_field(rec, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2645
						 templ->rec_field_no, &len);
2542.47.1 by df at erinye
apply snapshot innodb-5.1-ss2387
2646
2647
			if (UNIV_UNLIKELY(templ->type == DATA_BLOB)
2648
			    && len != UNIV_SQL_NULL) {
2649
2650
				/* It is a BLOB field locally stored in the
2651
				InnoDB record: we MUST copy its contents to
2652
				prebuilt->blob_heap here because later code
2653
				assumes all BLOB values have been copied to a
2654
				safe place. */
2655
2656
				if (prebuilt->blob_heap == NULL) {
2657
					prebuilt->blob_heap = mem_heap_create(
2658
						UNIV_PAGE_SIZE);
2659
				}
2660
2661
				data = memcpy(mem_heap_alloc(
2662
						prebuilt->blob_heap, len),
2663
						data, len);
2664
			}
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2665
		}
2666
551.1.1 by monty at mysql
Added Innobase to source distribution
2667
		if (len != UNIV_SQL_NULL) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2668
			row_sel_field_store_in_mysql_format(
2669
				mysql_rec + templ->mysql_col_offset,
2670
				templ, data, len);
1616.1383.2 by marko at mysql
InnoDB: Fixed bugs in the padding and trimming of trailing spaces
2671
1572.1.5 by heikki at mysql
Many files:
2672
			/* Cleanup */
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
2673
			if (extern_field_heap) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2674
				mem_heap_free(extern_field_heap);
676.106.1 by heikki at mysql
row0sel.c Fix a memory freeing bug when a row which contains an externally stored long field in the middle of the row is fetched in a SELECT
2675
				extern_field_heap = NULL;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2676
			}
2677
1546.69.9 by serg at serg
making InnoDB to return the row exactly the same (bytewise) as it was written to it
2678
			if (templ->mysql_null_bit_mask) {
1572.1.5 by heikki at mysql
Many files:
2679
				/* It is a nullable column with a non-NULL
2680
				value */
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2681
				mysql_rec[templ->mysql_null_byte_offset]
2682
					&= ~(byte) templ->mysql_null_bit_mask;
1546.69.9 by serg at serg
making InnoDB to return the row exactly the same (bytewise) as it was written to it
2683
			}
551.1.1 by monty at mysql
Added Innobase to source distribution
2684
		} else {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2685
			/* MySQL seems to assume the field for an SQL NULL
2686
			value is set to zero or space. Not taking this into
1572.1.5 by heikki at mysql
Many files:
2687
			account caused seg faults with NULL BLOB fields, and
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2688
			bug number 154 in the MySQL bug database: GROUP BY
2689
			and DISTINCT could treat NULL values inequal. */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2690
			int	pad_char;
676.177.36 by heikki at mysql
row0mysql.c:
2691
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2692
			mysql_rec[templ->mysql_null_byte_offset]
2693
				|= (byte) templ->mysql_null_bit_mask;
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2694
			switch (templ->type) {
2695
			case DATA_VARCHAR:
1810.393.3 by marko at mysql
row_sel_store_mysql_rec(): Convert NULL true VARCHAR columns
2696
			case DATA_BINARY:
2697
			case DATA_VARMYSQL:
2698
				if (templ->mysql_type
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2699
				    == DATA_MYSQL_TRUE_VARCHAR) {
1810.393.3 by marko at mysql
row_sel_store_mysql_rec(): Convert NULL true VARCHAR columns
2700
					/* This is a >= 5.0.3 type
2701
					true VARCHAR.  Zero the field. */
2702
					pad_char = 0x00;
2703
					break;
2704
				}
2705
				/* Fall through */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2706
			case DATA_CHAR:
2707
			case DATA_FIXBINARY:
2708
			case DATA_MYSQL:
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2709
				/* MySQL pads all string types (except
1810.393.4 by marko at mysql
row0sel.c:
2710
				BLOB, TEXT and true VARCHAR) with space. */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2711
				if (UNIV_UNLIKELY(templ->mbminlen == 2)) {
2712
					/* Treat UCS2 as a special case. */
2713
					data = mysql_rec
2714
						+ templ->mysql_col_offset;
2715
					len = templ->mysql_col_len;
2716
					/* There are two UCS2 bytes per char,
2717
					so the length has to be even. */
2718
					ut_a(!(len & 1));
2719
					/* Pad with 0x0020. */
2720
					while (len) {
2721
						*data++ = 0x00;
2722
						*data++ = 0x20;
2723
						len -= 2;
2724
					}
2725
					continue;
2726
				}
2727
				pad_char = 0x20;
2728
				break;
2729
			default:
2730
				pad_char = 0x00;
2731
				break;
1572.1.5 by heikki at mysql
Many files:
2732
			}
2733
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
2734
			ut_ad(!pad_char || templ->mbminlen == 1);
2735
			memset(mysql_rec + templ->mysql_col_offset,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2736
			       pad_char, templ->mysql_col_len);
551.1.1 by monty at mysql
Added Innobase to source distribution
2737
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2738
	}
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
2739
2740
	return(TRUE);
551.1.1 by monty at mysql
Added Innobase to source distribution
2741
}
2742
2743
/*************************************************************************
2744
Builds a previous version of a clustered index record for a consistent read */
2745
static
2746
ulint
2747
row_sel_build_prev_vers_for_mysql(
2748
/*==============================*/
2749
					/* out: DB_SUCCESS or error code */
2750
	read_view_t*	read_view,	/* in: read view */
2751
	dict_index_t*	clust_index,	/* in: clustered index */
2752
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
2753
	rec_t*		rec,		/* in: record in a clustered index */
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
2754
	ulint**		offsets,	/* in/out: offsets returned by
2755
					rec_get_offsets(rec, clust_index) */
2756
	mem_heap_t**	offset_heap,	/* in/out: memory heap from which
2757
					the offsets are allocated */
551.1.1 by monty at mysql
Added Innobase to source distribution
2758
	rec_t**		old_vers,	/* out: old version, or NULL if the
2759
					record does not exist in the view:
2760
					i.e., it was freshly inserted
2761
					afterwards */
2762
	mtr_t*		mtr)		/* in: mtr */
2763
{
2764
	ulint	err;
2765
2766
	if (prebuilt->old_vers_heap) {
2767
		mem_heap_empty(prebuilt->old_vers_heap);
2768
	} else {
2769
		prebuilt->old_vers_heap = mem_heap_create(200);
2770
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2771
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2772
	err = row_vers_build_for_consistent_read(
2773
		rec, mtr, clust_index, offsets, read_view, offset_heap,
2774
		prebuilt->old_vers_heap, old_vers);
551.1.1 by monty at mysql
Added Innobase to source distribution
2775
	return(err);
2776
}
2777
2778
/*************************************************************************
2779
Retrieves the clustered index record corresponding to a record in a
2780
non-clustered index. Does the necessary locking. Used in the MySQL
2781
interface. */
2782
static
2783
ulint
2784
row_sel_get_clust_rec_for_mysql(
2785
/*============================*/
2786
				/* out: DB_SUCCESS or error code */
2787
	row_prebuilt_t*	prebuilt,/* in: prebuilt struct in the handle */
2788
	dict_index_t*	sec_index,/* in: secondary index where rec resides */
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
2789
	rec_t*		rec,	/* in: record in a non-clustered index; if
2790
				this is a locking read, then rec is not
2791
				allowed to be delete-marked, and that would
2792
				not make sense either */
551.1.1 by monty at mysql
Added Innobase to source distribution
2793
	que_thr_t*	thr,	/* in: query thread */
2794
	rec_t**		out_rec,/* out: clustered record or an old version of
2795
				it, NULL if the old version did not exist
2796
				in the read view, i.e., it was a fresh
2797
				inserted version */
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
2798
	ulint**		offsets,/* out: offsets returned by
2799
				rec_get_offsets(out_rec, clust_index) */
2800
	mem_heap_t**	offset_heap,/* in/out: memory heap from which
2801
				the offsets are allocated */
551.1.1 by monty at mysql
Added Innobase to source distribution
2802
	mtr_t*		mtr)	/* in: mtr used to get access to the
2803
				non-clustered record; the same mtr is used to
2804
				access the clustered index */
2805
{
2806
	dict_index_t*	clust_index;
2807
	rec_t*		clust_rec;
2808
	rec_t*		old_vers;
2809
	ulint		err;
2810
	trx_t*		trx;
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2811
551.1.1 by monty at mysql
Added Innobase to source distribution
2812
	*out_rec = NULL;
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2813
	trx = thr_get_trx(thr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2814
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2815
	row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec, trx);
551.1.1 by monty at mysql
Added Innobase to source distribution
2816
2817
	clust_index = dict_table_get_first_index(sec_index->table);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2818
551.1.1 by monty at mysql
Added Innobase to source distribution
2819
	btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2820
				   PAGE_CUR_LE, BTR_SEARCH_LEAF,
2821
				   prebuilt->clust_pcur, 0, mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
2822
2823
	clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
2824
1616.1799.8 by heikki at mysql
row0sel.c, btr0pcur.c, btr0pcur.ic, btr0pcur.h:
2825
	prebuilt->clust_pcur->trx_if_known = trx;
2826
1346.226.33 by heikki at mysql
row0sel.c, row0ins.c:
2827
	/* Note: only if the search ends up on a non-infimum record is the
2828
	low_match value the real match to the search tuple */
2829
2830
	if (!page_rec_is_user_rec(clust_rec)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2831
	    || btr_pcur_get_low_match(prebuilt->clust_pcur)
2832
	    < dict_index_get_n_unique(clust_index)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2833
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
2834
		/* In a rare case it is possible that no clust rec is found
2835
		for a delete-marked secondary index record: if in row0umod.c
2836
		in row_undo_mod_remove_clust_low() we have already removed
2837
		the clust rec, while purge is still cleaning and removing
2838
		secondary index records associated with earlier versions of
2839
		the clustered index record. In that case we know that the
2840
		clustered index record did not exist in the read view of
2841
		trx. */
2842
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2843
		if (!rec_get_deleted_flag(rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2844
					  dict_table_is_comp(sec_index->table))
2845
		    || prebuilt->select_lock_type != LOCK_NONE) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2846
			ut_print_timestamp(stderr);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2847
			fputs("  InnoDB: error clustered record"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2848
			      " for sec rec not found\n"
2849
			      "InnoDB: ", stderr);
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
2850
			dict_index_name_print(stderr, trx, sec_index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2851
			fputs("\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2852
			      "InnoDB: sec index record ", stderr);
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2853
			rec_print(stderr, rec, sec_index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2854
			fputs("\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2855
			      "InnoDB: clust index record ", stderr);
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2856
			rec_print(stderr, clust_rec, clust_index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2857
			putc('\n', stderr);
1810.457.1 by osku at 127
InnoDB: Print more than 300 characters of queries in various error conditions,
2858
			trx_print(stderr, trx, 600);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
2859
2860
			fputs("\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2861
			      "InnoDB: Submit a detailed bug report"
2862
			      " to http://bugs.mysql.com\n", stderr);
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
2863
		}
1346.8.10 by heikki at mysql
Many files:
2864
2865
		clust_rec = NULL;
2866
2867
		goto func_exit;
2868
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
2869
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
2870
	*offsets = rec_get_offsets(clust_rec, clust_index, *offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2871
				   ULINT_UNDEFINED, offset_heap);
1659.1.48 by marko at mysql
Many files:
2872
551.1.1 by monty at mysql
Added Innobase to source distribution
2873
	if (prebuilt->select_lock_type != LOCK_NONE) {
1346.8.10 by heikki at mysql
Many files:
2874
		/* Try to place a lock on the index record; we are searching
2875
		the clust rec with a unique condition, hence
2876
		we set a LOCK_REC_NOT_GAP type lock */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2877
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2878
		err = lock_clust_rec_read_check_and_lock(
2879
			0, clust_rec, clust_index, *offsets,
2880
			prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
551.1.1 by monty at mysql
Added Innobase to source distribution
2881
		if (err != DB_SUCCESS) {
2882
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2883
			goto err_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
2884
		}
2885
	} else {
2886
		/* This is a non-locking consistent read: if necessary, fetch
2887
		a previous version of the record */
2888
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
2889
		old_vers = NULL;
1346.8.10 by heikki at mysql
Many files:
2890
2891
		/* If the isolation level allows reading of uncommitted data,
2892
		then we never look for an earlier version */
2893
2894
		if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2895
		    && !lock_clust_rec_cons_read_sees(
2896
			    clust_rec, clust_index, *offsets,
2897
			    trx->read_view)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2898
1810.590.10 by heikki at mysql
row0sel.c:
2899
			/* The following call returns 'offsets' associated with
2900
			'old_vers' */
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2901
			err = row_sel_build_prev_vers_for_mysql(
2902
				trx->read_view, clust_index, prebuilt,
2903
				clust_rec, offsets, offset_heap, &old_vers,
2904
				mtr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2905
551.1.1 by monty at mysql
Added Innobase to source distribution
2906
			if (err != DB_SUCCESS) {
2907
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2908
				goto err_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
2909
			}
2910
2911
			clust_rec = old_vers;
2912
		}
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
2913
2914
		/* If we had to go to an earlier version of row or the
2915
		secondary index record is delete marked, then it may be that
2916
		the secondary index record corresponding to clust_rec
2917
		(or old_vers) is not rec; in that case we must ignore
2918
		such row because in our snapshot rec would not have existed.
2919
		Remember that from rec we cannot see directly which transaction
676.169.18 by heikki at mysql
Many files:
2920
		id corresponds to it: we have to go to the clustered index
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
2921
		record. A query where we want to fetch all rows where
2922
		the secondary index value is in some interval would return
2923
		a wrong result if we would not drop rows which we come to
2924
		visit through secondary index records that would not really
2925
		exist in our snapshot. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2926
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2927
		if (clust_rec && (old_vers || rec_get_deleted_flag(
2928
					  rec,
2929
					  dict_table_is_comp(
2930
						  sec_index->table)))
2931
		    && !row_sel_sec_rec_is_for_clust_rec(
2932
			    rec, sec_index, clust_rec, clust_index)) {
676.1.58 by heikki at mysql
row0sel.c Fix a bug in multiversioned reads through a secondary index
2933
			clust_rec = NULL;
676.169.18 by heikki at mysql
Many files:
2934
		} else {
2935
#ifdef UNIV_SEARCH_DEBUG
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
2936
			ut_a(clust_rec == NULL
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
2937
			     || row_sel_sec_rec_is_for_clust_rec(
2938
				     rec, sec_index, clust_rec, clust_index));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2939
#endif
676.50.27 by heikki at mysql
row0sel.c Fix a bug in consistent read through a secondary index
2940
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
2941
	}
2942
1346.8.10 by heikki at mysql
Many files:
2943
func_exit:
551.1.1 by monty at mysql
Added Innobase to source distribution
2944
	*out_rec = clust_rec;
2945
2946
	if (prebuilt->select_lock_type == LOCK_X) {
2947
		/* We may use the cursor in update: store its position */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2948
551.1.1 by monty at mysql
Added Innobase to source distribution
2949
		btr_pcur_store_position(prebuilt->clust_pcur, mtr);
2950
	}
2951
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
2952
	err = DB_SUCCESS;
2953
err_exit:
2954
	return(err);
551.1.1 by monty at mysql
Added Innobase to source distribution
2955
}
2956
2957
/************************************************************************
2958
Restores cursor position after it has been stored. We have to take into
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
2959
account that the record cursor was positioned on may have been deleted.
551.1.1 by monty at mysql
Added Innobase to source distribution
2960
Then we may have to move the cursor one step up or down. */
2961
static
2962
ibool
2963
sel_restore_position_for_mysql(
2964
/*===========================*/
2965
					/* out: TRUE if we may need to
2966
					process the record the cursor is
2967
					now positioned on (i.e. we should
2968
					not go to the next record yet) */
1810.260.2 by heikki at mysql
Many files:
2969
	ibool*		same_user_rec,	/* out: TRUE if we were able to restore
2970
					the cursor on a user record with the
2971
					same ordering prefix in in the
2972
					B-tree index */
551.1.1 by monty at mysql
Added Innobase to source distribution
2973
	ulint		latch_mode,	/* in: latch mode wished in
2974
					restoration */
2975
	btr_pcur_t*	pcur,		/* in: cursor whose position
2976
					has been stored */
2977
	ibool		moves_up,	/* in: TRUE if the cursor moves up
2978
					in the index */
2979
	mtr_t*		mtr)		/* in: mtr; CAUTION: may commit
2980
					mtr temporarily! */
2981
{
2982
	ibool	success;
2983
	ulint	relative_position;
2984
2985
	relative_position = pcur->rel_pos;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
2986
551.1.1 by monty at mysql
Added Innobase to source distribution
2987
	success = btr_pcur_restore_position(latch_mode, pcur, mtr);
2988
1810.260.2 by heikki at mysql
Many files:
2989
	*same_user_rec = success;
2990
551.1.1 by monty at mysql
Added Innobase to source distribution
2991
	if (relative_position == BTR_PCUR_ON) {
2992
		if (success) {
2993
			return(FALSE);
2994
		}
2995
2996
		if (moves_up) {
2997
			btr_pcur_move_to_next(pcur, mtr);
2998
		}
2999
3000
		return(TRUE);
3001
	}
3002
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3003
	if (relative_position == BTR_PCUR_AFTER
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3004
	    || relative_position == BTR_PCUR_AFTER_LAST_IN_TREE) {
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3005
551.1.1 by monty at mysql
Added Innobase to source distribution
3006
		if (moves_up) {
3007
			return(TRUE);
3008
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3009
551.1.1 by monty at mysql
Added Innobase to source distribution
3010
		if (btr_pcur_is_on_user_rec(pcur, mtr)) {
3011
			btr_pcur_move_to_prev(pcur, mtr);
3012
		}
3013
3014
		return(TRUE);
3015
	}
3016
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3017
	ut_ad(relative_position == BTR_PCUR_BEFORE
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3018
	      || relative_position == BTR_PCUR_BEFORE_FIRST_IN_TREE);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3019
551.1.1 by monty at mysql
Added Innobase to source distribution
3020
	if (moves_up && btr_pcur_is_on_user_rec(pcur, mtr)) {
3021
		btr_pcur_move_to_next(pcur, mtr);
3022
	}
3023
3024
	return(TRUE);
3025
}
3026
3027
/************************************************************************
3028
Pops a cached row for MySQL from the fetch cache. */
3029
UNIV_INLINE
3030
void
3031
row_sel_pop_cached_row_for_mysql(
3032
/*=============================*/
3033
	byte*		buf,		/* in/out: buffer where to copy the
3034
					row */
3035
	row_prebuilt_t*	prebuilt)	/* in: prebuilt struct */
3036
{
1624.32.1 by sergefp at mysql
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
3037
	ulint			i;
3038
	mysql_row_templ_t*	templ;
3039
	byte*			cached_rec;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3040
	ut_ad(prebuilt->n_fetch_cached > 0);
1773.330.4 by marko at mysql
InnoDB: Reduce memcpy() load in row_sel_pop_cached_row_for_mysql()
3041
	ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3042
3043
	if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) {
3044
		/* Copy cache record field by field, don't touch fields that
1624.32.1 by sergefp at mysql
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
3045
		are not covered by current key */
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3046
		cached_rec = prebuilt->fetch_cache[
3047
			prebuilt->fetch_cache_first];
1624.32.1 by sergefp at mysql
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
3048
3049
		for (i = 0; i < prebuilt->n_template; i++) {
3050
			templ = prebuilt->mysql_template + i;
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3051
			ut_memcpy(buf + templ->mysql_col_offset,
3052
				  cached_rec + templ->mysql_col_offset,
3053
				  templ->mysql_col_len);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3054
			/* Copy NULL bit of the current field from cached_rec
1659.123.1 by sergefp at mysql
Fix for BUG#5401 (attempt 2)
3055
			to buf */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3056
			if (templ->mysql_null_bit_mask) {
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3057
				buf[templ->mysql_null_byte_offset]
3058
					^= (buf[templ->mysql_null_byte_offset]
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3059
					    ^ cached_rec[templ->mysql_null_byte_offset])
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3060
					& (byte)templ->mysql_null_bit_mask;
1659.123.1 by sergefp at mysql
Fix for BUG#5401 (attempt 2)
3061
			}
1624.32.1 by sergefp at mysql
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
3062
		}
3063
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3064
	else {
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3065
		ut_memcpy(buf,
3066
			  prebuilt->fetch_cache[prebuilt->fetch_cache_first],
3067
			  prebuilt->mysql_prefix_len);
1624.32.1 by sergefp at mysql
This is first cset for WL#1394 "Optimize index merge when all involved index ranges include only values with equal keys"
3068
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
3069
	prebuilt->n_fetch_cached--;
3070
	prebuilt->fetch_cache_first++;
3071
3072
	if (prebuilt->n_fetch_cached == 0) {
3073
		prebuilt->fetch_cache_first = 0;
3074
	}
3075
}
3076
3077
/************************************************************************
3078
Pushes a row for MySQL to the fetch cache. */
3079
UNIV_INLINE
3080
void
3081
row_sel_push_cache_row_for_mysql(
3082
/*=============================*/
3083
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
1659.1.48 by marko at mysql
Many files:
3084
	rec_t*		rec,		/* in: record to push */
3085
	const ulint*	offsets)	/* in: rec_get_offsets() */
551.1.1 by monty at mysql
Added Innobase to source distribution
3086
{
1346.7.136 by heikki at mysql
Many files:
3087
	byte*	buf;
551.1.1 by monty at mysql
Added Innobase to source distribution
3088
	ulint	i;
3089
3090
	ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
1659.1.48 by marko at mysql
Many files:
3091
	ut_ad(rec_offs_validate(rec, NULL, offsets));
676.177.36 by heikki at mysql
row0mysql.c:
3092
	ut_a(!prebuilt->templ_contains_blob);
551.1.1 by monty at mysql
Added Innobase to source distribution
3093
3094
	if (prebuilt->fetch_cache[0] == NULL) {
3095
		/* Allocate memory for the fetch cache */
3096
3097
		for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
1346.7.136 by heikki at mysql
Many files:
3098
3099
			/* A user has reported memory corruption in these
3100
			buffers in Linux. Put magic numbers there to help
3101
			to track a possible bug. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3102
1346.7.136 by heikki at mysql
Many files:
3103
			buf = mem_alloc(prebuilt->mysql_row_len + 8);
3104
3105
			prebuilt->fetch_cache[i] = buf + 4;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3106
1346.7.136 by heikki at mysql
Many files:
3107
			mach_write_to_4(buf, ROW_PREBUILT_FETCH_MAGIC_N);
3108
			mach_write_to_4(buf + 4 + prebuilt->mysql_row_len,
3109
					ROW_PREBUILT_FETCH_MAGIC_N);
551.1.1 by monty at mysql
Added Innobase to source distribution
3110
		}
3111
	}
3112
3113
	ut_ad(prebuilt->fetch_cache_first == 0);
3114
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3115
	if (UNIV_UNLIKELY(!row_sel_store_mysql_rec(
3116
				  prebuilt->fetch_cache[
3117
					  prebuilt->n_fetch_cached],
3118
				  prebuilt, rec, offsets))) {
1700.245.1 by marko at mysql
InnoDB: Make CREATE TABLE return error when the minimum row length
3119
		ut_error;
3120
	}
551.1.1 by monty at mysql
Added Innobase to source distribution
3121
3122
	prebuilt->n_fetch_cached++;
3123
}
1346.7.136 by heikki at mysql
Many files:
3124
676.50.8 by heikki at mysql
manual.texi website address change
3125
/*************************************************************************
3126
Tries to do a shortcut to fetch a clustered index record with a unique key,
3127
using the hash index if possible (not always). We assume that the search
1346.8.10 by heikki at mysql
Many files:
3128
mode is PAGE_CUR_GE, it is a consistent read, there is a read view in trx,
676.50.8 by heikki at mysql
manual.texi website address change
3129
btr search latch has been locked in S-mode. */
3130
static
3131
ulint
3132
row_sel_try_search_shortcut_for_mysql(
3133
/*==================================*/
3134
				/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
3135
	rec_t**		out_rec,/* out: record if found */
3136
	row_prebuilt_t*	prebuilt,/* in: prebuilt struct */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3137
	ulint**		offsets,/* in/out: for rec_get_offsets(*out_rec) */
3138
	mem_heap_t**	heap,	/* in/out: heap for rec_get_offsets() */
676.50.8 by heikki at mysql
manual.texi website address change
3139
	mtr_t*		mtr)	/* in: started mtr */
3140
{
3141
	dict_index_t*	index		= prebuilt->index;
3142
	dtuple_t*	search_tuple	= prebuilt->search_tuple;
3143
	btr_pcur_t*	pcur		= prebuilt->pcur;
3144
	trx_t*		trx		= prebuilt->trx;
3145
	rec_t*		rec;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3146
676.50.8 by heikki at mysql
manual.texi website address change
3147
	ut_ad(index->type & DICT_CLUSTERED);
676.177.36 by heikki at mysql
row0mysql.c:
3148
	ut_ad(!prebuilt->templ_contains_blob);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3149
676.50.8 by heikki at mysql
manual.texi website address change
3150
	btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3151
				   BTR_SEARCH_LEAF, pcur,
676.169.18 by heikki at mysql
Many files:
3152
#ifndef UNIV_SEARCH_DEBUG
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3153
				   RW_S_LATCH,
676.169.18 by heikki at mysql
Many files:
3154
#else
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3155
				   0,
676.169.18 by heikki at mysql
Many files:
3156
#endif
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3157
				   mtr);
676.50.8 by heikki at mysql
manual.texi website address change
3158
	rec = btr_pcur_get_rec(pcur);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3159
676.50.8 by heikki at mysql
manual.texi website address change
3160
	if (!page_rec_is_user_rec(rec)) {
3161
3162
		return(SEL_RETRY);
3163
	}
3164
3165
	/* As the cursor is now placed on a user record after a search with
3166
	the mode PAGE_CUR_GE, the up_match field in the cursor tells how many
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3167
	fields in the user record matched to the search tuple */
676.50.8 by heikki at mysql
manual.texi website address change
3168
3169
	if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) {
3170
3171
		return(SEL_EXHAUSTED);
3172
	}
3173
3174
	/* This is a non-locking consistent read: if necessary, fetch
3175
	a previous version of the record */
1659.1.48 by marko at mysql
Many files:
3176
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3177
	*offsets = rec_get_offsets(rec, index, *offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3178
				   ULINT_UNDEFINED, heap);
1659.1.48 by marko at mysql
Many files:
3179
3180
	if (!lock_clust_rec_cons_read_sees(rec, index,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3181
					   *offsets, trx->read_view)) {
676.50.8 by heikki at mysql
manual.texi website address change
3182
3183
		return(SEL_RETRY);
3184
	}
3185
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3186
	if (rec_get_deleted_flag(rec, dict_table_is_comp(index->table))) {
676.50.8 by heikki at mysql
manual.texi website address change
3187
3188
		return(SEL_EXHAUSTED);
3189
	}
3190
3191
	*out_rec = rec;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3192
676.50.8 by heikki at mysql
manual.texi website address change
3193
	return(SEL_FOUND);
3194
}
3195
551.1.1 by monty at mysql
Added Innobase to source distribution
3196
/************************************************************************
3197
Searches for rows in the database. This is used in the interface to
3198
MySQL. This function opens a cursor, and also implements fetch next
3199
and fetch prev. NOTE that if we do a search with a full key value
3200
from a unique index (ROW_SEL_EXACT), then we will not store the cursor
3201
position and fetch next or fetch prev must not be tried to the cursor! */
3202
3203
ulint
3204
row_search_for_mysql(
3205
/*=================*/
3206
					/* out: DB_SUCCESS,
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3207
					DB_RECORD_NOT_FOUND,
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
3208
					DB_END_OF_INDEX, DB_DEADLOCK,
1616.1407.1 by heikki at mysql
Many files:
3209
					DB_LOCK_TABLE_FULL, DB_CORRUPTION,
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
3210
					or DB_TOO_BIG_RECORD */
551.1.1 by monty at mysql
Added Innobase to source distribution
3211
	byte*		buf,		/* in/out: buffer for the fetched
3212
					row in the MySQL format */
3213
	ulint		mode,		/* in: search mode PAGE_CUR_L, ... */
3214
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct for the
3215
					table handle; this contains the info
3216
					of search_tuple, index; if search
3217
					tuple contains 0 fields then we
3218
					position the cursor at the start or
3219
					the end of the index, depending on
3220
					'mode' */
3221
	ulint		match_mode,	/* in: 0 or ROW_SEL_EXACT or
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3222
					ROW_SEL_EXACT_PREFIX */
551.1.1 by monty at mysql
Added Innobase to source distribution
3223
	ulint		direction)	/* in: 0 or ROW_SEL_NEXT or
3224
					ROW_SEL_PREV; NOTE: if this is != 0,
3225
					then prebuilt must have a pcur
3226
					with stored position! In opening of a
3227
					cursor 'direction' should be 0. */
3228
{
3229
	dict_index_t*	index		= prebuilt->index;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3230
	ibool		comp		= dict_table_is_comp(index->table);
551.1.1 by monty at mysql
Added Innobase to source distribution
3231
	dtuple_t*	search_tuple	= prebuilt->search_tuple;
3232
	btr_pcur_t*	pcur		= prebuilt->pcur;
3233
	trx_t*		trx		= prebuilt->trx;
3234
	dict_index_t*	clust_index;
3235
	que_thr_t*	thr;
3236
	rec_t*		rec;
1810.590.10 by heikki at mysql
row0sel.c:
3237
	rec_t*		result_rec;
551.1.1 by monty at mysql
Added Innobase to source distribution
3238
	rec_t*		clust_rec;
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3239
	ulint		err				= DB_SUCCESS;
1346.8.10 by heikki at mysql
Many files:
3240
	ibool		unique_search			= FALSE;
551.1.1 by monty at mysql
Added Innobase to source distribution
3241
	ibool		unique_search_from_clust_index	= FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3242
	ibool		mtr_has_extra_clust_latch	= FALSE;
3243
	ibool		moves_up			= FALSE;
1346.8.10 by heikki at mysql
Many files:
3244
	ibool		set_also_gap_locks		= TRUE;
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3245
	/* if the query is a plain locking SELECT, and the isolation level
3246
	is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */
1979 by lars at mysql
WL#1012: All changes as one single changeset.
3247
	ibool		did_semi_consistent_read	= FALSE;
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3248
	/* if the returned record was locked and we did a semi-consistent
3249
	read (fetch the newest committed version), then this is set to
3250
	TRUE */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3251
#ifdef UNIV_SEARCH_DEBUG
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
3252
	ulint		cnt				= 0;
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3253
#endif /* UNIV_SEARCH_DEBUG */
1346.7.37 by heikki at mysql
Many files:
3254
	ulint		next_offs;
1810.260.2 by heikki at mysql
Many files:
3255
	ibool		same_user_rec;
551.1.1 by monty at mysql
Added Innobase to source distribution
3256
	mtr_t		mtr;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3257
	mem_heap_t*	heap				= NULL;
1773.10.2 by marko at mysql
InnoDB: Introduce the symbols REC_OFFS_NORMAL_SIZE and
3258
	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3259
	ulint*		offsets				= offsets_;
1810.260.2 by heikki at mysql
Many files:
3260
1773.10.1 by marko at mysql
InnoDB: Improve performance by about 10% by removing implicit
3261
	*offsets_ = (sizeof offsets_) / sizeof *offsets_;
3262
551.1.1 by monty at mysql
Added Innobase to source distribution
3263
	ut_ad(index && pcur && search_tuple);
3264
	ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1616.1407.1 by heikki at mysql
Many files:
3265
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3266
	if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3267
		ut_print_timestamp(stderr);
3268
		fprintf(stderr, "  InnoDB: Error:\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3269
			"InnoDB: MySQL is trying to use a table handle"
3270
			" but the .ibd file for\n"
3271
			"InnoDB: table %s does not exist.\n"
3272
			"InnoDB: Have you deleted the .ibd file"
3273
			" from the database directory under\n"
3274
			"InnoDB: the MySQL datadir, or have you used"
3275
			" DISCARD TABLESPACE?\n"
3276
			"InnoDB: Look from\n"
3277
			"InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3278
			"innodb-troubleshooting.html\n"
3279
			"InnoDB: how you can resolve the problem.\n",
3280
			prebuilt->table->name);
1810.414.1 by heikki at mysql
Many files:
3281
1616.1407.1 by heikki at mysql
Many files:
3282
		return(DB_ERROR);
3283
	}
3284
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3285
	if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
676.152.40 by heikki at mysql
Many files:
3286
		fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3287
			"InnoDB: Error: trying to free a corrupt\n"
3288
			"InnoDB: table handle. Magic n %lu, table name ",
3289
			(ulong) prebuilt->magic_n);
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
3290
		ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3291
		putc('\n', stderr);
676.152.40 by heikki at mysql
Many files:
3292
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3293
		mem_analyze_corruption(prebuilt);
676.152.40 by heikki at mysql
Many files:
3294
1346.556.1 by marko at mysql
InnoDB: Replace ut_a(0) with ut_error
3295
		ut_error;
676.152.40 by heikki at mysql
Many files:
3296
	}
3297
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3298
#if 0
3299
	/* August 19, 2005 by Heikki: temporarily disable this error
3300
	print until the cursor lock count is done correctly.
3301
	See bugs #12263 and #12456!*/
3302
1616.1667.24 by heikki at mysql
row0sel.c:
3303
	if (trx->n_mysql_tables_in_use == 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3304
	    && UNIV_UNLIKELY(prebuilt->select_lock_type == LOCK_NONE)) {
1616.1667.24 by heikki at mysql
row0sel.c:
3305
		/* Note that if MySQL uses an InnoDB temp table that it
3306
		created inside LOCK TABLES, then n_mysql_tables_in_use can
3307
		be zero; in that case select_lock_type is set to LOCK_X in
3308
		::start_stmt. */
3309
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3310
		fputs("InnoDB: Error: MySQL is trying to perform a SELECT\n"
3311
		      "InnoDB: but it has not locked"
3312
		      " any tables in ::external_lock()!\n",
3313
		      stderr);
1810.457.1 by osku at 127
InnoDB: Print more than 300 characters of queries in various error conditions,
3314
		trx_print(stderr, trx, 600);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3315
		fputc('\n', stderr);
1616.70.23 by heikki at mysql
row0sel.c:
3316
	}
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3317
#endif
1616.70.23 by heikki at mysql
row0sel.c:
3318
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3319
#if 0
3320
	fprintf(stderr, "Match mode %lu\n search tuple ",
3321
		(ulong) match_mode);
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
3322
	dtuple_print(search_tuple);
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3323
	fprintf(stderr, "N tables locked %lu\n",
3324
		(ulong) trx->mysql_n_tables_locked);
3325
#endif
1346.8.10 by heikki at mysql
Many files:
3326
	/*-------------------------------------------------------------*/
1346.179.14 by heikki at mysql
Many files:
3327
	/* PHASE 0: Release a possible s-latch we are holding on the
3328
	adaptive hash index latch if there is someone waiting behind */
3329
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3330
	if (UNIV_UNLIKELY(btr_search_latch.writer != RW_LOCK_NOT_LOCKED)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3331
	    && trx->has_search_latch) {
1346.179.14 by heikki at mysql
Many files:
3332
3333
		/* There is an x-latch request on the adaptive hash index:
3334
		release the s-latch to reduce starvation and wait for
3335
		BTR_SEA_TIMEOUT rounds before trying to keep it again over
3336
		calls from MySQL */
3337
3338
		rw_lock_s_unlock(&btr_search_latch);
3339
		trx->has_search_latch = FALSE;
3340
3341
		trx->search_latch_timeout = BTR_SEA_TIMEOUT;
3342
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3343
1979 by lars at mysql
WL#1012: All changes as one single changeset.
3344
	/* Reset the new record lock info if srv_locks_unsafe_for_binlog
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3345
	is set or session is using a READ COMMITED isolation level. Then
3346
	we are able to remove the record locks set here on an individual
3347
	row. */
1810.260.2 by heikki at mysql
Many files:
3348
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3349
	if ((srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3350
	     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3351
	    && prebuilt->select_lock_type != LOCK_NONE) {
1810.122.44 by heikki at mysql
row0sel.c:
3352
1810.260.2 by heikki at mysql
Many files:
3353
		trx_reset_new_rec_lock_info(trx);
3354
	}
3355
1346.179.14 by heikki at mysql
Many files:
3356
	/*-------------------------------------------------------------*/
1346.8.10 by heikki at mysql
Many files:
3357
	/* PHASE 1: Try to pop the row from the prefetch cache */
3358
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3359
	if (UNIV_UNLIKELY(direction == 0)) {
1616.426.11 by marko at mysql
InnoDB cleanup:
3360
		trx->op_info = "starting index read";
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3361
551.1.1 by monty at mysql
Added Innobase to source distribution
3362
		prebuilt->n_rows_fetched = 0;
3363
		prebuilt->n_fetch_cached = 0;
3364
		prebuilt->fetch_cache_first = 0;
3365
3366
		if (prebuilt->sel_graph == NULL) {
3367
			/* Build a dummy select query graph */
3368
			row_prebuild_sel_graph(prebuilt);
3369
		}
3370
	} else {
1616.426.11 by marko at mysql
InnoDB cleanup:
3371
		trx->op_info = "fetching rows";
676.118.4 by heikki at mysql
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
3372
551.1.1 by monty at mysql
Added Innobase to source distribution
3373
		if (prebuilt->n_rows_fetched == 0) {
3374
			prebuilt->fetch_direction = direction;
3375
		}
3376
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3377
		if (UNIV_UNLIKELY(direction != prebuilt->fetch_direction)) {
3378
			if (UNIV_UNLIKELY(prebuilt->n_fetch_cached > 0)) {
1346.556.1 by marko at mysql
InnoDB: Replace ut_a(0) with ut_error
3379
				ut_error;
551.1.1 by monty at mysql
Added Innobase to source distribution
3380
				/* TODO: scrollable cursor: restore cursor to
3381
				the place of the latest returned row,
3382
				or better: prevent caching for a scroll
3383
				cursor! */
3384
			}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3385
551.1.1 by monty at mysql
Added Innobase to source distribution
3386
			prebuilt->n_rows_fetched = 0;
3387
			prebuilt->n_fetch_cached = 0;
3388
			prebuilt->fetch_cache_first = 0;
3389
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3390
		} else if (UNIV_LIKELY(prebuilt->n_fetch_cached > 0)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3391
			row_sel_pop_cached_row_for_mysql(buf, prebuilt);
3392
3393
			prebuilt->n_rows_fetched++;
3394
676.118.4 by heikki at mysql
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
3395
			srv_n_rows_read++;
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3396
			err = DB_SUCCESS;
3397
			goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
3398
		}
3399
3400
		if (prebuilt->fetch_cache_first > 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3401
		    && prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3402
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3403
			/* The previous returned row was popped from the fetch
3404
			cache, but the cache was not full at the time of the
3405
			popping: no more rows can exist in the result set */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3406
3407
			err = DB_RECORD_NOT_FOUND;
3408
			goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
3409
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3410
551.1.1 by monty at mysql
Added Innobase to source distribution
3411
		prebuilt->n_rows_fetched++;
3412
3413
		if (prebuilt->n_rows_fetched > 1000000000) {
3414
			/* Prevent wrap-over */
3415
			prebuilt->n_rows_fetched = 500000000;
3416
		}
3417
3418
		mode = pcur->search_mode;
3419
	}
3420
1346.8.10 by heikki at mysql
Many files:
3421
	/* In a search where at most one record in the index may match, we
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3422
	can use a LOCK_REC_NOT_GAP type record lock when locking a
3423
	non-delete-marked matching record.
1346.8.10 by heikki at mysql
Many files:
3424
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3425
	Note that in a unique secondary index there may be different
3426
	delete-marked versions of a record where only the primary key
3427
	values differ: thus in a secondary index we must use next-key
3428
	locks when locking delete-marked records. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3429
676.177.36 by heikki at mysql
row0mysql.c:
3430
	if (match_mode == ROW_SEL_EXACT
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3431
	    && index->type & DICT_UNIQUE
3432
	    && dtuple_get_n_fields(search_tuple)
3433
	    == dict_index_get_n_unique(index)
3434
	    && (index->type & DICT_CLUSTERED
3435
		|| !dtuple_contains_null(search_tuple))) {
1346.425.71 by heikki at mysql
data0data.ic, data0data.h, row0sel.c:
3436
3437
		/* Note above that a UNIQUE secondary index can contain many
3438
		rows with the same key value if one of the columns is the SQL
3439
		null. A clustered index under MySQL can never contain null
3440
		columns because we demand that all the columns in primary key
3441
		are non-null. */
3442
1346.8.10 by heikki at mysql
Many files:
3443
		unique_search = TRUE;
1346.354.1 by heikki at mysql
row0sel.c:
3444
3445
		/* Even if the condition is unique, MySQL seems to try to
3446
		retrieve also a second row if a primary key contains more than
3447
		1 column. Return immediately if this is not a HANDLER
3448
		command. */
1572.1.5 by heikki at mysql
Many files:
3449
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3450
		if (UNIV_UNLIKELY(direction != 0
3451
				  && !prebuilt->used_in_HANDLER)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3452
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3453
			err = DB_RECORD_NOT_FOUND;
3454
			goto func_exit;
1346.354.1 by heikki at mysql
row0sel.c:
3455
		}
1346.8.10 by heikki at mysql
Many files:
3456
	}
3457
1346.354.2 by heikki at mysql
row0sel.c:
3458
	mtr_start(&mtr);
3459
1346.8.10 by heikki at mysql
Many files:
3460
	/*-------------------------------------------------------------*/
3461
	/* PHASE 2: Try fast adaptive hash index search if possible */
3462
3463
	/* Next test if this is the special case where we can use the fast
3464
	adaptive hash index to try the search. Since we must release the
3465
	search system latch when we retrieve an externally stored field, we
3466
	cannot use the adaptive hash index in a search in the case the row
3467
	may be long and there may be externally stored fields */
3468
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3469
	if (UNIV_UNLIKELY(direction == 0)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3470
	    && unique_search
3471
	    && index->type & DICT_CLUSTERED
3472
	    && !prebuilt->templ_contains_blob
3473
	    && !prebuilt->used_in_HANDLER
3474
	    && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3475
3476
		mode = PAGE_CUR_GE;
3477
3478
		unique_search_from_clust_index = TRUE;
676.50.8 by heikki at mysql
manual.texi website address change
3479
1346.58.4 by heikki at mysql
row0sel.c:
3480
		if (trx->mysql_n_tables_locked == 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3481
		    && prebuilt->select_lock_type == LOCK_NONE
3482
		    && trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
3483
		    && trx->read_view) {
676.50.8 by heikki at mysql
manual.texi website address change
3484
3485
			/* This is a SELECT query done as a consistent read,
3486
			and the read view has already been allocated:
3487
			let us try a search shortcut through the hash
1346.58.4 by heikki at mysql
row0sel.c:
3488
			index.
3489
			NOTE that we must also test that
3490
			mysql_n_tables_locked == 0, because this might
3491
			also be INSERT INTO ... SELECT ... or
3492
			CREATE TABLE ... SELECT ... . Our algorithm is
3493
			NOT prepared to inserts interleaved with the SELECT,
3494
			and if we try that, we can deadlock on the adaptive
3495
			hash index semaphore! */
1346.179.14 by heikki at mysql
Many files:
3496
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3497
#ifndef UNIV_SEARCH_DEBUG
676.50.8 by heikki at mysql
manual.texi website address change
3498
			if (!trx->has_search_latch) {
3499
				rw_lock_s_lock(&btr_search_latch);
3500
				trx->has_search_latch = TRUE;
3501
			}
676.169.18 by heikki at mysql
Many files:
3502
#endif
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3503
			switch (row_sel_try_search_shortcut_for_mysql(
3504
					&rec, prebuilt, &offsets, &heap,
3505
					&mtr)) {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3506
			case SEL_FOUND:
676.169.18 by heikki at mysql
Many files:
3507
#ifdef UNIV_SEARCH_DEBUG
1659.1.48 by marko at mysql
Many files:
3508
				ut_a(0 == cmp_dtuple_rec(search_tuple,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3509
							 rec, offsets));
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3510
#endif
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
3511
				if (!row_sel_store_mysql_rec(buf, prebuilt,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3512
							     rec, offsets)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3513
					err = DB_TOO_BIG_RECORD;
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
3514
1572.1.5 by heikki at mysql
Many files:
3515
					/* We let the main loop to do the
3516
					error handling */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3517
					goto shortcut_fails_too_big_rec;
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
3518
				}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3519
3520
				mtr_commit(&mtr);
676.50.8 by heikki at mysql
manual.texi website address change
3521
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3522
				/* ut_print_name(stderr, index->name);
3523
				fputs(" shortcut\n", stderr); */
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
3524
676.118.4 by heikki at mysql
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
3525
				srv_n_rows_read++;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3526
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3527
				if (trx->search_latch_timeout > 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3528
				    && trx->has_search_latch) {
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3529
3530
					trx->search_latch_timeout--;
3531
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3532
					rw_lock_s_unlock(&btr_search_latch);
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3533
					trx->has_search_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3534
				}
3535
1346.179.22 by heikki at mysql
row0sel.c:
3536
				/* NOTE that we do NOT store the cursor
3537
				position */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3538
				err = DB_SUCCESS;
3539
				goto func_exit;
676.50.8 by heikki at mysql
manual.texi website address change
3540
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3541
			case SEL_EXHAUSTED:
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3542
				mtr_commit(&mtr);
676.50.8 by heikki at mysql
manual.texi website address change
3543
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3544
				/* ut_print_name(stderr, index->name);
3545
				fputs(" record not found 2\n", stderr); */
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3546
3547
				if (trx->search_latch_timeout > 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3548
				    && trx->has_search_latch) {
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3549
3550
					trx->search_latch_timeout--;
3551
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3552
					rw_lock_s_unlock(&btr_search_latch);
676.136.13 by heikki at mysql
ut0mem.c Merge changes in InnoDB-3.23.43b
3553
					trx->has_search_latch = FALSE;
3554
				}
3555
1346.179.22 by heikki at mysql
row0sel.c:
3556
				/* NOTE that we do NOT store the cursor
3557
				position */
3558
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3559
				err = DB_RECORD_NOT_FOUND;
3560
				goto func_exit;
676.50.8 by heikki at mysql
manual.texi website address change
3561
			}
1572.1.5 by heikki at mysql
Many files:
3562
shortcut_fails_too_big_rec:
676.77.38 by heikki at mysql
row0sel.c Remove a possible cause of the Peter Zaitsev hang
3563
			mtr_commit(&mtr);
3564
			mtr_start(&mtr);
676.50.8 by heikki at mysql
manual.texi website address change
3565
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
3566
	}
1346.8.10 by heikki at mysql
Many files:
3567
3568
	/*-------------------------------------------------------------*/
3569
	/* PHASE 3: Open or restore index cursor position */
3570
676.50.8 by heikki at mysql
manual.texi website address change
3571
	if (trx->has_search_latch) {
3572
		rw_lock_s_unlock(&btr_search_latch);
3573
		trx->has_search_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3574
	}
676.50.8 by heikki at mysql
manual.texi website address change
3575
676.136.25 by monty at mysql
Merge
3576
	trx_start_if_not_started(trx);
1346.8.10 by heikki at mysql
Many files:
3577
3578
	if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3579
	    && prebuilt->select_lock_type != LOCK_NONE
2542.47.1 by df at erinye
apply snapshot innodb-5.1-ss2387
3580
	    && trx->mysql_query_str != NULL
2632.1.1 by tnurnberg at koehntopp
revert the following CS on grounds of "right patch, wrong time":
3581
	    && *trx->mysql_query_str != NULL
3582
	    && trx->mysql_thd != NULL) {
1346.8.10 by heikki at mysql
Many files:
3583
3584
		/* Scan the MySQL query string; check if SELECT is the first
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3585
		word there */
2154.45.1 by aivanov at mysql
Applied innodb-5.1-ss594 snapshot.
3586
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3587
		if (dict_str_starts_with_keyword(
3588
			    trx->mysql_thd, *trx->mysql_query_str, "SELECT")) {
1346.8.10 by heikki at mysql
Many files:
3589
			/* It is a plain locking SELECT and the isolation
3590
			level is low: do not lock gaps */
3591
3592
			set_also_gap_locks = FALSE;
3593
		}
3594
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3595
551.1.1 by monty at mysql
Added Innobase to source distribution
3596
	/* Note that if the search mode was GE or G, then the cursor
3597
	naturally moves upward (in fetch next) in alphabetical order,
3598
	otherwise downward */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3599
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3600
	if (UNIV_UNLIKELY(direction == 0)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3601
		if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G) {
3602
			moves_up = TRUE;
3603
		}
3604
	} else if (direction == ROW_SEL_NEXT) {
3605
		moves_up = TRUE;
3606
	}
3607
3608
	thr = que_fork_get_first_thr(prebuilt->sel_graph);
3609
3610
	que_thr_move_to_run_state_for_mysql(thr, trx);
3611
3612
	clust_index = dict_table_get_first_index(index->table);
3613
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3614
	if (UNIV_LIKELY(direction != 0)) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3615
		ibool	need_to_process = sel_restore_position_for_mysql(
3616
			&same_user_rec, BTR_SEARCH_LEAF,
3617
			pcur, moves_up, &mtr);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
3618
3619
		if (UNIV_UNLIKELY(need_to_process)) {
3620
			if (UNIV_UNLIKELY(prebuilt->row_read_type
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3621
					  == ROW_READ_DID_SEMI_CONSISTENT)) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
3622
				/* We did a semi-consistent read,
3623
				but the record was removed in
3624
				the meantime. */
3625
				prebuilt->row_read_type
3626
					= ROW_READ_TRY_SEMI_CONSISTENT;
3627
			}
3628
		} else if (UNIV_LIKELY(prebuilt->row_read_type
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3629
				       != ROW_READ_DID_SEMI_CONSISTENT)) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
3630
3631
			/* The cursor was positioned on the record
3632
			that we returned previously.  If we need
3633
			to repeat a semi-consistent read as a
3634
			pessimistic locking read, the record
3635
			cannot be skipped. */
3636
551.1.1 by monty at mysql
Added Innobase to source distribution
3637
			goto next_rec;
3638
		}
3639
3640
	} else if (dtuple_get_n_fields(search_tuple) > 0) {
3641
3642
		btr_pcur_open_with_no_init(index, search_tuple, mode,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3643
					   BTR_SEARCH_LEAF,
3644
					   pcur, 0, &mtr);
1616.1799.8 by heikki at mysql
row0sel.c, btr0pcur.c, btr0pcur.ic, btr0pcur.h:
3645
3646
		pcur->trx_if_known = trx;
2476.199.1 by tsmith at sita
Apply the following innodb-5.1-* snapshots: ss1489, ss1496, ss1550, ss1569.
3647
3648
		rec = btr_pcur_get_rec(pcur);
3649
3650
		if (!moves_up
3651
		    && !page_rec_is_supremum(rec)
3652
		    && set_also_gap_locks
3653
		    && !(srv_locks_unsafe_for_binlog
3654
			 || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3655
		    && prebuilt->select_lock_type != LOCK_NONE) {
3656
3657
			/* Try to place a gap lock on the next index record
3658
			to prevent phantoms in ORDER BY ... DESC queries */
3659
3660
			offsets = rec_get_offsets(page_rec_get_next(rec),
3661
						  index, offsets,
3662
						  ULINT_UNDEFINED, &heap);
3663
			err = sel_set_rec_lock(page_rec_get_next(rec),
3664
					       index, offsets,
3665
					       prebuilt->select_lock_type,
3666
					       LOCK_GAP, thr);
3667
3668
			if (err != DB_SUCCESS) {
3669
3670
				goto lock_wait_or_error;
3671
			}
3672
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
3673
	} else {
3674
		if (mode == PAGE_CUR_G) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3675
			btr_pcur_open_at_index_side(
3676
				TRUE, index, BTR_SEARCH_LEAF, pcur, FALSE,
3677
				&mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
3678
		} else if (mode == PAGE_CUR_L) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3679
			btr_pcur_open_at_index_side(
3680
				FALSE, index, BTR_SEARCH_LEAF, pcur, FALSE,
3681
				&mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
3682
		}
3683
	}
3684
3685
	if (!prebuilt->sql_stat_start) {
3686
		/* No need to set an intention lock or assign a read view */
3687
1616.70.23 by heikki at mysql
row0sel.c:
3688
		if (trx->read_view == NULL
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3689
		    && prebuilt->select_lock_type == LOCK_NONE) {
1616.318.2 by monty at mishka
After merge fixes
3690
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3691
			fputs("InnoDB: Error: MySQL is trying to"
3692
			      " perform a consistent read\n"
3693
			      "InnoDB: but the read view is not assigned!\n",
3694
			      stderr);
1810.457.1 by osku at 127
InnoDB: Print more than 300 characters of queries in various error conditions,
3695
			trx_print(stderr, trx, 600);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3696
			fputc('\n', stderr);
1616.70.23 by heikki at mysql
row0sel.c:
3697
			ut_a(0);
3698
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
3699
	} else if (prebuilt->select_lock_type == LOCK_NONE) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3700
		/* This is a consistent read */
551.1.1 by monty at mysql
Added Innobase to source distribution
3701
		/* Assign a read view for the query */
3702
3703
		trx_assign_read_view(trx);
3704
		prebuilt->sql_stat_start = FALSE;
676.136.25 by monty at mysql
Merge
3705
	} else {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3706
		ulint	lock_mode;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3707
		if (prebuilt->select_lock_type == LOCK_S) {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3708
			lock_mode = LOCK_IS;
551.1.1 by monty at mysql
Added Innobase to source distribution
3709
		} else {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3710
			lock_mode = LOCK_IX;
551.1.1 by monty at mysql
Added Innobase to source distribution
3711
		}
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3712
		err = lock_table(0, index->table, lock_mode, thr);
551.1.1 by monty at mysql
Added Innobase to source distribution
3713
3714
		if (err != DB_SUCCESS) {
3715
3716
			goto lock_wait_or_error;
3717
		}
3718
		prebuilt->sql_stat_start = FALSE;
3719
	}
3720
1346.8.10 by heikki at mysql
Many files:
3721
rec_loop:
551.1.1 by monty at mysql
Added Innobase to source distribution
3722
	/*-------------------------------------------------------------*/
1346.8.10 by heikki at mysql
Many files:
3723
	/* PHASE 4: Look for matching records in a loop */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3724
551.1.1 by monty at mysql
Added Innobase to source distribution
3725
	rec = btr_pcur_get_rec(pcur);
1810.590.8 by heikki at mysql
row0sel.c:
3726
	ut_ad(!!page_rec_is_comp(rec) == comp);
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3727
#ifdef UNIV_SEARCH_DEBUG
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3728
	/*
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3729
	fputs("Using ", stderr);
3730
	dict_index_name_print(stderr, index);
3731
	fprintf(stderr, " cnt %lu ; Page no %lu\n", cnt,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3732
	buf_frame_get_page_no(buf_frame_align(rec)));
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
3733
	rec_print(rec);
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3734
	*/
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3735
#endif /* UNIV_SEARCH_DEBUG */
3736
3737
	if (page_rec_is_infimum(rec)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3738
3739
		/* The infimum record on a page cannot be in the result set,
3740
		and neither can a record lock be placed on it: we skip such
3741
		a record. */
3742
3743
		goto next_rec;
3744
	}
1346.8.10 by heikki at mysql
Many files:
3745
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3746
	if (page_rec_is_supremum(rec)) {
1346.8.10 by heikki at mysql
Many files:
3747
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3748
		if (set_also_gap_locks
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3749
		    && !(srv_locks_unsafe_for_binlog
3750
			 || trx->isolation_level == TRX_ISO_READ_COMMITTED)
3751
		    && prebuilt->select_lock_type != LOCK_NONE) {
1346.8.10 by heikki at mysql
Many files:
3752
1616.1055.1 by jan at mysql
This patch removes unnecessary lock from the supremum record, takes
3753
			/* Try to place a lock on the index record */
1346.8.10 by heikki at mysql
Many files:
3754
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3755
			/* If innodb_locks_unsafe_for_binlog option is used
3756
			or this session is using a READ COMMITTED isolation
3757
			level we do not lock gaps. Supremum record is really
1616.1055.1 by jan at mysql
This patch removes unnecessary lock from the supremum record, takes
3758
			a gap and therefore we do not set locks there. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3759
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3760
			offsets = rec_get_offsets(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3761
						  ULINT_UNDEFINED, &heap);
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3762
			err = sel_set_rec_lock(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3763
					       prebuilt->select_lock_type,
3764
					       LOCK_ORDINARY, thr);
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3765
3766
			if (err != DB_SUCCESS) {
3767
3768
				goto lock_wait_or_error;
1616.1820.1 by heikki at mysql
row0sel.c:
3769
			}
551.1.1 by monty at mysql
Added Innobase to source distribution
3770
		}
3771
		/* A page supremum record cannot be in the result set: skip
1346.8.10 by heikki at mysql
Many files:
3772
		it now that we have placed a possible lock on it */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3773
551.1.1 by monty at mysql
Added Innobase to source distribution
3774
		goto next_rec;
3775
	}
3776
1346.7.37 by heikki at mysql
Many files:
3777
	/*-------------------------------------------------------------*/
3778
	/* Do sanity checks in case our cursor has bumped into page
3779
	corruption */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3780
1810.590.8 by heikki at mysql
row0sel.c:
3781
	if (comp) {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3782
		next_offs = rec_get_next_offs(rec, TRUE);
3783
		if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
1810.590.10 by heikki at mysql
row0sel.c:
3784
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3785
			goto wrong_offs;
3786
		}
3787
	} else {
3788
		next_offs = rec_get_next_offs(rec, FALSE);
3789
		if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
1810.590.10 by heikki at mysql
row0sel.c:
3790
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3791
			goto wrong_offs;
3792
		}
3793
	}
1810.590.10 by heikki at mysql
row0sel.c:
3794
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3795
	if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
1810.590.10 by heikki at mysql
row0sel.c:
3796
3797
wrong_offs:
1346.7.37 by heikki at mysql
Many files:
3798
		if (srv_force_recovery == 0 || moves_up == FALSE) {
3799
			ut_print_timestamp(stderr);
1346.661.1 by heikki at mysql
row0sel.c, page0page.ic:
3800
			buf_page_print(buf_frame_align(rec));
1346.7.37 by heikki at mysql
Many files:
3801
			fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3802
				"\nInnoDB: rec address %p, first"
3803
				" buffer frame %p\n"
3804
				"InnoDB: buffer pool high end %p,"
3805
				" buf block fix count %lu\n",
3806
				(void*) rec, (void*) buf_pool->frame_zero,
3807
				(void*) buf_pool->high_end,
1346.666.1 by heikki at mysql
row0sel.c, page0page.ic:
3808
				(ulong)buf_block_align(rec)->buf_fix_count);
3809
			fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3810
				"InnoDB: Index corruption: rec offs %lu"
3811
				" next offs %lu, page no %lu,\n"
3812
				"InnoDB: ",
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3813
				(ulong) page_offset(rec),
1616.318.1 by monty at mishka
Merge with 4.0
3814
				(ulong) next_offs,
3815
				(ulong) buf_frame_get_page_no(rec));
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
3816
			dict_index_name_print(stderr, trx, index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3817
			fputs(". Run CHECK TABLE. You may need to\n"
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3818
			      "InnoDB: restore from a backup, or"
3819
			      " dump + drop + reimport the table.\n",
3820
			      stderr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3821
1346.7.37 by heikki at mysql
Many files:
3822
			err = DB_CORRUPTION;
3823
3824
			goto lock_wait_or_error;
3825
		} else {
3826
			/* The user may be dumping a corrupt table. Jump
3827
			over the corruption to recover as much as possible. */
3828
3829
			fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3830
				"InnoDB: Index corruption: rec offs %lu"
3831
				" next offs %lu, page no %lu,\n"
3832
				"InnoDB: ",
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3833
				(ulong) page_offset(rec),
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3834
				(ulong) next_offs,
3835
				(ulong) buf_frame_get_page_no(rec));
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
3836
			dict_index_name_print(stderr, trx, index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3837
			fputs(". We try to skip the rest of the page.\n",
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3838
			      stderr);
1346.7.37 by heikki at mysql
Many files:
3839
3840
			btr_pcur_move_to_last_on_page(pcur, &mtr);
3841
3842
			goto next_rec;
3843
		}
3844
	}
1810.590.10 by heikki at mysql
row0sel.c:
3845
	/*-------------------------------------------------------------*/
3846
3847
	/* Calculate the 'offsets' associated with 'rec' */
1346.7.37 by heikki at mysql
Many files:
3848
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3849
	offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
1659.1.48 by marko at mysql
Many files:
3850
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3851
	if (UNIV_UNLIKELY(srv_force_recovery > 0)) {
1659.1.48 by marko at mysql
Many files:
3852
		if (!rec_validate(rec, offsets)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3853
		    || !btr_index_rec_validate(rec, index, FALSE)) {
1346.7.37 by heikki at mysql
Many files:
3854
			fprintf(stderr,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3855
				"InnoDB: Index corruption: rec offs %lu"
3856
				" next offs %lu, page no %lu,\n"
3857
				"InnoDB: ",
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3858
				(ulong) page_offset(rec),
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3859
				(ulong) next_offs,
3860
				(ulong) buf_frame_get_page_no(rec));
1616.989.3 by marko at mysql
InnoDB: quote identifiers according to MySQL settings (Bug #5292)
3861
			dict_index_name_print(stderr, trx, index);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3862
			fputs(". We try to skip the record.\n",
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3863
			      stderr);
1346.7.37 by heikki at mysql
Many files:
3864
3865
			goto next_rec;
3866
		}
3867
	}
3868
1346.7.52 by heikki at mysql
row0sel.c:
3869
	/* Note that we cannot trust the up_match value in the cursor at this
3870
	place because we can arrive here after moving the cursor! Thus
3871
	we have to recompare rec and search_tuple to determine if they
3872
	match enough. */
551.1.1 by monty at mysql
Added Innobase to source distribution
3873
1346.7.52 by heikki at mysql
row0sel.c:
3874
	if (match_mode == ROW_SEL_EXACT) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3875
		/* Test if the index record matches completely to search_tuple
3876
		in prebuilt: if not, then we return with DB_RECORD_NOT_FOUND */
3877
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3878
		/* fputs("Comparing rec and search tuple\n", stderr); */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3879
1659.1.48 by marko at mysql
Many files:
3880
		if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
3881
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3882
			if (set_also_gap_locks
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3883
			    && !(srv_locks_unsafe_for_binlog
3884
				 || trx->isolation_level
3885
				 == TRX_ISO_READ_COMMITTED)
3886
			    && prebuilt->select_lock_type != LOCK_NONE) {
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3887
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3888
				/* Try to place a gap lock on the index
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3889
				record only if innodb_locks_unsafe_for_binlog
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3890
				option is not set or this session is not
3891
				using a READ COMMITTED isolation level. */
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3892
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3893
				err = sel_set_rec_lock(
3894
					rec, index, offsets,
3895
					prebuilt->select_lock_type, LOCK_GAP,
3896
					thr);
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3897
3898
				if (err != DB_SUCCESS) {
3899
3900
					goto lock_wait_or_error;
1616.1820.1 by heikki at mysql
row0sel.c:
3901
				}
1346.8.10 by heikki at mysql
Many files:
3902
			}
3903
551.1.1 by monty at mysql
Added Innobase to source distribution
3904
			btr_pcur_store_position(pcur, &mtr);
3905
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3906
			err = DB_RECORD_NOT_FOUND;
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3907
			/* ut_print_name(stderr, index->name);
3908
			fputs(" record not found 3\n", stderr); */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3909
551.1.1 by monty at mysql
Added Innobase to source distribution
3910
			goto normal_return;
3911
		}
3912
3913
	} else if (match_mode == ROW_SEL_EXACT_PREFIX) {
3914
1659.1.48 by marko at mysql
Many files:
3915
		if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3916
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3917
			if (set_also_gap_locks
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3918
			    && !(srv_locks_unsafe_for_binlog
3919
				 || trx->isolation_level
3920
				 == TRX_ISO_READ_COMMITTED)
3921
			    && prebuilt->select_lock_type != LOCK_NONE) {
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3922
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
3923
				/* Try to place a gap lock on the index
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3924
				record only if innodb_locks_unsafe_for_binlog
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3925
				option is not set or this session is not
3926
				using a READ COMMITTED isolation level. */
1616.1246.5 by jan at mysql
Fixed BUG #6747: innodb_locks_unsafe_for_binlog still uses next-key locking.
3927
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
3928
				err = sel_set_rec_lock(
3929
					rec, index, offsets,
3930
					prebuilt->select_lock_type, LOCK_GAP,
3931
					thr);
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3932
3933
				if (err != DB_SUCCESS) {
3934
3935
					goto lock_wait_or_error;
1616.1820.1 by heikki at mysql
row0sel.c:
3936
				}
1346.8.10 by heikki at mysql
Many files:
3937
			}
3938
551.1.1 by monty at mysql
Added Innobase to source distribution
3939
			btr_pcur_store_position(pcur, &mtr);
3940
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
3941
			err = DB_RECORD_NOT_FOUND;
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
3942
			/* ut_print_name(stderr, index->name);
3943
			fputs(" record not found 4\n", stderr); */
551.1.1 by monty at mysql
Added Innobase to source distribution
3944
3945
			goto normal_return;
3946
		}
3947
	}
1810.260.2 by heikki at mysql
Many files:
3948
551.1.1 by monty at mysql
Added Innobase to source distribution
3949
	/* We are ready to look at a possible new index entry in the result
3950
	set: the cursor is now placed on a user record */
3951
1346.8.10 by heikki at mysql
Many files:
3952
	if (prebuilt->select_lock_type != LOCK_NONE) {
3953
		/* Try to place a lock on the index record; note that delete
3954
		marked records are a special case in a unique search. If there
3955
		is a non-delete marked record, then it is enough to lock its
3956
		existence with LOCK_REC_NOT_GAP. */
3957
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3958
		/* If innodb_locks_unsafe_for_binlog option is used
3959
		or this session is using a READ COMMITED isolation
3960
		level we lock only the record, i.e., next-key locking is
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3961
		not used. */
3962
1659.1.48 by marko at mysql
Many files:
3963
		ulint	lock_type;
3964
1346.8.10 by heikki at mysql
Many files:
3965
		if (!set_also_gap_locks
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3966
		    || srv_locks_unsafe_for_binlog
3967
		    || trx->isolation_level == TRX_ISO_READ_COMMITTED
3968
		    || (unique_search
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
3969
			&& !UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp)))) {
1810.260.2 by heikki at mysql
Many files:
3970
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3971
			goto no_gap_lock;
1346.8.10 by heikki at mysql
Many files:
3972
		} else {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
3973
			lock_type = LOCK_ORDINARY;
1346.8.10 by heikki at mysql
Many files:
3974
		}
1659.1.48 by marko at mysql
Many files:
3975
1773.151.15 by heikki at mysql
row0sel.c:
3976
		/* If we are doing a 'greater or equal than a primary key
3977
		value' search from a clustered index, and we find a record
3978
		that has that exact primary key value, then there is no need
3979
		to lock the gap before the record, because no insert in the
3980
		gap can be in our search range. That is, no phantom row can
3981
		appear that way.
3982
3983
		An example: if col1 is the primary key, the search is WHERE
3984
		col1 >= 100, and we find a record where col1 = 100, then no
3985
		need to lock the gap before that record. */
3986
3987
		if (index == clust_index
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3988
		    && mode == PAGE_CUR_GE
3989
		    && direction == 0
3990
		    && dtuple_get_n_fields_cmp(search_tuple)
3991
		    == dict_index_get_n_unique(index)
3992
		    && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) {
1810.260.2 by heikki at mysql
Many files:
3993
no_gap_lock:
1773.151.14 by jan at mysql
Fixed a bug where next-key locking doesn't allow the insert which does
3994
			lock_type = LOCK_REC_NOT_GAP;
3995
		}
3996
1659.1.48 by marko at mysql
Many files:
3997
		err = sel_set_rec_lock(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
3998
				       prebuilt->select_lock_type,
3999
				       lock_type, thr);
1659.1.48 by marko at mysql
Many files:
4000
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4001
		switch (err) {
4002
			rec_t*	old_vers;
4003
		case DB_SUCCESS:
4004
			break;
4005
		case DB_LOCK_WAIT:
4006
			if (UNIV_LIKELY(prebuilt->row_read_type
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4007
					!= ROW_READ_TRY_SEMI_CONSISTENT)
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4008
			    || index != clust_index) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4009
4010
				goto lock_wait_or_error;
4011
			}
4012
4013
			/* The following call returns 'offsets'
4014
			associated with 'old_vers' */
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4015
			err = row_sel_build_committed_vers_for_mysql(
4016
				clust_index, prebuilt, rec,
4017
				&offsets, &heap, &old_vers, &mtr);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4018
4019
			if (err != DB_SUCCESS) {
4020
4021
				goto lock_wait_or_error;
4022
			}
4023
4024
			mutex_enter(&kernel_mutex);
4025
			if (trx->was_chosen_as_deadlock_victim) {
4026
				mutex_exit(&kernel_mutex);
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
4027
				err = DB_DEADLOCK;
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4028
4029
				goto lock_wait_or_error;
4030
			}
4031
			if (UNIV_LIKELY(trx->wait_lock != NULL)) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4032
				lock_cancel_waiting_and_release(
4033
					trx->wait_lock);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4034
				trx_reset_new_rec_lock_info(trx);
4035
			} else {
4036
				mutex_exit(&kernel_mutex);
4037
4038
				/* The lock was granted while we were
4039
				searching for the last committed version.
4040
				Do a normal locking read. */
4041
4042
				offsets = rec_get_offsets(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4043
							  ULINT_UNDEFINED,
4044
							  &heap);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4045
				err = DB_SUCCESS;
4046
				break;
4047
			}
4048
			mutex_exit(&kernel_mutex);
4049
4050
			if (old_vers == NULL) {
4051
				/* The row was not yet committed */
4052
4053
				goto next_rec;
4054
			}
4055
4056
			did_semi_consistent_read = TRUE;
4057
			rec = old_vers;
4058
			break;
4059
		default:
1346.8.10 by heikki at mysql
Many files:
4060
4061
			goto lock_wait_or_error;
4062
		}
4063
	} else {
551.1.1 by monty at mysql
Added Innobase to source distribution
4064
		/* This is a non-locking consistent read: if necessary, fetch
4065
		a previous version of the record */
4066
1346.8.10 by heikki at mysql
Many files:
4067
		if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) {
4068
4069
			/* Do nothing: we let a non-locking SELECT read the
4070
			latest version of the record */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4071
1346.8.10 by heikki at mysql
Many files:
4072
		} else if (index == clust_index) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4073
1346.404.1 by heikki at mysql
row0sel.c:
4074
			/* Fetch a previous version of the row if the current
4075
			one is not visible in the snapshot; if we have a very
4076
			high force recovery level set, we try to avoid crashes
4077
			by skipping this lookup */
4078
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4079
			if (UNIV_LIKELY(srv_force_recovery < 5)
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4080
			    && !lock_clust_rec_cons_read_sees(
4081
				    rec, index, offsets, trx->read_view)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4082
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4083
				rec_t*	old_vers;
1810.590.10 by heikki at mysql
row0sel.c:
4084
				/* The following call returns 'offsets'
4085
				associated with 'old_vers' */
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4086
				err = row_sel_build_prev_vers_for_mysql(
4087
					trx->read_view, clust_index,
4088
					prebuilt, rec, &offsets, &heap,
4089
					&old_vers, &mtr);
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4090
551.1.1 by monty at mysql
Added Innobase to source distribution
4091
				if (err != DB_SUCCESS) {
4092
4093
					goto lock_wait_or_error;
4094
				}
4095
4096
				if (old_vers == NULL) {
4097
					/* The row did not exist yet in
4098
					the read view */
4099
4100
					goto next_rec;
4101
				}
4102
4103
				rec = old_vers;
4104
			}
4105
		} else if (!lock_sec_rec_cons_read_sees(rec, index,
4106
							trx->read_view)) {
4107
			/* We are looking into a non-clustered index,
4108
			and to get the right version of the record we
4109
			have to look also into the clustered index: this
4110
			is necessary, because we can only get the undo
4111
			information via the clustered index record. */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4112
4113
			ut_ad(index != clust_index);
1810.260.2 by heikki at mysql
Many files:
4114
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4115
			goto requires_clust_rec;
551.1.1 by monty at mysql
Added Innobase to source distribution
4116
		}
4117
	}
4118
1810.590.8 by heikki at mysql
row0sel.c:
4119
	/* NOTE that at this point rec can be an old version of a clustered
4120
	index record built for a consistent read. We cannot assume after this
4121
	point that rec is on a buffer pool page. Functions like
1810.590.10 by heikki at mysql
row0sel.c:
4122
	page_rec_is_comp() cannot be used! */
1810.590.8 by heikki at mysql
row0sel.c:
4123
4124
	if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp))) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4125
1810.590.11 by heikki at mysql
row0sel.c:
4126
		/* The record is delete-marked: we can skip it */
1810.260.2 by heikki at mysql
Many files:
4127
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
4128
		if ((srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4129
		     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4130
		    && prebuilt->select_lock_type != LOCK_NONE
4131
		    && !did_semi_consistent_read) {
1810.122.44 by heikki at mysql
row0sel.c:
4132
1810.260.2 by heikki at mysql
Many files:
4133
			/* No need to keep a lock on a delete-marked record
4134
			if we do not want to use next-key locking. */
4135
4136
			row_unlock_for_mysql(prebuilt, TRUE);
4137
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4138
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4139
		/* This is an optimization to skip setting the next key lock
4140
		on the record that follows this delete-marked record. This
4141
		optimization works because of the unique search criteria
4142
		which precludes the presence of a range lock between this
4143
		delete marked record and the record following it.
4144
4145
		For now this is applicable only to clustered indexes while
4146
		doing a unique search. There is scope for further optimization
4147
		applicable to unique secondary indexes. Current behaviour is
4148
		to widen the scope of a lock on an already delete marked record
4149
		if the same record is deleted twice by the same transaction */
4150
		if (index == clust_index && unique_search) {
4151
			err = DB_RECORD_NOT_FOUND;
4152
4153
			goto normal_return;
4154
		}
4155
551.1.1 by monty at mysql
Added Innobase to source distribution
4156
		goto next_rec;
4157
	}
4158
1810.590.10 by heikki at mysql
row0sel.c:
4159
	/* Get the clustered index record if needed, if we did not do the
4160
	search using the clustered index. */
551.1.1 by monty at mysql
Added Innobase to source distribution
4161
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4162
	if (index != clust_index && prebuilt->need_to_access_clustered) {
1810.260.2 by heikki at mysql
Many files:
4163
4164
requires_clust_rec:
1810.590.10 by heikki at mysql
row0sel.c:
4165
		/* We use a 'goto' to the preceding label if a consistent
4166
		read of a secondary index record requires us to look up old
4167
		versions of the associated clustered index record. */
1810.590.8 by heikki at mysql
row0sel.c:
4168
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4169
		ut_ad(rec_offs_validate(rec, index, offsets));
551.1.1 by monty at mysql
Added Innobase to source distribution
4170
4171
		/* It was a non-clustered index and we must fetch also the
4172
		clustered index record */
4173
4174
		mtr_has_extra_clust_latch = TRUE;
1810.590.10 by heikki at mysql
row0sel.c:
4175
4176
		/* The following call returns 'offsets' associated with
4177
		'clust_rec'. Note that 'clust_rec' can be an old version
4178
		built for a consistent read. */
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4179
551.1.1 by monty at mysql
Added Innobase to source distribution
4180
		err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4181
						      thr, &clust_rec,
4182
						      &offsets, &heap, &mtr);
551.1.1 by monty at mysql
Added Innobase to source distribution
4183
		if (err != DB_SUCCESS) {
4184
4185
			goto lock_wait_or_error;
4186
		}
4187
4188
		if (clust_rec == NULL) {
4189
			/* The record did not exist in the read view */
4190
			ut_ad(prebuilt->select_lock_type == LOCK_NONE);
4191
4192
			goto next_rec;
4193
		}
4194
1810.590.8 by heikki at mysql
row0sel.c:
4195
		if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4196
4197
			/* The record is delete marked: we can skip it */
4198
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
4199
			if ((srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4200
			     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4201
			    && prebuilt->select_lock_type != LOCK_NONE) {
1810.122.44 by heikki at mysql
row0sel.c:
4202
1810.260.2 by heikki at mysql
Many files:
4203
				/* No need to keep a lock on a delete-marked
4204
				record if we do not want to use next-key
4205
				locking. */
4206
4207
				row_unlock_for_mysql(prebuilt, TRUE);
4208
			}
4209
551.1.1 by monty at mysql
Added Innobase to source distribution
4210
			goto next_rec;
4211
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4212
676.26.1 by heikki at mysql
row0sel.c Fix a bug in consistent read through secondary key
4213
		if (prebuilt->need_to_access_clustered) {
1810.590.10 by heikki at mysql
row0sel.c:
4214
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4215
			result_rec = clust_rec;
1810.590.10 by heikki at mysql
row0sel.c:
4216
1810.590.11 by heikki at mysql
row0sel.c:
4217
			ut_ad(rec_offs_validate(result_rec, clust_index,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4218
						offsets));
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
4219
		} else {
1810.590.10 by heikki at mysql
row0sel.c:
4220
			/* We used 'offsets' for the clust rec, recalculate
4221
			them for 'rec' */
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
4222
			offsets = rec_get_offsets(rec, index, offsets,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4223
						  ULINT_UNDEFINED, &heap);
1810.590.10 by heikki at mysql
row0sel.c:
4224
			result_rec = rec;
676.26.1 by heikki at mysql
row0sel.c Fix a bug in consistent read through secondary key
4225
		}
1810.590.10 by heikki at mysql
row0sel.c:
4226
	} else {
4227
		result_rec = rec;
551.1.1 by monty at mysql
Added Innobase to source distribution
4228
	}
4229
1810.590.10 by heikki at mysql
row0sel.c:
4230
	/* We found a qualifying record 'result_rec'. At this point,
4231
	'offsets' are associated with 'result_rec'. */
4232
4233
	ut_ad(rec_offs_validate(result_rec,
4234
				result_rec != rec ? clust_index : index,
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
4235
				offsets));
4236
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4237
	if ((match_mode == ROW_SEL_EXACT
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4238
	     || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD)
4239
	    && prebuilt->select_lock_type == LOCK_NONE
4240
	    && !prebuilt->templ_contains_blob
4241
	    && !prebuilt->clust_index_was_generated
4242
	    && !prebuilt->used_in_HANDLER
4243
	    && prebuilt->template_type
4244
	    != ROW_MYSQL_DUMMY_TEMPLATE) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4245
4246
		/* Inside an update, for example, we do not cache rows,
4247
		since we may use the cursor position to do the actual
676.177.36 by heikki at mysql
row0mysql.c:
4248
		update, that is why we require ...lock_type == LOCK_NONE.
4249
		Since we keep space in prebuilt only for the BLOBs of
4250
		a single row, we cannot cache rows in the case there
1346.179.22 by heikki at mysql
row0sel.c:
4251
		are BLOBs in the fields to be fetched. In HANDLER we do
4252
		not cache rows because there the cursor is a scrollable
4253
		cursor. */
551.1.1 by monty at mysql
Added Innobase to source distribution
4254
1810.590.10 by heikki at mysql
row0sel.c:
4255
		row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4256
						 offsets);
551.1.1 by monty at mysql
Added Innobase to source distribution
4257
		if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4258
551.1.1 by monty at mysql
Added Innobase to source distribution
4259
			goto got_row;
4260
		}
4261
4262
		goto next_rec;
4263
	} else {
676.50.8 by heikki at mysql
manual.texi website address change
4264
		if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
1810.590.10 by heikki at mysql
row0sel.c:
4265
			memcpy(buf + 4, result_rec
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4266
			       - rec_offs_extra_size(offsets),
4267
			       rec_offs_size(offsets));
1659.1.48 by marko at mysql
Many files:
4268
			mach_write_to_4(buf,
4269
					rec_offs_extra_size(offsets) + 4);
676.50.8 by heikki at mysql
manual.texi website address change
4270
		} else {
1659.1.48 by marko at mysql
Many files:
4271
			if (!row_sel_store_mysql_rec(buf, prebuilt,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4272
						     result_rec, offsets)) {
1403.4.73 by heikki at mysql
ut0mem.c, row0sel.c, row0mysql.c, ut0mem.h, row0sel.h, row0mysql.h:
4273
				err = DB_TOO_BIG_RECORD;
4274
4275
				goto lock_wait_or_error;
4276
			}
676.50.8 by heikki at mysql
manual.texi website address change
4277
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
4278
4279
		if (prebuilt->clust_index_was_generated) {
1810.590.10 by heikki at mysql
row0sel.c:
4280
			if (result_rec != rec) {
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4281
				offsets = rec_get_offsets(
4282
					rec, index, offsets, ULINT_UNDEFINED,
4283
					&heap);
1764.35.1 by marko at mysql
InnoDB: optimize SELECT performance
4284
			}
1810.590.10 by heikki at mysql
row0sel.c:
4285
			row_sel_store_row_id_to_prebuilt(prebuilt, rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4286
							 index, offsets);
551.1.1 by monty at mysql
Added Innobase to source distribution
4287
		}
4288
	}
1810.590.10 by heikki at mysql
row0sel.c:
4289
4290
	/* From this point on, 'offsets' are invalid. */
4291
551.1.1 by monty at mysql
Added Innobase to source distribution
4292
got_row:
1346.179.21 by heikki at mysql
ha_innodb.cc, row0sel.c, row0mysql.c, row0mysql.h:
4293
	/* We have an optimization to save CPU time: if this is a consistent
4294
	read on a unique condition on the clustered index, then we do not
4295
	store the pcur position, because any fetch next or prev will anyway
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4296
	return 'end of file'. Exceptions are locking reads and the MySQL
4297
	HANDLER command where the user can move the cursor with PREV or NEXT
4298
	even after a unique search. */
551.1.1 by monty at mysql
Added Innobase to source distribution
4299
4300
	if (!unique_search_from_clust_index
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4301
	    || prebuilt->select_lock_type != LOCK_NONE
4302
	    || prebuilt->used_in_HANDLER) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4303
4304
		/* Inside an update always store the cursor position */
4305
4306
		btr_pcur_store_position(pcur, &mtr);
4307
	}
4308
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4309
	err = DB_SUCCESS;
551.1.1 by monty at mysql
Added Innobase to source distribution
4310
4311
	goto normal_return;
1346.8.10 by heikki at mysql
Many files:
4312
4313
next_rec:
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4314
	/* Reset the old and new "did semi-consistent read" flags. */
4315
	if (UNIV_UNLIKELY(prebuilt->row_read_type
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4316
			  == ROW_READ_DID_SEMI_CONSISTENT)) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4317
		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4318
	}
4319
	did_semi_consistent_read = FALSE;
4320
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
4321
	if (UNIV_UNLIKELY(srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4322
			  || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4323
	    && prebuilt->select_lock_type != LOCK_NONE) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4324
4325
		trx_reset_new_rec_lock_info(trx);
4326
	}
4327
1346.226.32 by heikki at mysql
row0vers.c, row0sel.c, row0ins.c:
4328
	/*-------------------------------------------------------------*/
1346.8.10 by heikki at mysql
Many files:
4329
	/* PHASE 5: Move the cursor to the next index record */
1810.260.2 by heikki at mysql
Many files:
4330
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4331
	if (UNIV_UNLIKELY(mtr_has_extra_clust_latch)) {
551.1.1 by monty at mysql
Added Innobase to source distribution
4332
		/* We must commit mtr if we are moving to the next
4333
		non-clustered index record, because we could break the
4334
		latching order if we would access a different clustered
4335
		index page right away without releasing the previous. */
4336
4337
		btr_pcur_store_position(pcur, &mtr);
4338
4339
		mtr_commit(&mtr);
4340
		mtr_has_extra_clust_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4341
551.1.1 by monty at mysql
Added Innobase to source distribution
4342
		mtr_start(&mtr);
1810.260.2 by heikki at mysql
Many files:
4343
		if (sel_restore_position_for_mysql(&same_user_rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4344
						   BTR_SEARCH_LEAF,
4345
						   pcur, moves_up, &mtr)) {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4346
#ifdef UNIV_SEARCH_DEBUG
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
4347
			cnt++;
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4348
#endif /* UNIV_SEARCH_DEBUG */
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
4349
551.1.1 by monty at mysql
Added Innobase to source distribution
4350
			goto rec_loop;
4351
		}
4352
	}
4353
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4354
	if (moves_up) {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4355
		if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) {
1810.590.10 by heikki at mysql
row0sel.c:
4356
not_moved:
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4357
			btr_pcur_store_position(pcur, &mtr);
4358
4359
			if (match_mode != 0) {
4360
				err = DB_RECORD_NOT_FOUND;
4361
			} else {
4362
				err = DB_END_OF_INDEX;
4363
			}
4364
4365
			goto normal_return;
4366
		}
551.1.1 by monty at mysql
Added Innobase to source distribution
4367
	} else {
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4368
		if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) {
4369
			goto not_moved;
551.1.1 by monty at mysql
Added Innobase to source distribution
4370
		}
4371
	}
4372
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4373
#ifdef UNIV_SEARCH_DEBUG
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
4374
	cnt++;
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4375
#endif /* UNIV_SEARCH_DEBUG */
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
4376
551.1.1 by monty at mysql
Added Innobase to source distribution
4377
	goto rec_loop;
1346.8.10 by heikki at mysql
Many files:
4378
4379
lock_wait_or_error:
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4380
	/* Reset the old and new "did semi-consistent read" flags. */
4381
	if (UNIV_UNLIKELY(prebuilt->row_read_type
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4382
			  == ROW_READ_DID_SEMI_CONSISTENT)) {
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4383
		prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4384
	}
4385
	did_semi_consistent_read = FALSE;
4386
551.1.1 by monty at mysql
Added Innobase to source distribution
4387
	/*-------------------------------------------------------------*/
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4388
551.1.1 by monty at mysql
Added Innobase to source distribution
4389
	btr_pcur_store_position(pcur, &mtr);
4390
4391
	mtr_commit(&mtr);
4392
	mtr_has_extra_clust_latch = FALSE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4393
551.1.1 by monty at mysql
Added Innobase to source distribution
4394
	trx->error_state = err;
4395
4396
	/* The following is a patch for MySQL */
4397
4398
	que_thr_stop_for_mysql(thr);
4399
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4400
	thr->lock_state = QUE_THR_LOCK_ROW;
1659.90.1 by vtkachenko at mysql
logging_ok:
4401
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4402
	if (row_mysql_handle_errors(&err, trx, thr, NULL)) {
1810.122.44 by heikki at mysql
row0sel.c:
4403
		/* It was a lock wait, and it ended */
4404
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4405
		thr->lock_state = QUE_THR_LOCK_NOLOCK;
551.1.1 by monty at mysql
Added Innobase to source distribution
4406
		mtr_start(&mtr);
4407
1810.260.2 by heikki at mysql
Many files:
4408
		sel_restore_position_for_mysql(&same_user_rec,
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4409
					       BTR_SEARCH_LEAF, pcur,
4410
					       moves_up, &mtr);
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
4411
4412
		if ((srv_locks_unsafe_for_binlog
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4413
		     || trx->isolation_level == TRX_ISO_READ_COMMITTED)
4414
		    && !same_user_rec) {
2119.458.2 by aivanov at mysql
Applied innodb-5.1-ss475 snapshot.
4415
1810.260.2 by heikki at mysql
Many files:
4416
			/* Since we were not able to restore the cursor
4417
			on the same user record, we cannot use
4418
			row_unlock_for_mysql() to unlock any records, and
4419
			we must thus reset the new rec lock info. Since
4420
			in lock0lock.c we have blocked the inheriting of gap
4421
			X-locks, we actually do not have any new record locks
4422
			set in this case.
4423
4424
			Note that if we were able to restore on the 'same'
4425
			user record, it is still possible that we were actually
4426
			waiting on a delete-marked record, and meanwhile
4427
			it was removed by purge and inserted again by some
4428
			other user. But that is no problem, because in
4429
			rec_loop we will again try to set a lock, and
4430
			new_rec_lock_info in trx will be right at the end. */
4431
4432
			trx_reset_new_rec_lock_info(trx);
4433
		}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4434
551.1.1 by monty at mysql
Added Innobase to source distribution
4435
		mode = pcur->search_mode;
4436
4437
		goto rec_loop;
4438
	}
676.77.67 by heikki at mysql
srv0srv.h Support raw disk partitions as data files
4439
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4440
	thr->lock_state = QUE_THR_LOCK_NOLOCK;
4441
4442
#ifdef UNIV_SEARCH_DEBUG
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4443
	/*	fputs("Using ", stderr);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
4444
	dict_index_name_print(stderr, index);
4445
	fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4446
#endif /* UNIV_SEARCH_DEBUG */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4447
	goto func_exit;
551.1.1 by monty at mysql
Added Innobase to source distribution
4448
4449
normal_return:
1346.8.10 by heikki at mysql
Many files:
4450
	/*-------------------------------------------------------------*/
551.1.1 by monty at mysql
Added Innobase to source distribution
4451
	que_thr_stop_for_mysql_no_error(thr, trx);
4452
4453
	mtr_commit(&mtr);
4454
4455
	if (prebuilt->n_fetch_cached > 0) {
4456
		row_sel_pop_cached_row_for_mysql(buf, prebuilt);
4457
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4458
		err = DB_SUCCESS;
551.1.1 by monty at mysql
Added Innobase to source distribution
4459
	}
4460
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4461
#ifdef UNIV_SEARCH_DEBUG
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4462
	/*	fputs("Using ", stderr);
1346.564.39 by marko at mysql
InnoDB: send diagnostic output to stderr or files
4463
	dict_index_name_print(stderr, index);
4464
	fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
1773.330.13 by marko at mysql
InnoDB: Performance optimizations based on OProfile analysis
4465
#endif /* UNIV_SEARCH_DEBUG */
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4466
	if (err == DB_SUCCESS) {
676.118.4 by heikki at mysql
trx0roll.c Fix the primary key update + BLOB bug, improve InnoDB Monitor prints
4467
		srv_n_rows_read++;
4468
	}
4469
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4470
func_exit:
1616.426.11 by marko at mysql
InnoDB cleanup:
4471
	trx->op_info = "";
1773.330.3 by marko at mysql
InnoDB: Define some macros around GCC's __builtin_expect()
4472
	if (UNIV_LIKELY_NULL(heap)) {
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4473
		mem_heap_free(heap);
4474
	}
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4475
4476
	/* Set or reset the "did semi-consistent read" flag on return.
4477
	The flag did_semi_consistent_read is set if and only if
4478
	the record being returned was fetched with a semi-consistent read. */
4479
	ut_ad(prebuilt->row_read_type != ROW_READ_WITH_LOCKS
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4480
	      || !did_semi_consistent_read);
1979 by lars at mysql
WL#1012: All changes as one single changeset.
4481
4482
	if (UNIV_UNLIKELY(prebuilt->row_read_type != ROW_READ_WITH_LOCKS)) {
4483
		if (UNIV_UNLIKELY(did_semi_consistent_read)) {
4484
			prebuilt->row_read_type = ROW_READ_DID_SEMI_CONSISTENT;
4485
		} else {
4486
			prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
4487
		}
4488
	}
1659.29.1 by marko at mysql
InnoDB: Changed interface to rec_get_offsets(), to reduce the use of
4489
	return(err);
551.1.1 by monty at mysql
Added Innobase to source distribution
4490
}
1290 by heikki at mysql
Many files:
4491
4492
/***********************************************************************
4493
Checks if MySQL at the moment is allowed for this table to retrieve a
4494
consistent read result, or store it to the query cache. */
4495
4496
ibool
4497
row_search_check_if_query_cache_permitted(
4498
/*======================================*/
1616.388.6 by marko at mysql
InnoDB cleanup: Add const qualifiers to many char* arguments
4499
					/* out: TRUE if storing or retrieving
4500
					from the query cache is permitted */
4501
	trx_t*		trx,		/* in: transaction object */
4502
	const char*	norm_name)	/* in: concatenation of database name,
4503
					'/' char, table name */
1290 by heikki at mysql
Many files:
4504
{
4505
	dict_table_t*	table;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4506
	ibool		ret	= FALSE;
1290 by heikki at mysql
Many files:
4507
2367.2.1 by tsmith at hindu
Applied innodb-5.1-ss1039 and innodb-5.1-ss1134 snapshots.
4508
	table = dict_table_get(norm_name, FALSE);
1290 by heikki at mysql
Many files:
4509
4510
	if (table == NULL) {
4511
4512
		return(FALSE);
4513
	}
4514
4515
	mutex_enter(&kernel_mutex);
4516
4517
	/* Start the transaction if it is not started yet */
4518
4519
	trx_start_if_not_started_low(trx);
4520
4521
	/* If there are locks on the table or some trx has invalidated the
4522
	cache up to our trx id, then ret = FALSE.
4523
	We do not check what type locks there are on the table, though only
4524
	IX type locks actually would require ret = FALSE. */
4525
4526
	if (UT_LIST_GET_LEN(table->locks) == 0
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4527
	    && ut_dulint_cmp(trx->id,
4528
			     table->query_cache_inv_trx_id) >= 0) {
1290 by heikki at mysql
Many files:
4529
4530
		ret = TRUE;
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4531
1346.8.10 by heikki at mysql
Many files:
4532
		/* If the isolation level is high, assign a read view for the
4533
		transaction if it does not yet have one */
4534
4535
		if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ
2273.23.2 by tsmith at mysql
Applied InnoDB 5.1 snapshot ss787.
4536
		    && !trx->read_view) {
1346.8.10 by heikki at mysql
Many files:
4537
2273.87.2 by tim at hindu
Applied innodb-5.1 snapshots ss799 and ss854
4538
			trx->read_view = read_view_open_now(
4539
				trx->id, trx->global_read_view_heap);
1810.383.1 by jan at mysql
Implement MySQL framework to support consistent read views in
4540
			trx->global_read_view = trx->read_view;
1290 by heikki at mysql
Many files:
4541
		}
4542
	}
2119.166.1 by aivanov at mysql
Applied innodb-5.1-ss269 snapshot.
4543
1290 by heikki at mysql
Many files:
4544
	mutex_exit(&kernel_mutex);
4545
4546
	return(ret);
4547
}
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4548
4549
/***********************************************************************
2476.532.7 by tsmith at hindu
Apply snapshot innodb-5.1-ss2034
4550
Read the AUTOINC column from the current row. If the value is less than
4551
0 and the type is not unsigned then we reset the value to 0. */
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4552
static
2542.39.1 by tsmith at mysql
Apply innodb-5.1-ss2360 snapshot
4553
ib_ulonglong
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4554
row_search_autoinc_read_column(
4555
/*===========================*/
4556
					/* out: value read from the column */
4557
	dict_index_t*	index,		/* in: index to read from */
4558
	const rec_t*	rec,		/* in: current rec */
4559
	ulint		col_no,		/* in: column number */
4560
	ibool		unsigned_type)	/* in: signed or unsigned flag */
4561
{
4562
	ulint		len;
4563
	const byte*	data;
2542.39.1 by tsmith at mysql
Apply innodb-5.1-ss2360 snapshot
4564
	ib_ulonglong	value;
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4565
	mem_heap_t*	heap = NULL;
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
4566
	/* Our requirement is that dest should be word aligned. */
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4567
	byte		dest[sizeof(value)];
4568
	ulint		offsets_[REC_OFFS_NORMAL_SIZE];
4569
	ulint*		offsets	= offsets_;
4570
4571
	*offsets_ = sizeof offsets_ / sizeof *offsets_;
4572
4573
	/* TODO: We have to cast away the const of rec for now.  This needs
4574
	to be fixed later.*/
4575
	offsets = rec_get_offsets(
4576
		(rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap);
4577
4578
	/* TODO: We have to cast away the const of rec for now.  This needs
4579
	to be fixed later.*/
4580
	data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len);
4581
4582
	ut_a(len != UNIV_SQL_NULL);
4583
	ut_a(len <= sizeof value);
4584
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
4585
	mach_read_int_type(dest, data, len, unsigned_type);
4586
4587
	/* The assumption here is that the AUTOINC value can't be negative
4588
	and that dest is word aligned. */
4589
	switch (len) {
4590
	case 8:
2542.39.1 by tsmith at mysql
Apply innodb-5.1-ss2360 snapshot
4591
		value = *(ib_ulonglong*) dest;
2476.532.6 by tsmith at hindu
Apply snapshot innodb-5.1-ss1989
4592
		break;
4593
4594
	case 4:
4595
		value = *(ib_uint32_t*) dest;
4596
		break;
4597
4598
	case 3:
4599
		value = *(ib_uint32_t*) dest;
4600
		value &= 0xFFFFFF;
4601
		break;
4602
4603
	case 2:
4604
		value = *(uint16 *) dest;
4605
		break;
4606
4607
	case 1:
4608
		value = *dest;
4609
		break;
4610
4611
	default:
4612
		ut_error;
4613
	}
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4614
4615
	if (UNIV_LIKELY_NULL(heap)) {
4616
		mem_heap_free(heap);
4617
	}
4618
2542.39.1 by tsmith at mysql
Apply innodb-5.1-ss2360 snapshot
4619
	if (!unsigned_type && (ib_longlong) value < 0) {
2476.532.7 by tsmith at hindu
Apply snapshot innodb-5.1-ss2034
4620
		value = 0;
4621
	}
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4622
4623
	return(value);
4624
}
4625
4626
/***********************************************************************
4627
Get the last row. */
4628
static
4629
const rec_t*
4630
row_search_autoinc_get_rec(
4631
/*=======================*/
4632
					/* out: current rec or NULL */
4633
	btr_pcur_t*	pcur,		/* in: the current cursor */
4634
	mtr_t*		mtr)		/* in: mini transaction */
4635
{
4636
	do {
4637
		const rec_t* rec = btr_pcur_get_rec(pcur);
4638
4639
		if (page_rec_is_user_rec(rec)) {
4640
			return(rec);
4641
		}
4642
	} while (btr_pcur_move_to_prev(pcur, mtr));
4643
4644
	return(NULL);
4645
}
4646
4647
/***********************************************************************
4648
Read the max AUTOINC value from an index. */
4649
4650
ulint
4651
row_search_max_autoinc(
4652
/*===================*/
4653
					/* out: DB_SUCCESS if all OK else
4654
					error code, DB_RECORD_NOT_FOUND if
4655
					column name can't be found in index */
4656
	dict_index_t*	index,		/* in: index to search */
4657
	const char*	col_name,	/* in: name of autoinc column */
2542.39.1 by tsmith at mysql
Apply innodb-5.1-ss2360 snapshot
4658
	ib_ulonglong*	value)		/* out: AUTOINC value read */
2476.352.1 by tsmith at hindu
Apply InnoDB snapshot innodb-5.1-ss1726.
4659
{
4660
	ulint		i;
4661
	ulint		n_cols;
4662
	dict_field_t*	dfield = NULL;
4663
	ulint		error = DB_SUCCESS;
4664
4665
	n_cols = dict_index_get_n_ordering_defined_by_user(index);
4666
4667
	/* Search the index for the AUTOINC column name */
4668
	for (i = 0; i < n_cols; ++i) {
4669
		dfield = dict_index_get_nth_field(index, i);
4670
4671
		if (strcmp(col_name, dfield->name) == 0) {
4672
			break;
4673
		}
4674
	}
4675
4676
	*value = 0;
4677
4678
	/* Must find the AUTOINC column name */
4679
	if (i < n_cols && dfield) {
4680
		mtr_t		mtr;
4681
		btr_pcur_t	pcur;
4682
4683
		mtr_start(&mtr);
4684
4685
		/* Open at the high/right end (FALSE), and INIT
4686
		cursor (TRUE) */
4687
		btr_pcur_open_at_index_side(
4688
			FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
4689
4690
		if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
4691
			const rec_t*	rec;
4692
4693
			rec = row_search_autoinc_get_rec(&pcur, &mtr);
4694
4695
			if (rec != NULL) {
4696
				ibool unsigned_type = (
4697
					dfield->col->prtype & DATA_UNSIGNED);
4698
4699
				*value = row_search_autoinc_read_column(
4700
					index, rec, i, unsigned_type);
4701
			}
4702
		}
4703
4704
		btr_pcur_close(&pcur);
4705
4706
		mtr_commit(&mtr);
4707
	} else {
4708
		error = DB_RECORD_NOT_FOUND;
4709
	}
4710
4711
	return(error);
4712
}