~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/row/row0umod.c

  • Committer: Monty Taylor
  • Date: 2009-03-22 07:55:08 UTC
  • mto: (960.5.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 961.
  • Revision ID: mordred@inaugust.com-20090322075508-1h34cksq2knhaxc3
Removed global.h from a header.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
4
4
 
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
13
13
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
Place, Suite 330, Boston, MA 02111-1307 USA
16
16
 
17
17
*****************************************************************************/
18
18
 
19
 
/**************************************************//**
20
 
@file row/row0umod.c
 
19
/******************************************************
21
20
Undo modify of a row
22
21
 
23
22
Created 2/27/1997 Heikki Tuuri
58
57
some of its fields were changed. Now, it is possible that the delete marked
59
58
version has become obsolete at the time the undo is started. */
60
59
 
61
 
/*************************************************************************
62
 
IMPORTANT NOTE: Any operation that generates redo MUST check that there
63
 
is enough space in the redo log before for that operation. This is
64
 
done by calling log_free_check(). The reason for checking the
65
 
availability of the redo log space before the start of the operation is
66
 
that we MUST not hold any synchonization objects when performing the
67
 
check.
68
 
If you make a change in this module make sure that no codepath is
69
 
introduced where a call to log_free_check() is bypassed. */
70
 
 
71
 
/***********************************************************//**
 
60
/***************************************************************
72
61
Checks if also the previous version of the clustered index record was
73
62
modified or inserted by the same transaction, and its undo number is such
74
 
that it should be undone in the same rollback.
75
 
@return TRUE if also previous modify or insert of this row should be undone */
76
 
static
 
63
that it should be undone in the same rollback. */
 
64
UNIV_INLINE
77
65
ibool
78
66
row_undo_mod_undo_also_prev_vers(
79
67
/*=============================*/
80
 
        undo_node_t*    node,   /*!< in: row undo node */
81
 
        undo_no_t*      undo_no)/*!< out: the undo number */
 
68
                                /* out: TRUE if also previous modify or
 
69
                                insert of this row should be undone */
 
70
        undo_node_t*    node,   /* in: row undo node */
 
71
        dulint*         undo_no)/* out: the undo number */
82
72
{
83
73
        trx_undo_rec_t* undo_rec;
84
74
        trx_t*          trx;
85
75
 
86
76
        trx = node->trx;
87
77
 
88
 
        if (node->new_trx_id != trx->id) {
 
78
        if (0 != ut_dulint_cmp(node->new_trx_id, trx->id)) {
89
79
 
90
 
                *undo_no = 0;
 
80
                *undo_no = ut_dulint_zero;
91
81
                return(FALSE);
92
82
        }
93
83
 
95
85
 
96
86
        *undo_no = trx_undo_rec_get_undo_no(undo_rec);
97
87
 
98
 
        return(trx->roll_limit <= *undo_no);
 
88
        return(ut_dulint_cmp(trx->roll_limit, *undo_no) <= 0);
99
89
}
100
90
 
101
 
/***********************************************************//**
102
 
Undoes a modify in a clustered index record.
103
 
@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
 
91
/***************************************************************
 
92
Undoes a modify in a clustered index record. */
104
93
static
105
94
ulint
106
95
row_undo_mod_clust_low(
107
96
/*===================*/
108
 
        undo_node_t*    node,   /*!< in: row undo node */
109
 
        que_thr_t*      thr,    /*!< in: query thread */
110
 
        mtr_t*          mtr,    /*!< in: mtr; must be committed before
 
97
                                /* out: DB_SUCCESS, DB_FAIL, or error code:
 
98
                                we may run out of file space */
 
99
        undo_node_t*    node,   /* in: row undo node */
 
100
        que_thr_t*      thr,    /* in: query thread */
 
101
        mtr_t*          mtr,    /* in: mtr; must be committed before
111
102
                                latching any further pages */
112
 
        ulint           mode)   /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
 
103
        ulint           mode)   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
