~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/******************************************************
2
The index tree persistent cursor
3
4
(c) 1996 Innobase Oy
5
6
Created 2/23/1996 Heikki Tuuri
7
*******************************************************/
8
9
10
/*************************************************************
11
Gets the rel_pos field for a cursor whose position has been stored. */
12
UNIV_INLINE
13
ulint
14
btr_pcur_get_rel_pos(
15
/*=================*/
16
				/* out: BTR_PCUR_ON, ... */
17
	btr_pcur_t*	cursor)	/* in: persistent cursor */
18
{
19
	ut_ad(cursor);
20
	ut_ad(cursor->old_rec);
21
	ut_ad(cursor->old_stored == BTR_PCUR_OLD_STORED);
22
	ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
23
	      || cursor->pos_state == BTR_PCUR_IS_POSITIONED);
24
25
	return(cursor->rel_pos);
26
}
27
28
/*************************************************************
29
Sets the mtr field for a pcur. */
30
UNIV_INLINE
31
void
32
btr_pcur_set_mtr(
33
/*=============*/
34
	btr_pcur_t*	cursor,	/* in: persistent cursor */
35
	mtr_t*		mtr)	/* in, own: mtr */
36
{
37
	ut_ad(cursor);
38
39
	cursor->mtr = mtr;
40
}
41
42
/*************************************************************
43
Gets the mtr field for a pcur. */
44
UNIV_INLINE
45
mtr_t*
46
btr_pcur_get_mtr(
47
/*=============*/
48
				/* out: mtr */
49
	btr_pcur_t*	cursor)	/* in: persistent cursor */
50
{
51
	ut_ad(cursor);
52
53
	return(cursor->mtr);
54
}
55
56
/*************************************************************
57
Returns the btr cursor component of a persistent cursor. */
58
UNIV_INLINE
59
btr_cur_t*
60
btr_pcur_get_btr_cur(
61
/*=================*/
62
				/* out: pointer to btr cursor component */
63
	btr_pcur_t*	cursor)	/* in: persistent cursor */
64
{
65
	return(&(cursor->btr_cur));
66
}
67
68
/*************************************************************
69
Returns the page cursor component of a persistent cursor. */
70
UNIV_INLINE
71
page_cur_t*
72
btr_pcur_get_page_cur(
73
/*==================*/
74
				/* out: pointer to page cursor component */
75
	btr_pcur_t*	cursor)	/* in: persistent cursor */
76
{
77
	return(btr_cur_get_page_cur(&(cursor->btr_cur)));
78
}
79
80
/*************************************************************
81
Returns the page of a persistent cursor. */
82
UNIV_INLINE
83
page_t*
84
btr_pcur_get_page(
85
/*==============*/
86
				/* out: pointer to the page */
87
	btr_pcur_t*	cursor)	/* in: persistent cursor */
88
{
89
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
90
91
	return(page_cur_get_page(btr_pcur_get_page_cur(cursor)));
92
}
93
94
/*************************************************************
95
Returns the record of a persistent cursor. */
96
UNIV_INLINE
97
rec_t*
98
btr_pcur_get_rec(
99
/*=============*/
100
				/* out: pointer to the record */
101
	btr_pcur_t*	cursor)	/* in: persistent cursor */
102
{
103
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
104
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
105
106
	return(page_cur_get_rec(btr_pcur_get_page_cur(cursor)));
107
}
108
109
/******************************************************************
110
Gets the up_match value for a pcur after a search. */
111
UNIV_INLINE
112
ulint
113
btr_pcur_get_up_match(
114
/*==================*/
115
				/* out: number of matched fields at the cursor
116
				or to the right if search mode was PAGE_CUR_GE,
117
				otherwise undefined */
118
	btr_pcur_t*	cursor) /* in: memory buffer for persistent cursor */
