1
/*****************************************************************************
3
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
17
*****************************************************************************/
19
/**************************************************//**
1
/******************************************************
23
6
Created 12/27/1996 Heikki Tuuri
24
7
*******************************************************/
92
73
searched delete is obviously to keep the x-latch for several
93
74
steps of query graph execution. */
95
/*************************************************************************
96
IMPORTANT NOTE: Any operation that generates redo MUST check that there
97
is enough space in the redo log before for that operation. This is
98
done by calling log_free_check(). The reason for checking the
99
availability of the redo log space before the start of the operation is
100
that we MUST not hold any synchonization objects when performing the
102
If you make a change in this module make sure that no codepath is
103
introduced where a call to log_free_check() is bypassed. */
105
/*************************************************************************
106
IMPORTANT NOTE: Any operation that generates redo MUST check that there
107
is enough space in the redo log before for that operation. This is
108
done by calling log_free_check(). The reason for checking the
109
availability of the redo log space before the start of the operation is
110
that we MUST not hold any synchonization objects when performing the
112
If you make a change in this module make sure that no codepath is
113
introduced where a call to log_free_check() is bypassed. */
115
/***********************************************************//**
76
/***************************************************************
116
77
Checks if an update vector changes some of the first ordering fields of an
117
78
index record. This is only used in foreign key checks and we can assume
118
that index does not contain column prefixes.
119
@return TRUE if changes */
79
that index does not contain column prefixes. */
122
82
row_upd_changes_first_fields_binary(
123
83
/*================================*/
124
dtuple_t* entry, /*!< in: old value of index entry */
125
dict_index_t* index, /*!< in: index of entry */
126
const upd_t* update, /*!< in: update vector for the row */
127
ulint n); /*!< in: how many first fields to check */
130
/*********************************************************************//**
84
/* out: TRUE if changes */
85
dtuple_t* entry, /* in: old value of index entry */
86
dict_index_t* index, /* in: index of entry */
87
const upd_t* update, /* in: update vector for the row */
88
ulint n); /* in: how many first fields to check */
91
/*************************************************************************
131
92
Checks if index currently is mentioned as a referenced index in a foreign
134
NOTE that since we do not hold dict_operation_lock when leaving the
135
function, it may be that the referencing table has been dropped when
136
we leave this function: this function is only for heuristic use!
138
@return TRUE if referenced */
141
96
row_upd_index_is_referenced(
142
97
/*========================*/
143
dict_index_t* index, /*!< in: index */
144
trx_t* trx) /*!< in: transaction */
98
/* out: TRUE if referenced; NOTE that since
99
we do not hold dict_operation_lock
100
when leaving the function, it may be that
101
the referencing table has been dropped when
102
we leave this function: this function is only
103
for heuristic use! */
104
dict_index_t* index, /* in: index */
105
trx_t* trx) /* in: transaction */
146
107
dict_table_t* table = index->table;
147
108
dict_foreign_t* foreign;
178
139
return(is_referenced);
181
/*********************************************************************//**
142
/*************************************************************************
182
143
Checks if possible foreign key constraints hold after a delete of the record
185
NOTE that this function will temporarily commit mtr and lose the
188
@return DB_SUCCESS or an error code */
144
under pcur. NOTE that this function will temporarily commit mtr and lose the
191
148
row_upd_check_references_constraints(
192
149
/*=================================*/
193
upd_node_t* node, /*!< in: row update node */
194
btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the
150
/* out: DB_SUCCESS or an error code */
151
upd_node_t* node, /* in: row update node */
152
btr_pcur_t* pcur, /* in: cursor positioned on a record; NOTE: the
195
153
cursor position is lost in this function! */
196
dict_table_t* table, /*!< in: table in question */
197
dict_index_t* index, /*!< in: index of the cursor */
198
ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */
199
que_thr_t* thr, /*!< in: query thread */
200
mtr_t* mtr) /*!< in: mtr */
154
dict_table_t* table, /* in: table in question */
155
dict_index_t* index, /* in: index of the cursor */
156
ulint* offsets,/* in/out: rec_get_offsets(pcur.rec, index) */
157
que_thr_t* thr, /* in: query thread */
158
mtr_t* mtr) /* in: mtr */
202
160
dict_foreign_t* foreign;
203
161
mem_heap_t* heap;
342
#endif /* !UNIV_HOTBACKUP */
344
/*********************************************************************//**
302
/*************************************************************************
345
303
Updates the trx id and roll ptr field in a clustered index record in database
349
307
row_upd_rec_sys_fields_in_recovery(
350
308
/*===============================*/
351
rec_t* rec, /*!< in/out: record */
352
page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
353
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
354
ulint pos, /*!< in: TRX_ID position in rec */
355
trx_id_t trx_id, /*!< in: transaction id */
356
roll_ptr_t roll_ptr)/*!< in: roll ptr of the undo log record */
309
rec_t* rec, /* in/out: record */
310
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
311
const ulint* offsets,/* in: array returned by rec_get_offsets() */
312
ulint pos, /* in: TRX_ID position in rec */
313
dulint trx_id, /* in: transaction id */
314
dulint roll_ptr)/* in: roll ptr of the undo log record */
358
316
ut_ad(rec_offs_validate(rec, NULL, offsets));
377
#ifndef UNIV_HOTBACKUP
378
/*********************************************************************//**
335
/*************************************************************************
379
336
Sets the trx id or roll ptr field of a clustered index entry. */
382
339
row_upd_index_entry_sys_field(
383
340
/*==========================*/
384
const dtuple_t* entry, /*!< in: index entry, where the memory buffers
341
const dtuple_t* entry, /* in: index entry, where the memory buffers
385
342
for sys fields are already allocated:
386
343
the function just copies the new values to
388
dict_index_t* index, /*!< in: clustered index */
389
ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
390
ib_uint64_t val) /*!< in: value to write */
345
dict_index_t* index, /* in: clustered index */
346
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
347
dulint val) /* in: value to write */
392
349
dfield_t* dfield;
411
/***********************************************************//**
368
/***************************************************************
412
369
Returns TRUE if row update changes size of some field in index or if some
413
field to be updated is stored externally in rec or update.
414
@return TRUE if the update changes the size of some field in index or
415
the field is external in rec or update */
370
field to be updated is stored externally in rec or update. */
418
373
row_upd_changes_field_size_or_external(
419
374
/*===================================*/
420
dict_index_t* index, /*!< in: index */
421
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
422
const upd_t* update) /*!< in: update vector */
375
/* out: TRUE if the update changes the size of
376
some field in index or the field is external
378
dict_index_t* index, /* in: index */
379
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
380
const upd_t* update) /* in: update vector */
424
382
const upd_field_t* upd_field;
425
383
const dfield_t* new_val;
476
#endif /* !UNIV_HOTBACKUP */
478
/***********************************************************//**
434
/***************************************************************
479
435
Replaces the new column values stored in the update vector to the record
480
436
given. No field size changes are allowed. */
483
439
row_upd_rec_in_place(
484
440
/*=================*/
485
rec_t* rec, /*!< in/out: record where replaced */
486
dict_index_t* index, /*!< in: the index the record belongs to */
487
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
488
const upd_t* update, /*!< in: update vector */
489
page_zip_des_t* page_zip)/*!< in: compressed page with enough space
441
rec_t* rec, /* in/out: record where replaced */
442
dict_index_t* index, /* in: the index the record belongs to */
443
const ulint* offsets,/* in: array returned by rec_get_offsets() */
444
const upd_t* update, /* in: update vector */
445
page_zip_des_t* page_zip)/* in: compressed page with enough space
490
446
available, or NULL */
492
448
const upd_field_t* upd_field;
523
#ifndef UNIV_HOTBACKUP
524
/*********************************************************************//**
479
/*************************************************************************
525
480
Writes into the redo log the values of trx id and roll ptr and enough info
526
to determine their positions within a clustered index record.
527
@return new pointer to mlog */
481
to determine their positions within a clustered index record. */
530
484
row_upd_write_sys_vals_to_log(
531
485
/*==========================*/
532
dict_index_t* index, /*!< in: clustered index */
533
trx_t* trx, /*!< in: transaction */
534
roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */
535
byte* log_ptr,/*!< pointer to a buffer of size > 20 opened
486
/* out: new pointer to mlog */
487
dict_index_t* index, /* in: clustered index */
488
trx_t* trx, /* in: transaction */
489
dulint roll_ptr,/* in: roll ptr of the undo log record */
490
byte* log_ptr,/* pointer to a buffer of size > 20 opened
537
mtr_t* mtr __attribute__((unused))) /*!< in: mtr */
492
mtr_t* mtr __attribute__((unused))) /* in: mtr */
539
494
ut_ad(dict_index_is_clust(index));
546
501
trx_write_roll_ptr(log_ptr, roll_ptr);
547
502
log_ptr += DATA_ROLL_PTR_LEN;
549
log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
504
log_ptr += mach_dulint_write_compressed(log_ptr, trx->id);
553
#endif /* !UNIV_HOTBACKUP */
555
/*********************************************************************//**
556
Parses the log data of system field values.
557
@return log data end or NULL */
509
/*************************************************************************
510
Parses the log data of system field values. */
560
513
row_upd_parse_sys_vals(
561
514
/*===================*/
562
byte* ptr, /*!< in: buffer */
563
byte* end_ptr,/*!< in: buffer end */
564
ulint* pos, /*!< out: TRX_ID position in record */
565
trx_id_t* trx_id, /*!< out: trx id */
566
roll_ptr_t* roll_ptr)/*!< out: roll ptr */
515
/* out: log data end or NULL */
516
byte* ptr, /* in: buffer */
517
byte* end_ptr,/* in: buffer end */
518
ulint* pos, /* out: TRX_ID position in record */
519
dulint* trx_id, /* out: trx id */
520
dulint* roll_ptr)/* out: roll ptr */
568
522
ptr = mach_parse_compressed(ptr, end_ptr, pos);
580
534
*roll_ptr = trx_read_roll_ptr(ptr);
581
535
ptr += DATA_ROLL_PTR_LEN;
583
ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
537
ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
588
#ifndef UNIV_HOTBACKUP
589
/***********************************************************//**
542
/***************************************************************
590
543
Writes to the redo log the new values of the fields occurring in the index. */
593
546
row_upd_index_write_log(
594
547
/*====================*/
595
const upd_t* update, /*!< in: update vector */
596
byte* log_ptr,/*!< in: pointer to mlog buffer: must
548
const upd_t* update, /* in: update vector */
549
byte* log_ptr,/* in: pointer to mlog buffer: must
597
550
contain at least MLOG_BUF_MARGIN bytes
598
551
of free space; the buffer is closed
599
552
within this function */
600
mtr_t* mtr) /*!< in: mtr into whose log to write */
553
mtr_t* mtr) /* in: mtr into whose log to write */
602
555
const upd_field_t* upd_field;
603
556
const dfield_t* new_val;
657
610
mlog_close(mtr, log_ptr);
659
#endif /* !UNIV_HOTBACKUP */
661
/*********************************************************************//**
662
Parses the log data written by row_upd_index_write_log.
663
@return log data end or NULL */
613
/*************************************************************************
614
Parses the log data written by row_upd_index_write_log. */
666
617
row_upd_index_parse(
667
618
/*================*/
668
byte* ptr, /*!< in: buffer */
669
byte* end_ptr,/*!< in: buffer end */
670
mem_heap_t* heap, /*!< in: memory heap where update vector is
619
/* out: log data end or NULL */
620
byte* ptr, /* in: buffer */
621
byte* end_ptr,/* in: buffer end */
622
mem_heap_t* heap, /* in: memory heap where update vector is
672
upd_t** update_out)/*!< out: update vector */
624
upd_t** update_out)/* out: update vector */
675
627
upd_field_t* upd_field;
740
#ifndef UNIV_HOTBACKUP
741
/***************************************************************//**
692
/*******************************************************************
742
693
Builds an update vector from those fields which in a secondary index entry
743
694
differ from a record that has the equal ordering fields. NOTE: we compare
744
the fields as binary strings!
745
@return own: update vector of differing fields */
695
the fields as binary strings! */
748
698
row_upd_build_sec_rec_difference_binary(
749
699
/*====================================*/
750
dict_index_t* index, /*!< in: index */
751
const dtuple_t* entry, /*!< in: entry to insert */
752
const rec_t* rec, /*!< in: secondary index record */
753
trx_t* trx, /*!< in: transaction */
754
mem_heap_t* heap) /*!< in: memory heap from which allocated */
700
/* out, own: update vector of differing
702
dict_index_t* index, /* in: index */
703
const dtuple_t* entry, /* in: entry to insert */
704
const rec_t* rec, /* in: secondary index record */
705
trx_t* trx, /* in: transaction */
706
mem_heap_t* heap) /* in: memory heap from which allocated */
756
708
upd_field_t* upd_field;
757
709
const dfield_t* dfield;
810
/***************************************************************//**
762
/*******************************************************************
811
763
Builds an update vector from those fields, excluding the roll ptr and
812
764
trx id fields, which in an index entry differ from a record that has
813
the equal ordering fields. NOTE: we compare the fields as binary strings!
814
@return own: update vector of differing fields, excluding roll ptr and
765
the equal ordering fields. NOTE: we compare the fields as binary strings! */
818
768
row_upd_build_difference_binary(
819
769
/*============================*/
820
dict_index_t* index, /*!< in: clustered index */
821
const dtuple_t* entry, /*!< in: entry to insert */
822
const rec_t* rec, /*!< in: clustered index record */
823
trx_t* trx, /*!< in: transaction */
824
mem_heap_t* heap) /*!< in: memory heap from which allocated */
770
/* out, own: update vector of differing
771
fields, excluding roll ptr and trx id */
772
dict_index_t* index, /* in: clustered index */
773
const dtuple_t* entry, /* in: entry to insert */
774
const rec_t* rec, /* in: clustered index record */
775
trx_t* trx, /* in: transaction */
776
mem_heap_t* heap) /* in: memory heap from which allocated */
826
778
upd_field_t* upd_field;
827
779
const dfield_t* dfield;
887
/***********************************************************//**
839
/***************************************************************
888
840
Fetch a prefix of an externally stored column. This is similar
889
841
to row_ext_lookup(), but the row_ext_t holds the old values
890
of the column and must not be poisoned with the new values.
891
@return BLOB prefix */
842
of the column and must not be poisoned with the new values. */
894
845
row_upd_ext_fetch(
895
846
/*==============*/
896
const byte* data, /*!< in: 'internally' stored part of the
847
/* out: BLOB prefix */
848
const byte* data, /* in: 'internally' stored part of the
897
849
field containing also the reference to
898
850
the external part */
899
ulint local_len, /*!< in: length of data, in bytes */
900
ulint zip_size, /*!< in: nonzero=compressed BLOB
851
ulint local_len, /* in: length of data, in bytes */
852
ulint zip_size, /* in: nonzero=compressed BLOB
901
853
page size, zero for uncompressed
903
ulint* len, /*!< in: length of prefix to fetch;
855
ulint* len, /* in: length of prefix to fetch;
904
856
out: fetched length of the prefix */
905
mem_heap_t* heap) /*!< in: heap where to allocate */
857
mem_heap_t* heap) /* in: heap where to allocate */
907
859
byte* buf = mem_heap_alloc(heap, *len);
918
/***********************************************************//**
870
/***************************************************************
919
871
Replaces the new column value stored in the update vector in
920
872
the given index entry field. */
923
875
row_upd_index_replace_new_col_val(
924
876
/*==============================*/
925
dfield_t* dfield, /*!< in/out: data field
877
dfield_t* dfield, /* in/out: data field
926
878
of the index entry */
927
const dict_field_t* field, /*!< in: index field */
928
const dict_col_t* col, /*!< in: field->col */
929
const upd_field_t* uf, /*!< in: update field */
930
mem_heap_t* heap, /*!< in: memory heap for allocating
879
const dict_field_t* field, /* in: index field */
880
const dict_col_t* col, /* in: field->col */
881
const upd_field_t* uf, /* in: update field */
882
mem_heap_t* heap, /* in: memory heap for allocating
931
883
and copying the new value */
932
ulint zip_size)/*!< in: compressed page
884
ulint zip_size)/* in: compressed page
933
885
size of the table, or 0 */
1011
/***********************************************************//**
963
/***************************************************************
1012
964
Replaces the new column values stored in the update vector to the index entry
1016
968
row_upd_index_replace_new_col_vals_index_pos(
1017
969
/*=========================================*/
1018
dtuple_t* entry, /*!< in/out: index entry where replaced;
970
dtuple_t* entry, /* in/out: index entry where replaced;
1019
971
the clustered index record must be
1020
972
covered by a lock or a page latch to
1021
973
prevent deletion (rollback or purge) */
1022
dict_index_t* index, /*!< in: index; NOTE that this may also be a
974
dict_index_t* index, /* in: index; NOTE that this may also be a
1023
975
non-clustered index */
1024
const upd_t* update, /*!< in: an update vector built for the index so
976
const upd_t* update, /* in: an update vector built for the index so
1025
977
that the field number in an upd_field is the
1026
978
index position */
1027
979
ibool order_only,
1028
/*!< in: if TRUE, limit the replacement to
980
/* in: if TRUE, limit the replacement to
1029
981
ordering fields of index; note that this
1030
982
does not work for non-clustered indexes. */
1031
mem_heap_t* heap) /*!< in: memory heap for allocating and
983
mem_heap_t* heap) /* in: memory heap for allocating and
1032
984
copying the new values */
1065
/***********************************************************//**
1017
/***************************************************************
1066
1018
Replaces the new column values stored in the update vector to the index entry
1070
1022
row_upd_index_replace_new_col_vals(
1071
1023
/*===============================*/
1072
dtuple_t* entry, /*!< in/out: index entry where replaced;
1024
dtuple_t* entry, /* in/out: index entry where replaced;
1073
1025
the clustered index record must be
1074
1026
covered by a lock or a page latch to
1075
1027
prevent deletion (rollback or purge) */
1076
dict_index_t* index, /*!< in: index; NOTE that this may also be a
1028
dict_index_t* index, /* in: index; NOTE that this may also be a
1077
1029
non-clustered index */
1078
const upd_t* update, /*!< in: an update vector built for the
1030
const upd_t* update, /* in: an update vector built for the
1079
1031
CLUSTERED index so that the field number in
1080
1032
an upd_field is the clustered index position */
1081
mem_heap_t* heap) /*!< in: memory heap for allocating and
1033
mem_heap_t* heap) /* in: memory heap for allocating and
1082
1034
copying the new values */
1110
/***********************************************************//**
1062
/***************************************************************
1111
1063
Replaces the new column values stored in the update vector. */
1114
1066
row_upd_replace(
1115
1067
/*============*/
1116
dtuple_t* row, /*!< in/out: row where replaced,
1068
dtuple_t* row, /* in/out: row where replaced,
1117
1069
indexed by col_no;
1118
1070
the clustered index record must be
1119
1071
covered by a lock or a page latch to
1120
1072
prevent deletion (rollback or purge) */
1121
row_ext_t** ext, /*!< out, own: NULL, or externally
1073
row_ext_t** ext, /* out, own: NULL, or externally
1122
1074
stored column prefixes */
1123
const dict_index_t* index, /*!< in: clustered index */
1124
const upd_t* update, /*!< in: an update vector built for the
1075
const dict_index_t* index, /* in: clustered index */
1076
const upd_t* update, /* in: an update vector built for the
1125
1077
clustered index */
1126
mem_heap_t* heap) /*!< in: memory heap */
1078
mem_heap_t* heap) /* in: memory heap */
1193
/***********************************************************//**
1145
/***************************************************************
1194
1146
Checks if an update vector changes an ordering field of an index record.
1196
1147
This function is fast if the update vector is short or the number of ordering
1197
1148
fields in the index is small. Otherwise, this can be quadratic.
1198
NOTE: we compare the fields as binary strings!
1199
@return TRUE if update vector changes an ordering field in the index record */
1149
NOTE: we compare the fields as binary strings! */
1202
1152
row_upd_changes_ord_field_binary(
1203
1153
/*=============================*/
1204
const dtuple_t* row, /*!< in: old value of row, or NULL if the
1154
/* out: TRUE if update vector changes
1155
an ordering field in the index record;
1156
NOTE: the fields are compared as binary
1158
const dtuple_t* row, /* in: old value of row, or NULL if the
1205
1159
row and the data values in update are not
1206
1160
known when this function is called, e.g., at
1207
1161
compile time */
1208
dict_index_t* index, /*!< in: index of the record */
1209
const upd_t* update) /*!< in: update vector for the row; NOTE: the
1162
dict_index_t* index, /* in: index of the record */
1163
const upd_t* update) /* in: update vector for the row; NOTE: the
1210
1164
field numbers in this MUST be clustered index
1262
/***********************************************************//**
1216
/***************************************************************
1263
1217
Checks if an update vector changes an ordering field of an index record.
1264
NOTE: we compare the fields as binary strings!
1265
@return TRUE if update vector may change an ordering field in an index
1218
NOTE: we compare the fields as binary strings! */
1269
1221
row_upd_changes_some_index_ord_field_binary(
1270
1222
/*========================================*/
1271
const dict_table_t* table, /*!< in: table */
1272
const upd_t* update) /*!< in: update vector for the row */
1223
/* out: TRUE if update vector
1224
may change an ordering field
1225
in an index record */
1226
const dict_table_t* table, /* in: table */
1227
const upd_t* update) /* in: update vector for the row */
1274
1229
upd_field_t* upd_field;
1275
1230
dict_index_t* index;
1295
/***********************************************************//**
1250
/***************************************************************
1296
1251
Checks if an update vector changes some of the first ordering fields of an
1297
1252
index record. This is only used in foreign key checks and we can assume
1298
that index does not contain column prefixes.
1299
@return TRUE if changes */
1253
that index does not contain column prefixes. */
1302
1256
row_upd_changes_first_fields_binary(
1303
1257
/*================================*/
1304
dtuple_t* entry, /*!< in: index entry */
1305
dict_index_t* index, /*!< in: index of entry */
1306
const upd_t* update, /*!< in: update vector for the row */
1307
ulint n) /*!< in: how many first fields to check */
1258
/* out: TRUE if changes */
1259
dtuple_t* entry, /* in: index entry */
1260
dict_index_t* index, /* in: index of entry */
1261
const upd_t* update, /* in: update vector for the row */
1262
ulint n) /* in: how many first fields to check */
1309
1264
ulint n_upd_fields;
1349
/*********************************************************************//**
1304
/*************************************************************************
1350
1305
Copies the column values from a record. */
1353
1308
row_upd_copy_columns(
1354
1309
/*=================*/
1355
rec_t* rec, /*!< in: record in a clustered index */
1356
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
1357
sym_node_t* column) /*!< in: first column in a column list, or
1310
rec_t* rec, /* in: record in a clustered index */
1311
const ulint* offsets,/* in: array returned by rec_get_offsets() */
1312
sym_node_t* column) /* in: first column in a column list, or
1364
1319
data = rec_get_nth_field(rec, offsets,
1365
1320
column->field_nos[SYM_CLUST_FIELD_NO],
1322
if (len == UNIV_SQL_NULL) {
1323
len = UNIV_SQL_NULL;
1367
1325
eval_node_copy_and_alloc_val(column, data, len);
1369
1327
column = UT_LIST_GET_NEXT(col_var_list, column);
1373
/*********************************************************************//**
1331
/*************************************************************************
1374
1332
Calculates the new values for fields to update. Note that row_upd_copy_columns
1375
1333
must have been called first. */
1378
1336
row_upd_eval_new_vals(
1379
1337
/*==================*/
1380
upd_t* update) /*!< in/out: update vector */
1338
upd_t* update) /* in/out: update vector */
1382
1340
que_node_t* exp;
1383
1341
upd_field_t* upd_field;
1426
1383
offsets = rec_get_offsets(rec, clust_index, offsets_,
1427
1384
ULINT_UNDEFINED, &heap);
1429
if (dict_table_get_format(node->table) >= DICT_TF_FORMAT_ZIP) {
1430
/* In DYNAMIC or COMPRESSED format, there is no prefix
1431
of externally stored columns in the clustered index
1432
record. Build a cache of column prefixes. */
1435
/* REDUNDANT and COMPACT formats store a local
1436
768-byte prefix of each externally stored column.
1437
No cache is needed. */
1442
1385
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1443
NULL, ext, node->heap);
1386
NULL, &node->ext, node->heap);
1444
1387
if (node->is_delete) {
1445
1388
node->upd_row = NULL;
1446
1389
node->upd_ext = NULL;
1458
/***********************************************************//**
1459
Updates a secondary index entry of a row.
1460
@return DB_SUCCESS if operation successfully completed, else error
1461
code or DB_LOCK_WAIT */
1401
/***************************************************************
1402
Updates a secondary index entry of a row. */
1464
1405
row_upd_sec_index_entry(
1465
1406
/*====================*/
1466
upd_node_t* node, /*!< in: row update node */
1467
que_thr_t* thr) /*!< in: query thread */
1407
/* out: DB_SUCCESS if operation successfully
1408
completed, else error code or DB_LOCK_WAIT */
1409
upd_node_t* node, /* in: row update node */
1410
que_thr_t* thr) /* in: query thread */
1474
dict_index_t* index;
1477
ulint err = DB_SUCCESS;
1478
trx_t* trx = thr_get_trx(thr);
1479
ulint mode = BTR_MODIFY_LEAF;
1480
enum row_search_result search_result;
1414
dict_index_t* index;
1420
ulint err = DB_SUCCESS;
1422
trx_t* trx = thr_get_trx(thr);
1482
1424
index = node->index;
1484
referenced = row_upd_index_is_referenced(index, trx);
1426
check_ref = row_upd_index_is_referenced(index, trx);
1486
1428
heap = mem_heap_create(1024);
1489
1431
entry = row_build_index_entry(node->row, node->ext, index, heap);
1492
1435
mtr_start(&mtr);
1494
/* Set the query thread, so that ibuf_insert_low() will be
1495
able to invoke thd_get_trx(). */
1496
btr_pcur_get_btr_cur(&pcur)->thr = thr;
1498
/* We can only try to use the insert/delete buffer to buffer
1499
delete-mark operations if the index we're modifying has no foreign
1500
key constraints referring to it. */
1502
mode |= BTR_DELETE_MARK;
1505
search_result = row_search_index_entry(index, entry, mode,
1437
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
1508
1439
btr_cur = btr_pcur_get_btr_cur(&pcur);
1510
1441
rec = btr_cur_get_rec(btr_cur);
1512
switch (search_result) {
1513
case ROW_NOT_DELETED_REF: /* should only occur for BTR_DELETE */
1517
/* Entry was delete marked already. */
1443
if (UNIV_UNLIKELY(!found)) {
1521
1444
fputs("InnoDB: error in sec index entry update in\n"
1522
1445
"InnoDB: ", stderr);
1523
1446
dict_index_name_print(stderr, trx, index);
1535
1458
"InnoDB: Submit a detailed bug report"
1536
1459
" to http://bugs.mysql.com\n", stderr);
1539
1461
/* Delete mark the old index record; it can already be
1540
1462
delete marked if we return after a lock wait in
1541
1463
row_ins_index_entry below */
1543
if (!rec_get_deleted_flag(
1544
rec, dict_table_is_comp(index->table))) {
1546
err = btr_cur_del_mark_set_sec_rec(
1547
0, btr_cur, TRUE, thr, &mtr);
1549
if (err == DB_SUCCESS && referenced) {
1553
offsets = rec_get_offsets(
1554
rec, index, NULL, ULINT_UNDEFINED,
1465
if (!rec_get_deleted_flag(rec,
1466
dict_table_is_comp(index->table))) {
1467
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
1469
if (err == DB_SUCCESS && check_ref) {
1471
ulint* offsets = rec_get_offsets(
1473
ULINT_UNDEFINED, &heap);
1557
1474
/* NOTE that the following call loses
1558
1475
the position of pcur ! */
1559
1476
err = row_upd_check_references_constraints(
1589
/***********************************************************//**
1505
/***************************************************************
1590
1506
Updates the secondary index record if it is changed in the row update or
1591
deletes it if this is a delete.
1592
@return DB_SUCCESS if operation successfully completed, else error
1593
code or DB_LOCK_WAIT */
1507
deletes it if this is a delete. */
1596
1510
row_upd_sec_step(
1597
1511
/*=============*/
1598
upd_node_t* node, /*!< in: row update node */
1599
que_thr_t* thr) /*!< in: query thread */
1512
/* out: DB_SUCCESS if operation successfully
1513
completed, else error code or DB_LOCK_WAIT */
1514
upd_node_t* node, /* in: row update node */
1515
que_thr_t* thr) /* in: query thread */
1601
1517
ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC)
1602
1518
|| (node->state == UPD_NODE_UPDATE_SOME_SEC));
1611
1527
return(DB_SUCCESS);
1614
/***********************************************************//**
1530
/***************************************************************
1615
1531
Marks the clustered index record deleted and inserts the updated version
1616
1532
of the record to the index. This function should be used when the ordering
1617
1533
fields of the clustered index record change. This should be quite rare in
1618
database applications.
1619
@return DB_SUCCESS if operation successfully completed, else error
1620
code or DB_LOCK_WAIT */
1534
database applications. */
1623
1537
row_upd_clust_rec_by_insert(
1624
1538
/*========================*/
1625
upd_node_t* node, /*!< in: row update node */
1626
dict_index_t* index, /*!< in: clustered index of the record */
1627
que_thr_t* thr, /*!< in: query thread */
1628
ibool referenced,/*!< in: TRUE if index may be referenced in
1539
/* out: DB_SUCCESS if operation successfully
1540
completed, else error code or DB_LOCK_WAIT */
1541
upd_node_t* node, /* in: row update node */
1542
dict_index_t* index, /* in: clustered index of the record */
1543
que_thr_t* thr, /* in: query thread */
1544
ibool check_ref,/* in: TRUE if index may be referenced in
1629
1545
a foreign key constraint */
1630
mtr_t* mtr) /*!< in: mtr; gets committed here */
1546
mtr_t* mtr) /* in: mtr; gets committed here */
1632
1548
mem_heap_t* heap = NULL;
1633
1549
btr_pcur_t* pcur;
1669
1584
index = dict_table_get_first_index(table);
1670
1585
offsets = rec_get_offsets(rec, index, offsets_,
1671
1586
ULINT_UNDEFINED, &heap);
1672
change_ownership = btr_cur_mark_extern_inherited_fields(
1673
btr_cur_get_page_zip(btr_cur), rec, index, offsets,
1587
btr_cur_mark_extern_inherited_fields(
1588
btr_cur_get_page_zip(btr_cur),
1589
rec, index, offsets, node->update, mtr);
1676
1591
/* NOTE that the following call loses
1677
1592
the position of pcur ! */
1679
1593
err = row_upd_check_references_constraints(
1680
1594
node, pcur, table, index, offsets, thr, mtr);
1682
1595
if (err != DB_SUCCESS) {
1684
1596
mtr_commit(mtr);
1686
1597
if (UNIV_LIKELY_NULL(heap)) {
1687
1598
mem_heap_free(heap);
1730
/***********************************************************//**
1639
/***************************************************************
1731
1640
Updates a clustered index record of a row when the ordering fields do
1733
@return DB_SUCCESS if operation successfully completed, else error
1734
code or DB_LOCK_WAIT */
1737
1644
row_upd_clust_rec(
1738
1645
/*==============*/
1739
upd_node_t* node, /*!< in: row update node */
1740
dict_index_t* index, /*!< in: clustered index */
1741
que_thr_t* thr, /*!< in: query thread */
1742
mtr_t* mtr) /*!< in: mtr; gets committed here */
1646
/* out: DB_SUCCESS if operation successfully
1647
completed, else error code or DB_LOCK_WAIT */
1648
upd_node_t* node, /* in: row update node */
1649
dict_index_t* index, /* in: clustered index */
1650
que_thr_t* thr, /* in: query thread */
1651
mtr_t* mtr) /* in: mtr; gets committed here */
1744
1653
mem_heap_t* heap = NULL;
1745
1654
big_rec_t* big_rec = NULL;
1833
/***********************************************************//**
1834
Delete marks a clustered index record.
1835
@return DB_SUCCESS if operation successfully completed, else error code */
1742
/***************************************************************
1743
Delete marks a clustered index record. */
1838
1746
row_upd_del_mark_clust_rec(
1839
1747
/*=======================*/
1840
upd_node_t* node, /*!< in: row update node */
1841
dict_index_t* index, /*!< in: clustered index */
1842
ulint* offsets,/*!< in/out: rec_get_offsets() for the
1748
/* out: DB_SUCCESS if operation successfully
1749
completed, else error code */
1750
upd_node_t* node, /* in: row update node */
1751
dict_index_t* index, /* in: clustered index */
1752
ulint* offsets,/* in/out: rec_get_offsets() for the
1843
1753
record under the cursor */
1844
que_thr_t* thr, /*!< in: query thread */
1846
/*!< in: TRUE if index may be referenced in
1754
que_thr_t* thr, /* in: query thread */
1755
ibool check_ref,/* in: TRUE if index may be referenced in
1847
1756
a foreign key constraint */
1848
mtr_t* mtr) /*!< in: mtr; gets committed here */
1757
mtr_t* mtr) /* in: mtr; gets committed here */
1850
1759
btr_pcur_t* pcur;
1851
1760
btr_cur_t* btr_cur;
1869
1778
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1870
1779
btr_cur, TRUE, thr, mtr);
1871
if (err == DB_SUCCESS && referenced) {
1780
if (err == DB_SUCCESS && check_ref) {
1872
1781
/* NOTE that the following call loses the position of pcur ! */
1874
err = row_upd_check_references_constraints(
1875
node, pcur, index->table, index, offsets, thr, mtr);
1783
err = row_upd_check_references_constraints(node,
1878
1789
mtr_commit(mtr);
1883
/***********************************************************//**
1884
Updates the clustered index record.
1885
@return DB_SUCCESS if operation successfully completed, DB_LOCK_WAIT
1886
in case of a lock wait, else error code */
1794
/***************************************************************
1795
Updates the clustered index record. */
1889
1798
row_upd_clust_step(
1890
1799
/*===============*/
1891
upd_node_t* node, /*!< in: row update node */
1892
que_thr_t* thr) /*!< in: query thread */
1800
/* out: DB_SUCCESS if operation successfully
1801
completed, DB_LOCK_WAIT in case of a lock wait,
1803
upd_node_t* node, /* in: row update node */
1804
que_thr_t* thr) /* in: query thread */
1894
1806
dict_index_t* index;
1895
1807
btr_pcur_t* pcur;
1975
1888
/* NOTE: the following function calls will also commit mtr */
1977
1890
if (node->is_delete) {
1978
err = row_upd_del_mark_clust_rec(
1979
node, index, offsets, thr, referenced, mtr);
1891
err = row_upd_del_mark_clust_rec(node, index, offsets,
1892
thr, check_ref, mtr);
1981
1893
if (err == DB_SUCCESS) {
1982
1894
node->state = UPD_NODE_UPDATE_ALL_SEC;
1983
1895
node->index = dict_table_get_next_index(index);
2053
/***********************************************************//**
1964
/***************************************************************
2054
1965
Updates the affected index records of a row. When the control is transferred
2055
1966
to this node, we assume that we have a persistent cursor which was on a
2056
record, and the position of the cursor is stored in the cursor.
2057
@return DB_SUCCESS if operation successfully completed, else error
2058
code or DB_LOCK_WAIT */
1967
record, and the position of the cursor is stored in the cursor. */
2063
upd_node_t* node, /*!< in: row update node */
2064
que_thr_t* thr) /*!< in: query thread */
1972
/* out: DB_SUCCESS if operation successfully
1973
completed, else error code or DB_LOCK_WAIT */
1974
upd_node_t* node, /* in: row update node */
1975
que_thr_t* thr) /* in: query thread */
2066
1977
ulint err = DB_SUCCESS;
2246
#endif /* !UNIV_HOTBACKUP */
2155
/*************************************************************************
2156
Performs an in-place update for the current clustered index record in
2160
row_upd_in_place_in_select(
2161
/*=======================*/
2162
sel_node_t* sel_node, /* in: select node */
2163
que_thr_t* thr, /* in: query thread */
2164
mtr_t* mtr) /* in: mtr */
2170
mem_heap_t* heap = NULL;
2171
ulint offsets_[REC_OFFS_NORMAL_SIZE];
2172
rec_offs_init(offsets_);
2174
ut_ad(sel_node->select_will_do_update);
2175
ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
2176
ut_ad(sel_node->asc);
2178
node = que_node_get_parent(sel_node);
2180
ut_ad(que_node_get_type(node) == QUE_NODE_UPDATE);
2183
btr_cur = btr_pcur_get_btr_cur(pcur);
2185
/* Copy the necessary columns from clust_rec and calculate the new
2188
row_upd_copy_columns(btr_pcur_get_rec(pcur),
2189
rec_get_offsets(btr_pcur_get_rec(pcur),
2190
btr_cur->index, offsets_,
2191
ULINT_UNDEFINED, &heap),
2192
UT_LIST_GET_FIRST(node->columns));
2193
if (UNIV_LIKELY_NULL(heap)) {
2194
mem_heap_free(heap);
2196
row_upd_eval_new_vals(node->update);
2198
ut_ad(!rec_get_deleted_flag(
2199
btr_pcur_get_rec(pcur),
2200
dict_table_is_comp(btr_cur->index->table)));
2202
ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE);
2203
ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
2204
ut_ad(node->select_will_do_update);
2206
err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur,
2207
node->update, node->cmpl_info,
2209
/* TODO: the above can fail with DB_ZIP_OVERFLOW if page_zip != NULL.
2210
However, this function row_upd_in_place_in_select() is only invoked
2211
when executing UPDATE statements of the built-in InnoDB SQL parser.
2212
The built-in SQL is only used for InnoDB system tables, which
2213
always are in the old, uncompressed format (ROW_FORMAT=REDUNDANT,
2214
comp == FALSE, page_zip == NULL). */
2215
ut_ad(err == DB_SUCCESS);