113
104
{
114
105
        btr_pcur_t*     pcur;
115
106
        btr_cur_t*      btr_cur;
116
107
        ulint           err;
117
 
#ifdef UNIV_DEBUG
118
108
        ibool           success;
119
 
#endif /* UNIV_DEBUG */
120
109
 
121
110
        pcur = &(node->pcur);
122
111
        btr_cur = btr_pcur_get_btr_cur(pcur);
123
112
 
124
 
#ifdef UNIV_DEBUG
125
 
        success =
126
 
#endif /* UNIV_DEBUG */
127
 
        btr_pcur_restore_position(mode, pcur, mtr);
 
113
        success = btr_pcur_restore_position(mode, pcur, mtr);
128
114
 
129
115
        ut_ad(success);
130
116
 
157
143
        return(err);
158
144
}
159
145
 
160
 
/***********************************************************//**
161
 
Removes a clustered index record after undo if possible.
162
 
This is attempted when the record was inserted by updating a
163
 
delete-marked record and there no longer exist transactions
164
 
that would see the delete-marked record.  In other words, we
165
 
roll back the insert by purging the record.
166
 
@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
 
146
/***************************************************************
 
147
Removes a clustered index record after undo if possible. */
167
148
static
168
149
ulint
169
150
row_undo_mod_remove_clust_low(
170
151
/*==========================*/
171
 
        undo_node_t*    node,   /*!< in: row undo node */
172
 
        que_thr_t*      thr,    /*!< in: query thread */
173
 
        mtr_t*          mtr,    /*!< in: mtr */
174
 
        ulint           mode)   /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
 
152
                                /* out: DB_SUCCESS, DB_FAIL, or error code:
 
153
                                we may run out of file space */
 
154
        undo_node_t*    node,   /* in: row undo node */
 
155
        que_thr_t*      thr __attribute__((unused)), /* in: query thread */
 
156
        mtr_t*          mtr,    /* in: mtr */
 
157
        ulint           mode)   /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
175
158
{
176
159
        btr_pcur_t*     pcur;
177
160
        btr_cur_t*      btr_cur;
178
161
        ulint           err;
179
162
        ibool           success;
180
163
 
181
 
        ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
182
164
        pcur = &(node->pcur);
183
165
        btr_cur = btr_pcur_get_btr_cur(pcur);
184
166
 
210
192
        } else {
211
193
                ut_ad(mode == BTR_MODIFY_TREE);
212
194
 
213
 
                /* This operation is analogous to purge, we can free also
214
 
                inherited externally stored fields */
 
195
                /* Note that since this operation is analogous to purge,
 
196
                we can free also inherited externally stored fields:
 
197
                hence the RB_NONE in the call below */
215
198
 
216
 
                btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
217
 
                                           thr_is_recv(thr)
218
 
                                           ? RB_RECOVERY_PURGE_REC
219
 
                                           : RB_NONE, mtr);
 
199
                btr_cur_pessimistic_delete(&err, FALSE, btr_cur, RB_NONE, mtr);
220
200
 
221
201
                /* The delete operation may fail if we have little
222
202
                file space left: TODO: easiest to crash the database
226
206
        return(err);
227
207
}
228
208
 
229
 
/***********************************************************//**
 
209
/***************************************************************
230
210
Undoes a modify in a clustered index record. Sets also the node state for the
231
 
next round of undo.
232
 
@return DB_SUCCESS or error code: we may run out of file space */
 
211
next round of undo. */
233
212
static
234
213
ulint
235
214
row_undo_mod_clust(
236
215
/*===============*/
237
 
        undo_node_t*    node,   /*!< in: row undo node */
238
 
        que_thr_t*      thr)    /*!< in: query thread */
 
216
                                /* out: DB_SUCCESS or error code: we may run
 
217
                                out of file space */
 
218
        undo_node_t*    node,   /* in: row undo node */
 