119
{
120
	btr_cur_t*	btr_cursor;
121
122
	ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
123
	      || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
124
125
	btr_cursor = btr_pcur_get_btr_cur(cursor);
126
127
	ut_ad(btr_cursor->up_match != ULINT_UNDEFINED);
128
129
	return(btr_cursor->up_match);
130
}
131
132
/******************************************************************
133
Gets the low_match value for a pcur after a search. */
134
UNIV_INLINE
135
ulint
136
btr_pcur_get_low_match(
137
/*===================*/
138
				/* out: number of matched fields at the cursor
139
				or to the right if search mode was PAGE_CUR_LE,
140
				otherwise undefined */
141
	btr_pcur_t*	cursor) /* in: memory buffer for persistent cursor */
142
{
143
	btr_cur_t*	btr_cursor;
144
145
	ut_ad((cursor->pos_state == BTR_PCUR_WAS_POSITIONED)
146
	      || (cursor->pos_state == BTR_PCUR_IS_POSITIONED));
147
148
	btr_cursor = btr_pcur_get_btr_cur(cursor);
149
	ut_ad(btr_cursor->low_match != ULINT_UNDEFINED);
150
151
	return(btr_cursor->low_match);
152
}
153
154
/*************************************************************
155
Checks if the persistent cursor is after the last user record on
156
a page. */
157
UNIV_INLINE
158
ibool
159
btr_pcur_is_after_last_on_page(
160
/*===========================*/
161
	btr_pcur_t*	cursor,	/* in: persistent cursor */
162
	mtr_t*		mtr)	/* in: mtr */
163
{
164
	UT_NOT_USED(mtr);
165
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
166
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
167
168
	return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
169
}
170
171
/*************************************************************
172
Checks if the persistent cursor is before the first user record on
173
a page. */
174
UNIV_INLINE
175
ibool
176
btr_pcur_is_before_first_on_page(
177
/*=============================*/
178
	btr_pcur_t*	cursor,	/* in: persistent cursor */
179
	mtr_t*		mtr)	/* in: mtr */
180
{
181
	UT_NOT_USED(mtr);
182
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
183
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
184
185
	return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
186
}
187
188
/*************************************************************
189
Checks if the persistent cursor is on a user record. */
190
UNIV_INLINE
191
ibool
192
btr_pcur_is_on_user_rec(
193
/*====================*/
194
	btr_pcur_t*	cursor,	/* in: persistent cursor */
195
	mtr_t*		mtr)	/* in: mtr */
196
{
197
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
198
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
199
200
	if ((btr_pcur_is_before_first_on_page(cursor, mtr))
201
	    || (btr_pcur_is_after_last_on_page(cursor, mtr))) {
202
203
		return(FALSE);
204
	}
205
206
	return(TRUE);
207
}
208
209
/*************************************************************
210
Checks if the persistent cursor is before the first user record in
211
the index tree. */
212
UNIV_INLINE
213
ibool
214
btr_pcur_is_before_first_in_tree(
215
/*=============================*/
216
	btr_pcur_t*	cursor,	/* in: persistent cursor */
217
	mtr_t*		mtr)	/* in: mtr */
