32
31
#include "fsp0fsp.h"
33
32
#include "mach0data.h"
34
35
#include "trx0undo.h"
36
#ifndef UNIV_HOTBACKUP
37
36
#include "dict0dict.h"
38
37
#include "ut0mem.h"
39
38
#include "row0ext.h"
40
39
#include "row0upd.h"
41
40
#include "que0que.h"
42
41
#include "trx0purge.h"
44
42
#include "row0row.h"
46
44
/*=========== UNDO LOG RECORD CREATION AND DECODING ====================*/
48
/**********************************************************************//**
46
/**************************************************************************
49
47
Writes the mtr log entry of the inserted undo log record on the undo log
53
51
trx_undof_page_add_undo_rec_log(
54
52
/*============================*/
55
page_t* undo_page, /*!< in: undo log page */
56
ulint old_free, /*!< in: start offset of the inserted entry */
57
ulint new_free, /*!< in: end offset of the entry */
58
mtr_t* mtr) /*!< in: mtr */
53
page_t* undo_page, /* in: undo log page */
54
ulint old_free, /* in: start offset of the inserted entry */
55
ulint new_free, /* in: end offset of the entry */
56
mtr_t* mtr) /* in: mtr */
61
59
const byte* log_end;
84
82
mlog_catenate_string(mtr, undo_page + old_free + 2, len);
87
#endif /* !UNIV_HOTBACKUP */
89
/***********************************************************//**
90
Parses a redo log record of adding an undo log record.
91
@return end of log record or NULL */
86
/***************************************************************
87
Parses a redo log record of adding an undo log record. */
94
90
trx_undo_parse_add_undo_rec(
95
91
/*========================*/
96
byte* ptr, /*!< in: buffer */
97
byte* end_ptr,/*!< in: buffer end */
98
page_t* page) /*!< in: page or NULL */
92
/* out: end of log record or NULL */
93
byte* ptr, /* in: buffer */
94
byte* end_ptr,/* in: buffer end */
95
page_t* page) /* in: page or NULL */
133
130
return(ptr + len);
136
#ifndef UNIV_HOTBACKUP
137
/**********************************************************************//**
138
Calculates the free space left for extending an undo log record.
139
@return bytes left */
133
/**************************************************************************
134
Calculates the free space left for extending an undo log record. */
144
const page_t* page, /*!< in: undo log page */
145
const byte* ptr) /*!< in: pointer to page */
139
/* out: bytes left */
140
const page_t* page, /* in: undo log page */
141
const byte* ptr) /* in: pointer to page */
147
143
/* The '- 10' is a safety margin, in case we have some small
148
144
calculation error below */
150
146
return(UNIV_PAGE_SIZE - (ptr - page) - 10 - FIL_PAGE_DATA_END);
153
/**********************************************************************//**
149
/**************************************************************************
154
150
Set the next and previous pointers in the undo page for the undo record
155
151
that was written to ptr. Update the first free value by the number of bytes
156
written for this undo record.
157
@return offset of the inserted entry on the page if succeeded, 0 if fail */
152
written for this undo record.*/
160
155
trx_undo_page_set_next_prev_and_add(
161
156
/*================================*/
162
page_t* undo_page, /*!< in/out: undo log page */
163
byte* ptr, /*!< in: ptr up to where data has been
157
/* out: offset of the inserted entry
158
on the page if succeeded, 0 if fail */
159
page_t* undo_page, /* in/out: undo log page */
160
byte* ptr, /* in: ptr up to where data has been
164
161
written on this undo page. */
165
mtr_t* mtr) /*!< in: mtr */
162
mtr_t* mtr) /* in: mtr */
167
ulint first_free; /*!< offset within undo_page */
168
ulint end_of_rec; /*!< offset within undo_page */
164
ulint first_free; /* offset within undo_page */
165
ulint end_of_rec; /* offset within undo_page */
169
166
byte* ptr_to_first_free;
170
167
/* pointer within undo_page
171
168
that points to the next free
202
199
return(first_free);
205
/**********************************************************************//**
206
Reports in the undo log of an insert of a clustered index record.
207
@return offset of the inserted entry on the page if succeed, 0 if fail */
202
/**************************************************************************
203
Reports in the undo log of an insert of a clustered index record. */
210
206
trx_undo_page_report_insert(
211
207
/*========================*/
212
page_t* undo_page, /*!< in: undo log page */
213
trx_t* trx, /*!< in: transaction */
214
dict_index_t* index, /*!< in: clustered index */
215
const dtuple_t* clust_entry, /*!< in: index entry which will be
208
/* out: offset of the inserted entry
209
on the page if succeed, 0 if fail */
210
page_t* undo_page, /* in: undo log page */
211
trx_t* trx, /* in: transaction */
212
dict_index_t* index, /* in: clustered index */
213
const dtuple_t* clust_entry, /* in: index entry which will be
216
214
inserted to the clustered index */
217
mtr_t* mtr) /*!< in: mtr */
215
mtr_t* mtr) /* in: mtr */
219
217
ulint first_free;
274
272
return(trx_undo_page_set_next_prev_and_add(undo_page, ptr, mtr));
277
/**********************************************************************//**
278
Reads from an undo log record the general parameters.
279
@return remaining part of undo log record after reading these values */
275
/**************************************************************************
276
Reads from an undo log record the general parameters. */
282
279
trx_undo_rec_get_pars(
283
280
/*==================*/
284
trx_undo_rec_t* undo_rec, /*!< in: undo log record */
285
ulint* type, /*!< out: undo record type:
281
/* out: remaining part of undo log
282
record after reading these values */
283
trx_undo_rec_t* undo_rec, /* in: undo log record */
284
ulint* type, /* out: undo record type:
286
285
TRX_UNDO_INSERT_REC, ... */
287
ulint* cmpl_info, /*!< out: compiler info, relevant only
286
ulint* cmpl_info, /* out: compiler info, relevant only
288
287
for update type records */
289
ibool* updated_extern, /*!< out: TRUE if we updated an
288
ibool* updated_extern, /* out: TRUE if we updated an
290
289
externally stored fild */
291
undo_no_t* undo_no, /*!< out: undo log record number */
292
dulint* table_id) /*!< out: table id */
290
dulint* undo_no, /* out: undo log record number */
291
dulint* table_id) /* out: table id */
321
/**********************************************************************//**
322
Reads from an undo log record a stored column value.
323
@return remaining part of undo log record after reading these values */
320
/**************************************************************************
321
Reads from an undo log record a stored column value. */
326
324
trx_undo_rec_get_col_val(
327
325
/*=====================*/
328
byte* ptr, /*!< in: pointer to remaining part of undo log record */
329
byte** field, /*!< out: pointer to stored field */
330
ulint* len, /*!< out: length of the field, or UNIV_SQL_NULL */
331
ulint* orig_len)/*!< out: original length of the locally
326
/* out: remaining part of undo log record after
327
reading these values */
328
byte* ptr, /* in: pointer to remaining part of undo log record */
329
byte** field, /* out: pointer to stored field */
330
ulint* len, /* out: length of the field, or UNIV_SQL_NULL */
331
ulint* orig_len)/* out: original length of the locally
332
332
stored part of an externally stored column, or 0 */
334
334
*len = mach_read_compressed(ptr);
370
/*******************************************************************//**
371
Builds a row reference from an undo log record.
372
@return pointer to remaining part of undo record */
370
/***********************************************************************
371
Builds a row reference from an undo log record. */
375
374
trx_undo_rec_get_row_ref(
376
375
/*=====================*/
377
byte* ptr, /*!< in: remaining part of a copy of an undo log
376
/* out: pointer to remaining part of undo
378
byte* ptr, /* in: remaining part of a copy of an undo log
378
379
record, at the start of the row reference;
379
380
NOTE that this copy of the undo log record must
380
381
be preserved as long as the row reference is
381
382
used, as we do NOT copy the data in the
383
dict_index_t* index, /*!< in: clustered index */
384
dtuple_t** ref, /*!< out, own: row reference */
385
mem_heap_t* heap) /*!< in: memory heap from which the memory
384
dict_index_t* index, /* in: clustered index */
385
dtuple_t** ref, /* out, own: row reference */
386
mem_heap_t* heap) /* in: memory heap from which the memory
386
387
needed is allocated */
416
/*******************************************************************//**
417
Skips a row reference from an undo log record.
418
@return pointer to remaining part of undo record */
417
/***********************************************************************
418
Skips a row reference from an undo log record. */
421
421
trx_undo_rec_skip_row_ref(
422
422
/*======================*/
423
byte* ptr, /*!< in: remaining part in update undo log
423
/* out: pointer to remaining part of undo
425
byte* ptr, /* in: remaining part in update undo log
424
426
record, at the start of the row reference */
425
dict_index_t* index) /*!< in: clustered index */
427
dict_index_t* index) /* in: clustered index */
446
/**********************************************************************//**
448
/**************************************************************************
447
449
Fetch a prefix of an externally stored column, for writing to the undo log
448
of an update or delete marking of a clustered index record.
450
of an update or delete marking of a clustered index record. */
452
453
trx_undo_page_fetch_ext(
453
454
/*====================*/
454
byte* ext_buf, /*!< in: a buffer of
456
byte* ext_buf, /* in: a buffer of
455
457
REC_MAX_INDEX_COL_LEN
456
458
+ BTR_EXTERN_FIELD_REF_SIZE */
457
ulint zip_size, /*!< compressed page size in bytes,
459
ulint zip_size, /* compressed page size in bytes,
458
460
or 0 for uncompressed BLOB */
459
const byte* field, /*!< in: an externally stored column */
460
ulint* len) /*!< in: length of field;
461
const byte* field, /* in: an externally stored column */
462
ulint* len) /* in: length of field;
461
463
out: used length of ext_buf */
463
465
/* Fetch the BLOB. */
476
/**********************************************************************//**
477
Writes to the undo log a prefix of an externally stored column.
478
@return undo log position */
478
/**************************************************************************
479
Writes to the undo log a prefix of an externally stored column. */
481
482
trx_undo_page_report_modify_ext(
482
483
/*============================*/
483
byte* ptr, /*!< in: undo log position,
484
/* out: undo log position */
485
byte* ptr, /* in: undo log position,
484
486
at least 15 bytes must be available */
485
byte* ext_buf, /*!< in: a buffer of
487
byte* ext_buf, /* in: a buffer of
486
488
REC_MAX_INDEX_COL_LEN
487
489
+ BTR_EXTERN_FIELD_REF_SIZE,
488
490
or NULL when should not fetch
489
491
a longer prefix */
490
ulint zip_size, /*!< compressed page size in bytes,
492
ulint zip_size, /* compressed page size in bytes,
491
493
or 0 for uncompressed BLOB */
492
const byte** field, /*!< in/out: the locally stored part of
494
const byte** field, /* in/out: the locally stored part of
493
495
the externally stored column */
494
ulint* len) /*!< in/out: length of field, in bytes */
496
ulint* len) /* in/out: length of field, in bytes */
497
499
/* If an ordering column is externally stored, we will
517
/**********************************************************************//**
519
/**************************************************************************
518
520
Reports in the undo log of an update or delete marking of a clustered index
520
@return byte offset of the inserted undo log entry on the page if
521
succeed, 0 if fail */
524
524
trx_undo_page_report_modify(
525
525
/*========================*/
526
page_t* undo_page, /*!< in: undo log page */
527
trx_t* trx, /*!< in: transaction */
528
dict_index_t* index, /*!< in: clustered index where update or
526
/* out: byte offset of the inserted
527
undo log entry on the page if succeed,
529
page_t* undo_page, /* in: undo log page */
530
trx_t* trx, /* in: transaction */
531
dict_index_t* index, /* in: clustered index where update or
529
532
delete marking is done */
530
const rec_t* rec, /*!< in: clustered index record which
533
const rec_t* rec, /* in: clustered index record which
531
534
has NOT yet been modified */
532
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
533
const upd_t* update, /*!< in: update vector which tells the
535
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
536
const upd_t* update, /* in: update vector which tells the
534
537
columns to be updated; in the case of
535
538
a delete, this should be set to NULL */
536
ulint cmpl_info, /*!< in: compiler info on secondary
539
ulint cmpl_info, /* in: compiler info on secondary
538
mtr_t* mtr) /*!< in: mtr */
541
mtr_t* mtr) /* in: mtr */
540
543
dict_table_t* table;
541
544
ulint first_free;
822
825
return(first_free);
825
/**********************************************************************//**
828
/**************************************************************************
826
829
Reads from an undo log update record the system field values of the old
828
@return remaining part of undo log record after reading these values */
831
833
trx_undo_update_rec_get_sys_cols(
832
834
/*=============================*/
833
byte* ptr, /*!< in: remaining part of undo
834
log record after reading
835
general parameters */
836
trx_id_t* trx_id, /*!< out: trx id */
837
roll_ptr_t* roll_ptr, /*!< out: roll ptr */
838
ulint* info_bits) /*!< out: info bits state */
835
/* out: remaining part of undo log
836
record after reading these values */
837
byte* ptr, /* in: remaining part of undo log
838
record after reading general
840
dulint* trx_id, /* out: trx id */
841
dulint* roll_ptr, /* out: roll ptr */
842
ulint* info_bits) /* out: info bits state */
840
844
/* Read the state of the info bits */
841
845
*info_bits = mach_read_from_1(ptr);
855
/**********************************************************************//**
856
Reads from an update undo log record the number of updated fields.
857
@return remaining part of undo log record after reading this value */
859
/**************************************************************************
860
Reads from an update undo log record the number of updated fields. */
860
863
trx_undo_update_rec_get_n_upd_fields(
861
864
/*=================================*/
862
byte* ptr, /*!< in: pointer to remaining part of undo log record */
863
ulint* n) /*!< out: number of fields */
865
/* out: remaining part of undo log record after
866
reading this value */
867
byte* ptr, /* in: pointer to remaining part of undo log record */
868
ulint* n) /* out: number of fields */
865
870
*n = mach_read_compressed(ptr);
866
871
ptr += mach_get_compressed_size(*n);
871
/**********************************************************************//**
872
Reads from an update undo log record a stored field number.
873
@return remaining part of undo log record after reading this value */
876
/**************************************************************************
877
Reads from an update undo log record a stored field number. */
876
880
trx_undo_update_rec_get_field_no(
877
881
/*=============================*/
878
byte* ptr, /*!< in: pointer to remaining part of undo log record */
879
ulint* field_no)/*!< out: field number */
882
/* out: remaining part of undo log record after
883
reading this value */
884
byte* ptr, /* in: pointer to remaining part of undo log record */
885
ulint* field_no)/* out: field number */
881
887
*field_no = mach_read_compressed(ptr);
882
888
ptr += mach_get_compressed_size(*field_no);
887
/*******************************************************************//**
888
Builds an update vector based on a remaining part of an undo log record.
889
@return remaining part of the record, NULL if an error detected, which
890
means that the record is corrupted */
893
/***********************************************************************
894
Builds an update vector based on a remaining part of an undo log record. */
893
897
trx_undo_update_rec_get_update(
894
898
/*===========================*/
895
byte* ptr, /*!< in: remaining part in update undo log
899
/* out: remaining part of the record,
900
NULL if an error detected, which means that
901
the record is corrupted */
902
byte* ptr, /* in: remaining part in update undo log
896
903
record, after reading the row reference
897
904
NOTE that this copy of the undo log record must
898
905
be preserved as long as the update vector is
899
906
used, as we do NOT copy the data in the
901
dict_index_t* index, /*!< in: clustered index */
902
ulint type, /*!< in: TRX_UNDO_UPD_EXIST_REC,
908
dict_index_t* index, /* in: clustered index */
909
ulint type, /* in: TRX_UNDO_UPD_EXIST_REC,
903
910
TRX_UNDO_UPD_DEL_REC, or
904
911
TRX_UNDO_DEL_MARK_REC; in the last case,
905
912
only trx id and roll ptr fields are added to
906
913
the update vector */
907
trx_id_t trx_id, /*!< in: transaction id from this undo record */
908
roll_ptr_t roll_ptr,/*!< in: roll pointer from this undo record */
909
ulint info_bits,/*!< in: info bits from this undo record */
910
trx_t* trx, /*!< in: transaction */
911
mem_heap_t* heap, /*!< in: memory heap from which the memory
914
dulint trx_id, /* in: transaction id from this undo record */
915
dulint roll_ptr,/* in: roll pointer from this undo record */
916
ulint info_bits,/* in: info bits from this undo record */
917
trx_t* trx, /* in: transaction */
918
mem_heap_t* heap, /* in: memory heap from which the memory
912
919
needed is allocated */
913
upd_t** upd) /*!< out, own: update vector */
920
upd_t** upd) /* out, own: update vector */
915
922
upd_field_t* upd_field;
1008
/*******************************************************************//**
1015
/***********************************************************************
1009
1016
Builds a partial row from an update undo log record. It contains the
1010
columns which occur as ordering in any index of the table.
1011
@return pointer to remaining part of undo record */
1017
columns which occur as ordering in any index of the table. */
1014
1020
trx_undo_rec_get_partial_row(
1015
1021
/*=========================*/
1016
byte* ptr, /*!< in: remaining part in update undo log
1022
/* out: pointer to remaining part of undo
1024
byte* ptr, /* in: remaining part in update undo log
1017
1025
record of a suitable type, at the start of
1018
1026
the stored index columns;
1019
1027
NOTE that this copy of the undo log record must
1020
1028
be preserved as long as the partial row is
1021
1029
used, as we do NOT copy the data in the
1023
dict_index_t* index, /*!< in: clustered index */
1024
dtuple_t** row, /*!< out, own: partial row */
1025
ibool ignore_prefix, /*!< in: flag to indicate if we
1031
dict_index_t* index, /* in: clustered index */
1032
dtuple_t** row, /* out, own: partial row */
1033
ibool ignore_prefix, /* in: flag to indicate if we
1026
1034
expect blob prefixes in undo. Used
1027
1035
only in the assertion. */
1028
mem_heap_t* heap) /*!< in: memory heap from which the memory
1036
mem_heap_t* heap) /* in: memory heap from which the memory
1029
1037
needed is allocated */
1031
1039
const byte* end_ptr;
1087
#endif /* !UNIV_HOTBACKUP */
1089
/***********************************************************************//**
1096
/***************************************************************************
1090
1097
Erases the unused undo log page end. */
1093
1100
trx_undo_erase_page_end(
1094
1101
/*====================*/
1095
page_t* undo_page, /*!< in: undo page whose end to erase */
1096
mtr_t* mtr) /*!< in: mtr */
1102
page_t* undo_page, /* in: undo page whose end to erase */
1103
mtr_t* mtr) /* in: mtr */
1098
1105
ulint first_free;
1105
1112
mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr);
1108
/***********************************************************//**
1109
Parses a redo log record of erasing of an undo page end.
1110
@return end of log record or NULL */
1115
/***************************************************************
1116
Parses a redo log record of erasing of an undo page end. */
1113
1119
trx_undo_parse_erase_page_end(
1114
1120
/*==========================*/
1115
byte* ptr, /*!< in: buffer */
1116
byte* end_ptr __attribute__((unused)), /*!< in: buffer end */
1117
page_t* page, /*!< in: page or NULL */
1118
mtr_t* mtr) /*!< in: mtr or NULL */
1121
/* out: end of log record or NULL */
1122
byte* ptr, /* in: buffer */
1123
byte* end_ptr __attribute__((unused)), /* in: buffer end */
1124
page_t* page, /* in: page or NULL */
1125
mtr_t* mtr) /* in: mtr or NULL */
1120
1127
ut_ad(ptr && end_ptr);
1132
#ifndef UNIV_HOTBACKUP
1133
/***********************************************************************//**
1139
/***************************************************************************
1134
1140
Writes information to an undo log about an insert, update, or a delete marking
1135
1141
of a clustered index record. This information is used in a rollback of the
1136
1142
transaction and in consistent reads that must look to the history of this
1138
@return DB_SUCCESS or error code */
1141
1146
trx_undo_report_row_operation(
1142
1147
/*==========================*/
1143
ulint flags, /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is
1148
/* out: DB_SUCCESS or error code */
1149
ulint flags, /* in: if BTR_NO_UNDO_LOG_FLAG bit is
1144
1150
set, does nothing */
1145
ulint op_type, /*!< in: TRX_UNDO_INSERT_OP or
1151
ulint op_type, /* in: TRX_UNDO_INSERT_OP or
1146
1152
TRX_UNDO_MODIFY_OP */
1147
que_thr_t* thr, /*!< in: query thread */
1148
dict_index_t* index, /*!< in: clustered index */
1149
const dtuple_t* clust_entry, /*!< in: in the case of an insert,
1153
que_thr_t* thr, /* in: query thread */
1154
dict_index_t* index, /* in: clustered index */
1155
const dtuple_t* clust_entry, /* in: in the case of an insert,
1150
1156
index entry to insert into the
1151
1157
clustered index, otherwise NULL */
1152
const upd_t* update, /*!< in: in the case of an update,
1158
const upd_t* update, /* in: in the case of an update,
1153
1159
the update vector, otherwise NULL */
1154
ulint cmpl_info, /*!< in: compiler info on secondary
1160
ulint cmpl_info, /* in: compiler info on secondary
1155
1161
index updates */
1156
const rec_t* rec, /*!< in: in case of an update or delete
1162
const rec_t* rec, /* in: in case of an update or delete
1157
1163
marking, the record in the clustered
1158
1164
index, otherwise NULL */
1159
roll_ptr_t* roll_ptr) /*!< out: rollback pointer to the
1165
dulint* roll_ptr) /* out: rollback pointer to the
1160
1166
inserted undo log record,
1161
1167
ut_dulint_zero if BTR_NO_UNDO_LOG
1162
1168
flag was specified */
1319
1325
/*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/
1321
/******************************************************************//**
1327
/**********************************************************************
1322
1328
Copies an undo record to heap. This function can be called if we know that
1323
the undo log record exists.
1324
@return own: copy of the record */
1329
the undo log record exists. */
1326
1331
trx_undo_rec_t*
1327
1332
trx_undo_get_undo_rec_low(
1328
1333
/*======================*/
1329
roll_ptr_t roll_ptr, /*!< in: roll pointer to record */
1330
mem_heap_t* heap) /*!< in: memory heap where copied */
1334
/* out, own: copy of the record */
1335
dulint roll_ptr, /* in: roll pointer to record */
1336
mem_heap_t* heap) /* in: memory heap where copied */
1332
1338
trx_undo_rec_t* undo_rec;
1354
1360
return(undo_rec);
1357
/******************************************************************//**
1358
Copies an undo record to heap.
1360
NOTE: the caller must have latches on the clustered index page and
1363
@return DB_SUCCESS, or DB_MISSING_HISTORY if the undo log has been
1364
truncated and we cannot fetch the old version */
1363
/**********************************************************************
1364
Copies an undo record to heap. */
1367
1367
trx_undo_get_undo_rec(
1368
1368
/*==================*/
1369
roll_ptr_t roll_ptr, /*!< in: roll pointer to record */
1370
trx_id_t trx_id, /*!< in: id of the trx that generated
1369
/* out: DB_SUCCESS, or
1370
DB_MISSING_HISTORY if the undo log
1371
has been truncated and we cannot
1372
fetch the old version; NOTE: the
1373
caller must have latches on the
1374
clustered index page and purge_view */
1375
dulint roll_ptr, /* in: roll pointer to record */
1376
dulint trx_id, /* in: id of the trx that generated
1371
1377
the roll pointer: it points to an
1372
1378
undo log of this transaction */
1373
trx_undo_rec_t** undo_rec, /*!< out, own: copy of the record */
1374
mem_heap_t* heap) /*!< in: memory heap where copied */
1379
trx_undo_rec_t** undo_rec, /* out, own: copy of the record */
1380
mem_heap_t* heap) /* in: memory heap where copied */
1376
1382
#ifdef UNIV_SYNC_DEBUG
1377
1383
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
1390
1396
return(DB_SUCCESS);
1393
/*******************************************************************//**
1399
/***********************************************************************
1394
1400
Build a previous version of a clustered index record. This function checks
1395
1401
that the caller has a latch on the index page of the clustered index record
1396
1402
and an s-latch on the purge_view. This guarantees that the stack of versions
1397
is locked all the way down to the purge_view.
1398
@return DB_SUCCESS, or DB_MISSING_HISTORY if the previous version is
1399
earlier than purge_view, which means that it may have been removed,
1400
DB_ERROR if corrupted record */
1403
is locked all the way down to the purge_view. */
1403
1406
trx_undo_prev_version_build(
1404
1407
/*========================*/
1405
const rec_t* index_rec,/*!< in: clustered index record in the
1408
/* out: DB_SUCCESS, or DB_MISSING_HISTORY if
1409
the previous version is not >= purge_view,
1410
which means that it may have been removed,
1411
DB_ERROR if corrupted record */
1412
const rec_t* index_rec,/* in: clustered index record in the
1407
1414
mtr_t* index_mtr __attribute__((unused)),
1408
/*!< in: mtr which contains the latch to
1415
/* in: mtr which contains the latch to
1409
1416
index_rec page and purge_view */
1410
const rec_t* rec, /*!< in: version of a clustered index record */
1411
dict_index_t* index, /*!< in: clustered index */
1412
ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1413
mem_heap_t* heap, /*!< in: memory heap from which the memory
1417
const rec_t* rec, /* in: version of a clustered index record */
1418
dict_index_t* index, /* in: clustered index */
1419
ulint* offsets,/* in: rec_get_offsets(rec, index) */
1420
mem_heap_t* heap, /* in: memory heap from which the memory
1414
1421
needed is allocated */
1415
rec_t** old_vers)/*!< out, own: previous version, or NULL if
1422
rec_t** old_vers)/* out, own: previous version, or NULL if
1416
1423
rec is the first inserted version, or if
1417
1424
history data has been deleted (an error),
1418
1425
or if the purge COULD have removed the version