219
        que_thr_t*      thr)    /* in: query thread */
239
220
{
240
221
        btr_pcur_t*     pcur;
241
222
        mtr_t           mtr;
242
223
        ulint           err;
243
224
        ibool           success;
244
225
        ibool           more_vers;
245
 
        undo_no_t       new_undo_no;
 
226
        dulint          new_undo_no;
246
227
 
247
228
        ut_ad(node && thr);
248
229
 
249
 
        log_free_check();
250
 
 
251
230
        /* Check if also the previous version of the clustered index record
252
231
        should be undone in this same rollback operation */
253
232
 
317
296
        return(err);
318
297
}
319
298
 
320
 
/***********************************************************//**
321
 
Delete marks or removes a secondary index entry if found.
322
 
@return DB_SUCCESS, DB_FAIL, or DB_OUT_OF_FILE_SPACE */
 
299
/***************************************************************
 
300
Delete marks or removes a secondary index entry if found. */
323
301
static
324
302
ulint
325
303
row_undo_mod_del_mark_or_remove_sec_low(
326
304
/*====================================*/
327
 
        undo_node_t*    node,   /*!< in: row undo node */
328
 
        que_thr_t*      thr,    /*!< in: query thread */
329
 
        dict_index_t*   index,  /*!< in: index */
330
 
        dtuple_t*       entry,  /*!< in: index entry */
331
 
        ulint           mode)   /*!< in: latch mode BTR_MODIFY_LEAF or
 
305
                                /* out: DB_SUCCESS, DB_FAIL, or
 
306
                                DB_OUT_OF_FILE_SPACE */
 
307
        undo_node_t*    node,   /* in: row undo node */
 
308
        que_thr_t*      thr,    /* in: query thread */
 
309
        dict_index_t*   index,  /* in: index */
 
310
        dtuple_t*       entry,  /* in: index entry */
 
311
        ulint           mode)   /* in: latch mode BTR_MODIFY_LEAF or
332
312
                                BTR_MODIFY_TREE */