218
{
219
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
220
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
221
222
	if (btr_page_get_prev(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
223
224
		return(FALSE);
225
	}
226
227
	return(page_cur_is_before_first(btr_pcur_get_page_cur(cursor)));
228
}
229
230
/*************************************************************
231
Checks if the persistent cursor is after the last user record in
232
the index tree. */
233
UNIV_INLINE
234
ibool
235
btr_pcur_is_after_last_in_tree(
236
/*===========================*/
237
	btr_pcur_t*	cursor,	/* in: persistent cursor */
238
	mtr_t*		mtr)	/* in: mtr */
239
{
240
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
241
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
242
243
	if (btr_page_get_next(btr_pcur_get_page(cursor), mtr) != FIL_NULL) {
244
245
		return(FALSE);
246
	}
247
248
	return(page_cur_is_after_last(btr_pcur_get_page_cur(cursor)));
249
}
250
251
/*************************************************************
252
Moves the persistent cursor to the next record on the same page. */
253
UNIV_INLINE
254
void
255
btr_pcur_move_to_next_on_page(
256
/*==========================*/
257
	btr_pcur_t*	cursor,	/* in: persistent cursor */
258
	mtr_t*		mtr)	/* in: mtr */
259
{
260
	UT_NOT_USED(mtr);
261
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
262
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
263
264
	page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
265
266
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
267
}
268
269
/*************************************************************
270
Moves the persistent cursor to the previous record on the same page. */
271
UNIV_INLINE
272
void
273
btr_pcur_move_to_prev_on_page(
274
/*==========================*/
275
	btr_pcur_t*	cursor,	/* in: persistent cursor */
276
	mtr_t*		mtr)	/* in: mtr */
277
{
278
	UT_NOT_USED(mtr);
279
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
280
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
281
282
	page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
283
284
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
285
}
286
287
/*************************************************************
288
Moves the persistent cursor to the last record on the same page. */
289
UNIV_INLINE
290
void
291
btr_pcur_move_to_last_on_page(
292
/*==========================*/
293
	btr_pcur_t*	cursor,	/* in: persistent cursor */
294
	mtr_t*		mtr)	/* in: mtr */
295
{
296
	UT_NOT_USED(mtr);
297
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
298
299
	page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
300
				btr_pcur_get_page_cur(cursor));
301
302
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
303
}
304
305
/*************************************************************
306
Moves the persistent cursor to the next user record in the tree. If no user
307
records are left, the cursor ends up 'after last in tree'. */
308
UNIV_INLINE
309
ibool
310
btr_pcur_move_to_next_user_rec(
311
/*===========================*/
312
				/* out: TRUE if the cursor moved forward,
313
				ending on a user record */
314
	btr_pcur_t*	cursor,	/* in: persistent cursor; NOTE that the
315
				function may release the page latch */
316
	mtr_t*		mtr)	/* in: mtr */
317
{
318
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
319
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
320
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
321
loop:
322
	if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
323
324
		if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
325
326
			return(FALSE);
327
		}
328
329
		btr_pcur_move_to_next_page(cursor, mtr);
330
	} else {
331
		btr_pcur_move_to_next_on_page(cursor, mtr);
332
	}
333
334
	if (btr_pcur_is_on_user_rec(cursor, mtr)) {
335
336
		return(TRUE);
337
	}
338
339
	goto loop;
340
}
341
342
/*************************************************************
343
Moves the persistent cursor to the next record in the tree. If no records are
344
left, the cursor stays 'after last in tree'. */
345
UNIV_INLINE
346
ibool
347
btr_pcur_move_to_next(
348
/*==================*/
349
				/* out: TRUE if the cursor was not after last
350
				in tree */
351
	btr_pcur_t*	cursor,	/* in: persistent cursor; NOTE that the
352
				function may release the page latch */
353
	mtr_t*		mtr)	/* in: mtr */
354
{
355
	ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
356
	ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
357
358
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
359
360
	if (btr_pcur_is_after_last_on_page(cursor, mtr)) {
361
362
		if (btr_pcur_is_after_last_in_tree(cursor, mtr)) {
363
364
			return(FALSE);
365
		}
366
367
		btr_pcur_move_to_next_page(cursor, mtr);
368
369
		return(TRUE);
370
	}
371
372
	btr_pcur_move_to_next_on_page(cursor, mtr);
373
374
	return(TRUE);
375
}
376
377
/******************************************************************
378
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
379
that is, the cursor becomes detached. If there have been modifications
380
to the page where pcur is positioned, this can be used instead of
381
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
382
before calling this, if restoration of cursor is wanted later. */
383
UNIV_INLINE
384
void
385
btr_pcur_commit(
386
/*============*/
387
	btr_pcur_t*	pcur)	/* in: persistent cursor */
388
{
389
	ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
390
391
	pcur->latch_mode = BTR_NO_LATCHES;
392
393
	mtr_commit(pcur->mtr);
394
395
	pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
396
}
397
398
/******************************************************************
399
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
400
UNIV_INLINE
401
void
402
btr_pcur_commit_specify_mtr(
403
/*========================*/
404
	btr_pcur_t*	pcur,	/* in: persistent cursor */