333
313
{
334
 
        btr_pcur_t              pcur;
335
 
        btr_cur_t*              btr_cur;
336
 
        ibool                   success;
337
 
        ibool                   old_has;
338
 
        ulint                   err;
339
 
        mtr_t                   mtr;
340
 
        mtr_t                   mtr_vers;
341
 
        enum row_search_result  search_result;
 
314
        ibool           found;
 
315
        btr_pcur_t      pcur;
 
316
        btr_cur_t*      btr_cur;
 
317
        ibool           success;
 
318
        ibool           old_has;
 
319
        ulint           err;
 
320
        mtr_t           mtr;
 
321
        mtr_t           mtr_vers;
342
322
 
343
323
        log_free_check();
344
324
        mtr_start(&mtr);
345
325
 
 
326
        found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
 
327
 
346
328
        btr_cur = btr_pcur_get_btr_cur(&pcur);
347
329
 
348
 
        ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
349
 
 
350
 
        search_result = row_search_index_entry(index, entry, mode,
351
 
                                               &pcur, &mtr);
352
 
 
353
 
        switch (UNIV_EXPECT(search_result, ROW_FOUND)) {
354
 
        case ROW_NOT_FOUND:
 
330
        if (!found) {
355
331
                /* In crash recovery, the secondary index record may
356
332
                be missing if the UPDATE did not have time to insert
357
333
                the secondary index records before the crash.  When we
362
338
                before it has inserted all updated secondary index
363
339
                records, then the undo will not find those records. */
364
340
 
365
 
                err = DB_SUCCESS;
366
 
                goto func_exit;
367
 
        case ROW_FOUND:
368
 
                break;
369
 
        case ROW_BUFFERED:
370
 
        case ROW_NOT_DELETED_REF:
371
 
                /* These are invalid outcomes, because the mode passed
372
 
                to row_search_index_entry() did not include any of the
373
 
                flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
374
 
                ut_error;
 
341
                btr_pcur_close(&pcur);
 
342
                mtr_commit(&mtr);
 
343
 
 
344
                return(DB_SUCCESS);
375
345
        }
376
346
 
377
347
        /* We should remove the index record if no prior version of the row,
404
374
                } else {
405
375
                        ut_ad(mode == BTR_MODIFY_TREE);
406
376
 
407
 
                        /* No need to distinguish RB_RECOVERY_PURGE here,
408
 
                        because we are deleting a secondary index record:
409
 
                        the distinction between RB_NORMAL and
410
 
                        RB_RECOVERY_PURGE only matters when deleting a
411
 
                        record that contains externally stored
 
377
                        /* No need to distinguish RB_RECOVERY here, because we
 
378
                        are deleting a secondary index record: the distinction
 
379
                        between RB_NORMAL and RB_RECOVERY only matters when
 
380
                        deleting a record that contains externally stored
412
381
                        columns. */
413
382
                        ut_ad(!dict_index_is_clust(index));
414
383
                        btr_cur_pessimistic_delete(&err, FALSE, btr_cur,
421
390
        }
422
391
 
423
392
        btr_pcur_commit_specify_mtr(&(node->pcur), &mtr_vers);
424
 
 
425
 
func_exit:
426
393
        btr_pcur_close(&pcur);
427
394
        mtr_commit(&mtr);
428
395
 
429
396
        return(err);
430
397
}
431
398
 
432
 
/***********************************************************//**
 
399
/***************************************************************
433
400
Delete marks or removes a secondary index entry if found.
434
401
NOTE that if we updated the fields of a delete-marked secondary index record
435
402
so that alphabetically they stayed the same, e.g., 'abc' -> 'aBc', we cannot
436
403
return to the original values because we do not know them. But this should
437
404
not cause problems because in row0sel.c, in queries we always retrieve the
438
405
clustered index record or an earlier version of it, if the secondary index
439
 
record through which we do the search is delete-marked.
440
 
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
406
record through which we do the search is delete-marked. */
441
407
static
442
408
ulint
443
409
row_undo_mod_del_mark_or_remove_sec(
444
410
/*================================*/
445
 
        undo_node_t*    node,   /*!< in: row undo node */
446
 
        que_thr_t*      thr,    /*!< in: query thread */
447
 
        dict_index_t*   index,  /*!< in: index */
448
 
        dtuple_t*       entry)  /*!< in: index entry */
 
411
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
412
        undo_node_t*    node,   /* in: row undo node */
 
413
        que_thr_t*      thr,    /* in: query thread */
 
414
        dict_index_t*   index,  /* in: index */
 
415
        dtuple_t*       entry)  /* in: index entry */
449
416
{
450
417
        ulint   err;
451
418
 
461
428
        return(err);
462
429
}
463
430
 
464
 
/***********************************************************//**
 
431
/***************************************************************
465
432
Delete unmarks a secondary index entry which must be found. It might not be
466
433
delete-marked at the moment, but it does not harm to unmark it anyway. We also
467
434
need to update the fields of the secondary index record if we updated its
468
 
fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'.
469
 
@return DB_FAIL or DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
435
fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'. */
470
436
static
471
437
ulint
472
438
row_undo_mod_del_unmark_sec_and_undo_update(
473
439
/*========================================*/
474
 
        ulint           mode,   /*!< in: search mode: BTR_MODIFY_LEAF or
 
440
                                /* out: DB_FAIL or DB_SUCCESS or
 
441
                                DB_OUT_OF_FILE_SPACE */
 
442
        ulint           mode,   /* in: search mode: BTR_MODIFY_LEAF or
475
443
                                BTR_MODIFY_TREE */
476
 
        que_thr_t*      thr,    /*!< in: query thread */
477
 
        dict_index_t*   index,  /*!< in: index */
478
 
        const dtuple_t* entry)  /*!< in: index entry */
 
444
        que_thr_t*      thr,    /* in: query thread */
 
445
        dict_index_t*   index,  /* in: index */
 
446
        dtuple_t*       entry)  /* in: index entry */
479
447
{
480
 
        mem_heap_t*             heap;
481
 
        btr_pcur_t              pcur;
482
 
        btr_cur_t*              btr_cur;
483
 
        upd_t*                  update;
484
 
        ulint                   err             = DB_SUCCESS;
485
 
        big_rec_t*              dummy_big_rec;
486
 
        mtr_t                   mtr;
487
 
        trx_t*                  trx             = thr_get_trx(thr);
488
 
        enum row_search_result  search_result;
 
448
        mem_heap_t*     heap;
 
449
        btr_pcur_t      pcur;
 
450
        upd_t*          update;
 
451
        ulint           err             = DB_SUCCESS;
 
452
        big_rec_t*      dummy_big_rec;
 
453
        mtr_t           mtr;
 
454
        trx_t*          trx             = thr_get_trx(thr);
489
455
 
490
456
        /* Ignore indexes that are being created. */
491
457
        if (UNIV_UNLIKELY(*index->name == TEMP_INDEX_PREFIX)) {
496
462
        log_free_check();
497
463
        mtr_start(&mtr);
498
464
 
499
 
        ut_ad(mode == BTR_MODIFY_TREE || mode == BTR_MODIFY_LEAF);
500
 
 
501
 
        search_result = row_search_index_entry(index, entry, mode,
502
 
                                               &pcur, &mtr);
503
 
 
504
 
        switch (search_result) {
505
 
        case ROW_BUFFERED:
506
 
        case ROW_NOT_DELETED_REF:
507
 
                /* These are invalid outcomes, because the mode passed
508
 
                to row_search_index_entry() did not include any of the
509
 
                flags BTR_INSERT, BTR_DELETE, or BTR_DELETE_MARK. */
510
 
                ut_error;
511
 
        case ROW_NOT_FOUND:
 
465
        if (UNIV_UNLIKELY(!row_search_index_entry(index, entry,
 
466
                                                  mode, &pcur, &mtr))) {
512
467
                fputs("InnoDB: error in sec index entry del undo in\n"
513
468
                      "InnoDB: ", stderr);
514
469
                dict_index_name_print(stderr, trx, index);
523
478
                fputs("\n"
524
479
                      "InnoDB: Submit a detailed bug report"
525
480
                      " to http://bugs.mysql.com\n", stderr);
526
 
                break;
527
 
        case ROW_FOUND:
528
 
                btr_cur = btr_pcur_get_btr_cur(&pcur);
 
481
        } else {
 
482
                btr_cur_t*      btr_cur = btr_pcur_get_btr_cur(&pcur);
 
483
 
529
484
                err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
530
485
                                                   btr_cur, FALSE, thr, &mtr);
531
486
                ut_a(err == DB_SUCCESS);
568
523
        return(err);
569
524
}
570
525
 
571
 
/***********************************************************//**
572
 
Undoes a modify in secondary indexes when undo record type is UPD_DEL.
573
 
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
526
/***************************************************************
 
527
Undoes a modify in secondary indexes when undo record type is UPD_DEL. */
574
528
static
575
529
ulint
576
530
row_undo_mod_upd_del_sec(
577
531
/*=====================*/
578
 
        undo_node_t*    node,   /*!< in: row undo node */
579
 
        que_thr_t*      thr)    /*!< in: query thread */
 
532
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
533
        undo_node_t*    node,   /* in: row undo node */
 
534
        que_thr_t*      thr)    /* in: query thread */
580
535
{
581
536
        mem_heap_t*     heap;
582
537
        dtuple_t*       entry;
583
538
        dict_index_t*   index;
584
539
        ulint           err     = DB_SUCCESS;
585
540
 
586
 
        ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
587
541
        heap = mem_heap_create(1024);
588
542
 
589
543
        while (node->index != NULL) {
601
555
                        does not exist.  However, this situation may
602
556
                        only occur during the rollback of incomplete
603
557
                        transactions. */
604
 
                        ut_a(thr_is_recv(thr));
 
558
                        ut_a(trx_is_recv(thr_get_trx(thr)));
605
559
                } else {
606
560
                        err = row_undo_mod_del_mark_or_remove_sec(
607
561
                                node, thr, index, entry);
622
576
        return(err);
623
577
}
624
578
 
625
 
/***********************************************************//**
626
 
Undoes a modify in secondary indexes when undo record type is DEL_MARK.
627
 
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
579
/***************************************************************
 
580
Undoes a modify in secondary indexes when undo record type is DEL_MARK. */
628
581
static
629
582
ulint
630
583
row_undo_mod_del_mark_sec(
631
584
/*======================*/
632
 
        undo_node_t*    node,   /*!< in: row undo node */
633
 
        que_thr_t*      thr)    /*!< in: query thread */
 
585
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
586
        undo_node_t*    node,   /* in: row undo node */
 
587
        que_thr_t*      thr)    /* in: query thread */
634
588
{
635
589
        mem_heap_t*     heap;
636
590
        dtuple_t*       entry;
667
621
        return(DB_SUCCESS);
668
622
}
669
623
 
670
 
/***********************************************************//**
671
 
Undoes a modify in secondary indexes when undo record type is UPD_EXIST.
672
 
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
624
/***************************************************************
 
625
Undoes a modify in secondary indexes when undo record type is UPD_EXIST. */
673
626
static
674
627
ulint
675
628
row_undo_mod_upd_exist_sec(
676
629
/*=======================*/
677
 
        undo_node_t*    node,   /*!< in: row undo node */
678
 
        que_thr_t*      thr)    /*!< in: query thread */
 
630
                                /* out: DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
 
631
        undo_node_t*    node,   /* in: row undo node */
 
632
        que_thr_t*      thr)    /* in: query thread */