405
	mtr_t*		mtr)	/* in: mtr to commit */
406
{
407
	ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
408
409
	pcur->latch_mode = BTR_NO_LATCHES;
410
411
	mtr_commit(mtr);
412
413
	pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
414
}
415
416
/******************************************************************
417
Sets the pcur latch mode to BTR_NO_LATCHES. */
418
UNIV_INLINE
419
void
420
btr_pcur_detach(
421
/*============*/
422
	btr_pcur_t*	pcur)	/* in: persistent cursor */
423
{
424
	ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
425
426
	pcur->latch_mode = BTR_NO_LATCHES;
427
428
	pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
429
}
430
431
/******************************************************************
432
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES. */
433
UNIV_INLINE
434
ibool
435
btr_pcur_is_detached(
436
/*=================*/
437
				/* out: TRUE if detached */
438
	btr_pcur_t*	pcur)	/* in: persistent cursor */
439
{
440
	if (pcur->latch_mode == BTR_NO_LATCHES) {
441
442
		return(TRUE);
443
	}
444
445
	return(FALSE);
446
}
447
448
/******************************************************************
449
Sets the old_rec_buf field to NULL. */
450
UNIV_INLINE
451
void
452
btr_pcur_init(
453
/*==========*/
454
	btr_pcur_t*	pcur)	/* in: persistent cursor */
455
{
456
	pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
457
	pcur->old_rec_buf = NULL;
458
	pcur->old_rec = NULL;
459
}
460
461
/******************************************************************
462
Initializes and opens a persistent cursor to an index tree. It should be
463
closed with btr_pcur_close. */
464
UNIV_INLINE
465
void
466
btr_pcur_open(
467
/*==========*/
468
	dict_index_t*	index,	/* in: index */
469
	dtuple_t*	tuple,	/* in: tuple on which search done */
470
	ulint		mode,	/* in: PAGE_CUR_L, ...;
471
				NOTE that if the search is made using a unique
472
				prefix of a record, mode should be
473
				PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
474
				may end up on the previous page from the
475
				record! */
476
	ulint		latch_mode,/* in: BTR_SEARCH_LEAF, ... */
477
	btr_pcur_t*	cursor, /* in: memory buffer for persistent cursor */
478
	mtr_t*		mtr)	/* in: mtr */
479
{
480
	btr_cur_t*	btr_cursor;
481
482
	/* Initialize the cursor */
483
484
	btr_pcur_init(cursor);
485
486
	cursor->latch_mode = latch_mode;
487
	cursor->search_mode = mode;
488
489
	/* Search with the tree cursor */
490
491
	btr_cursor = btr_pcur_get_btr_cur(cursor);
492
493
	btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
494
				    btr_cursor, 0, mtr);
495
	cursor->pos_state = BTR_PCUR_IS_POSITIONED;
496
497
	cursor->trx_if_known = NULL;
498
}
499
500
/******************************************************************
501
Opens an persistent cursor to an index tree without initializing the
502
cursor. */
503
UNIV_INLINE
504
void
505
btr_pcur_open_with_no_init(
506
/*=======================*/
507
	dict_index_t*	index,	/* in: index */
508
	dtuple_t*	tuple,	/* in: tuple on which search done */
509
	ulint		mode,	/* in: PAGE_CUR_L, ...;
510
				NOTE that if the search is made using a unique
511
				prefix of a record, mode should be
512
				PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
513
				may end up on the previous page of the
514
				record! */
515
	ulint		latch_mode,/* in: BTR_SEARCH_LEAF, ...;
516
				NOTE that if has_search_latch != 0 then
517
				we maybe do not acquire a latch on the cursor
518
				page, but assume that the caller uses his
519
				btr search latch to protect the record! */
520
	btr_pcur_t*	cursor, /* in: memory buffer for persistent cursor */
521
	ulint		has_search_latch,/* in: latch mode the caller
522
				currently has on btr_search_latch:
523
				RW_S_LATCH, or 0 */
524
	mtr_t*		mtr)	/* in: mtr */