679
633
{
680
634
        mem_heap_t*     heap;
681
635
        dtuple_t*       entry;
699
653
                        /* Build the newest version of the index entry */
700
654
                        entry = row_build_index_entry(node->row, node->ext,
701
655
                                                      index, heap);
702
 
                        if (UNIV_UNLIKELY(!entry)) {
703
 
                                /* The server must have crashed in
704
 
                                row_upd_clust_rec_by_insert(), in
705
 
                                row_ins_index_entry_low() before
706
 
                                btr_store_big_rec_extern_fields()
707
 
                                has written the externally stored columns
708
 
                                (BLOBs) of the new clustered index entry. */
709
 
 
710
 
                                /* The table must be in DYNAMIC or COMPRESSED
711
 
                                format.  REDUNDANT and COMPACT formats
712
 
                                store a local 768-byte prefix of each
713
 
                                externally stored column. */
714
 
                                ut_a(dict_table_get_format(index->table)
715
 
                                     >= DICT_TF_FORMAT_ZIP);
716
 
 
717
 
                                /* This is only legitimate when
718
 
                                rolling back an incomplete transaction
719
 
                                after crash recovery. */
720
 
                                ut_a(thr_get_trx(thr)->is_recovered);
721
 
 
722
 
                                /* The server must have crashed before
723
 
                                completing the insert of the new
724
 
                                clustered index entry and before
725
 
                                inserting to the secondary indexes.
726
 
                                Because node->row was not yet written
727
 
                                to this index, we can ignore it.  But
728
 
                                we must restore node->undo_row. */
729
 
                        } else {
730
 
                                /* NOTE that if we updated the fields of a
731
 
                                delete-marked secondary index record so that
732
 
                                alphabetically they stayed the same, e.g.,
733
 
                                'abc' -> 'aBc', we cannot return to the
734
 
                                original values because we do not know them.
735
 
                                But this should not cause problems because
736
 
                                in row0sel.c, in queries we always retrieve
737
 
                                the clustered index record or an earlier
738
 
                                version of it, if the secondary index record
739
 
                                through which we do the search is
740
 
                                delete-marked. */
741
 
 
742
 
                                err = row_undo_mod_del_mark_or_remove_sec(
743
 
                                        node, thr, index, entry);
744
 
                                if (err != DB_SUCCESS) {
745
 
                                        mem_heap_free(heap);
746
 
 
747
 
                                        return(err);
748
 
                                }
749
 
 
750
 
                                mem_heap_empty(heap);
 
656
                        ut_a(entry);
 
657
                        /* NOTE that if we updated the fields of a
 
658
                        delete-marked secondary index record so that
 
659
                        alphabetically they stayed the same, e.g.,
 
660
                        'abc' -> 'aBc', we cannot return to the original
 
661
                        values because we do not know them. But this should
 
662
                        not cause problems because in row0sel.c, in queries
 
663
                        we always retrieve the clustered index record or an
 
664
                        earlier version of it, if the secondary index record
 
665
                        through which we do the search is delete-marked. */
 
666
 
 
667
                        err = row_undo_mod_del_mark_or_remove_sec(node, thr,
 
668
                                                                  index,
 
669
                                                                  entry);
 
670
                        if (err != DB_SUCCESS) {
 
671
                                mem_heap_free(heap);
 
672
 
 
673
                                return(err);
751
674
                        }
752
675
 
753
676
                        /* We may have to update the delete mark in the
756
679
                        the secondary index record if we updated its fields
757
680
                        but alphabetically they stayed the same, e.g.,
758
681
                        'abc' -> 'aBc'. */
 
682
                        mem_heap_empty(heap);
759
683
                        entry = row_build_index_entry(node->undo_row,
760
684
                                                      node->undo_ext,
761
685
                                                      index, heap);
783
707
        return(DB_SUCCESS);
784
708
}
785
709
 
786
 
/***********************************************************//**
 
710
/***************************************************************
787
711
Parses the row reference and other info in a modify undo log record. */
788
712
static
789
713
void
790
714
row_undo_mod_parse_undo_rec(
791
715
/*========================*/
792
 
        undo_node_t*    node,   /*!< in: row undo node */
793
 
        que_thr_t*      thr)    /*!< in: query thread */
 
716
        undo_node_t*    node,   /* in: row undo node */
 
717
        que_thr_t*      thr)    /* in: query thread */