525
{
526
	btr_cur_t*	btr_cursor;
527
528
	cursor->latch_mode = latch_mode;
529
	cursor->search_mode = mode;
530
531
	/* Search with the tree cursor */
532
533
	btr_cursor = btr_pcur_get_btr_cur(cursor);
534
535
	btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
536
				    btr_cursor, has_search_latch, mtr);
537
	cursor->pos_state = BTR_PCUR_IS_POSITIONED;
538
539
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
540
541
	cursor->trx_if_known = NULL;
542
}
543
544
/*********************************************************************
545
Opens a persistent cursor at either end of an index. */
546
UNIV_INLINE
547
void
548
btr_pcur_open_at_index_side(
549
/*========================*/
550
	ibool		from_left,	/* in: TRUE if open to the low end,
551
					FALSE if to the high end */
552
	dict_index_t*	index,		/* in: index */
553
	ulint		latch_mode,	/* in: latch mode */
554
	btr_pcur_t*	pcur,		/* in: cursor */
555
	ibool		do_init,	/* in: TRUE if should be initialized */
556
	mtr_t*		mtr)		/* in: mtr */
557
{
558
	pcur->latch_mode = latch_mode;
559
560
	if (from_left) {
561
		pcur->search_mode = PAGE_CUR_G;
562
	} else {
563
		pcur->search_mode = PAGE_CUR_L;
564
	}
565
566
	if (do_init) {
567
		btr_pcur_init(pcur);
568
	}
569
570
	btr_cur_open_at_index_side(from_left, index, latch_mode,
571
				   btr_pcur_get_btr_cur(pcur), mtr);
572
	pcur->pos_state = BTR_PCUR_IS_POSITIONED;
573
574
	pcur->old_stored = BTR_PCUR_OLD_NOT_STORED;
575
576
	pcur->trx_if_known = NULL;
577
}
578
579
/**************************************************************************
580
Positions a cursor at a randomly chosen position within a B-tree. */
581
UNIV_INLINE
582
void
583
btr_pcur_open_at_rnd_pos(
584
/*=====================*/
585
	dict_index_t*	index,		/* in: index */
586
	ulint		latch_mode,	/* in: BTR_SEARCH_LEAF, ... */
587
	btr_pcur_t*	cursor,		/* in/out: B-tree pcur */
588
	mtr_t*		mtr)		/* in: mtr */
589
{
590
	/* Initialize the cursor */
591
592
	cursor->latch_mode = latch_mode;
593
	cursor->search_mode = PAGE_CUR_G;
594
595
	btr_pcur_init(cursor);
596
597
	btr_cur_open_at_rnd_pos(index, latch_mode,
598
				btr_pcur_get_btr_cur(cursor), mtr);
599
	cursor->pos_state = BTR_PCUR_IS_POSITIONED;
600
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
601
602
	cursor->trx_if_known = NULL;
603
}
604
605
/******************************************************************
606
Frees the possible memory heap of a persistent cursor and sets the latch
607
mode of the persistent cursor to BTR_NO_LATCHES. */
608
UNIV_INLINE
609
void
610
btr_pcur_close(
611
/*===========*/
612
	btr_pcur_t*	cursor)	/* in: persistent cursor */
613
{
614
	if (cursor->old_rec_buf != NULL) {
615
616
		mem_free(cursor->old_rec_buf);
617
618
		cursor->old_rec = NULL;
619
		cursor->old_rec_buf = NULL;
620
	}
621
622
	cursor->btr_cur.page_cur.rec = NULL;
623
	cursor->old_rec = NULL;
624
	cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
625
626
	cursor->latch_mode = BTR_NO_LATCHES;
627
	cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
628
629
	cursor->trx_if_known = NULL;
630
}