794
718
{
795
719
        dict_index_t*   clust_index;
796
720
        byte*           ptr;
797
 
        undo_no_t       undo_no;
798
 
        table_id_t      table_id;
799
 
        trx_id_t        trx_id;
800
 
        roll_ptr_t      roll_ptr;
 
721
        dulint          undo_no;
 
722
        dulint          table_id;
 
723
        dulint          trx_id;
 
724
        dulint          roll_ptr;
801
725
        ulint           info_bits;
802
726
        ulint           type;
803
727
        ulint           cmpl_info;
843
767
        node->cmpl_info = cmpl_info;
844
768
}
845
769
 
846
 
/***********************************************************//**
847
 
Undoes a modify operation on a row of a table.
848
 
@return DB_SUCCESS or error code */
 
770
/***************************************************************
 
771
Undoes a modify operation on a row of a table. */
849
772
UNIV_INTERN
850
773
ulint
851
774
row_undo_mod(
852
775
/*=========*/
853
 
        undo_node_t*    node,   /*!< in: row undo node */
854
 
        que_thr_t*      thr)    /*!< in: query thread */
 
776
                                /* out: DB_SUCCESS or error code */
 
777
        undo_node_t*    node,   /* in: row undo node */
 
778
        que_thr_t*      thr)    /* in: query thread */
855
779
{
856
780
        ulint   err;
857
781