11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
17
17
*****************************************************************************/
19
/**************************************************//**
19
/******************************************************
23
22
Created 12/27/1996 Heikki Tuuri
92
89
searched delete is obviously to keep the x-latch for several
93
90
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
/***********************************************************//**
92
/***************************************************************
116
93
Checks if an update vector changes some of the first ordering fields of an
117
94
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 */
95
that index does not contain column prefixes. */
122
98
row_upd_changes_first_fields_binary(
123
99
/*================================*/
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
/*********************************************************************//**
100
/* out: TRUE if changes */
101
dtuple_t* entry, /* in: old value of index entry */
102
dict_index_t* index, /* in: index of entry */
103
const upd_t* update, /* in: update vector for the row */
104
ulint n); /* in: how many first fields to check */
107
/*************************************************************************
131
108
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
112
row_upd_index_is_referenced(
142
113
/*========================*/
143
dict_index_t* index, /*!< in: index */
144
trx_t* trx) /*!< in: transaction */
114
/* out: TRUE if referenced; NOTE that since
115
we do not hold dict_operation_lock
116
when leaving the function, it may be that
117
the referencing table has been dropped when
118
we leave this function: this function is only
119
for heuristic use! */
120
dict_index_t* index, /* in: index */
121
trx_t* trx) /* in: transaction */
146
123
dict_table_t* table = index->table;
147
124
dict_foreign_t* foreign;
178
155
return(is_referenced);
181
/*********************************************************************//**
158
/*************************************************************************
182
159
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 */
160
under pcur. NOTE that this function will temporarily commit mtr and lose the
191
164
row_upd_check_references_constraints(
192
165
/*=================================*/
193
upd_node_t* node, /*!< in: row update node */
194
btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the
166
/* out: DB_SUCCESS or an error code */
167
upd_node_t* node, /* in: row update node */
168
btr_pcur_t* pcur, /* in: cursor positioned on a record; NOTE: the
195
169
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 */
170
dict_table_t* table, /* in: table in question */
171
dict_index_t* index, /* in: index of the cursor */
172
ulint* offsets,/* in/out: rec_get_offsets(pcur.rec, index) */
173
que_thr_t* thr, /* in: query thread */
174
mtr_t* mtr) /* in: mtr */
202
176
dict_foreign_t* foreign;
203
177
mem_heap_t* heap;
342
#endif /* !UNIV_HOTBACKUP */
344
/*********************************************************************//**
317
/*************************************************************************
345
318
Updates the trx id and roll ptr field in a clustered index record in database
349
322
row_upd_rec_sys_fields_in_recovery(
350
323
/*===============================*/
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 */
324
rec_t* rec, /* in/out: record */
325
page_zip_des_t* page_zip,/* in/out: compressed page, or NULL */
326
const ulint* offsets,/* in: array returned by rec_get_offsets() */
327
ulint pos, /* in: TRX_ID position in rec */
328
dulint trx_id, /* in: transaction id */
329
dulint roll_ptr)/* in: roll ptr of the undo log record */
358
331
ut_ad(rec_offs_validate(rec, NULL, offsets));
377
#ifndef UNIV_HOTBACKUP
378
/*********************************************************************//**
350
/*************************************************************************
379
351
Sets the trx id or roll ptr field of a clustered index entry. */
382
354
row_upd_index_entry_sys_field(
383
355
/*==========================*/
384
const dtuple_t* entry, /*!< in: index entry, where the memory buffers
356
const dtuple_t* entry, /* in: index entry, where the memory buffers
385
357
for sys fields are already allocated:
386
358
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 */
360
dict_index_t* index, /* in: clustered index */
361
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
362
dulint val) /* in: value to write */
392
364
dfield_t* dfield;
411
/***********************************************************//**
383
/***************************************************************
412
384
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 */
385
field to be updated is stored externally in rec or update. */
418
388
row_upd_changes_field_size_or_external(
419
389
/*===================================*/
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 */
390
/* out: TRUE if the update changes the size of
391
some field in index or the field is external
393
dict_index_t* index, /* in: index */
394
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
395
const upd_t* update) /* in: update vector */
424
397
const upd_field_t* upd_field;
425
398
const dfield_t* new_val;
476
#endif /* !UNIV_HOTBACKUP */
478
/***********************************************************//**
449
/***************************************************************
479
450
Replaces the new column values stored in the update vector to the record
480
451
given. No field size changes are allowed. */
483
454
row_upd_rec_in_place(
484
455
/*=================*/
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
456
rec_t* rec, /* in/out: record where replaced */
457
dict_index_t* index, /* in: the index the record belongs to */
458
const ulint* offsets,/* in: array returned by rec_get_offsets() */
459
const upd_t* update, /* in: update vector */
460
page_zip_des_t* page_zip)/* in: compressed page with enough space
490
461
available, or NULL */
492
463
const upd_field_t* upd_field;
523
#ifndef UNIV_HOTBACKUP
524
/*********************************************************************//**
494
/*************************************************************************
525
495
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 */
496
to determine their positions within a clustered index record. */
530
499
row_upd_write_sys_vals_to_log(
531
500
/*==========================*/
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
501
/* out: new pointer to mlog */
502
dict_index_t* index, /* in: clustered index */
503
trx_t* trx, /* in: transaction */
504
dulint roll_ptr,/* in: roll ptr of the undo log record */
505
byte* log_ptr,/* pointer to a buffer of size > 20 opened
537
mtr_t* mtr __attribute__((unused))) /*!< in: mtr */
507
mtr_t* mtr __attribute__((unused))) /* in: mtr */
539
509
ut_ad(dict_index_is_clust(index));
546
516
trx_write_roll_ptr(log_ptr, roll_ptr);
547
517
log_ptr += DATA_ROLL_PTR_LEN;
549
log_ptr += mach_ull_write_compressed(log_ptr, trx->id);
519
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 */
524
/*************************************************************************
525
Parses the log data of system field values. */
560
528
row_upd_parse_sys_vals(
561
529
/*===================*/
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 */
530
/* out: log data end or NULL */
531
byte* ptr, /* in: buffer */
532
byte* end_ptr,/* in: buffer end */
533
ulint* pos, /* out: TRX_ID position in record */
534
dulint* trx_id, /* out: trx id */
535
dulint* roll_ptr)/* out: roll ptr */
568
537
ptr = mach_parse_compressed(ptr, end_ptr, pos);
580
549
*roll_ptr = trx_read_roll_ptr(ptr);
581
550
ptr += DATA_ROLL_PTR_LEN;
583
ptr = mach_ull_parse_compressed(ptr, end_ptr, trx_id);
552
ptr = mach_dulint_parse_compressed(ptr, end_ptr, trx_id);
588
#ifndef UNIV_HOTBACKUP
589
/***********************************************************//**
557
/***************************************************************
590
558
Writes to the redo log the new values of the fields occurring in the index. */
593
561
row_upd_index_write_log(
594
562
/*====================*/
595
const upd_t* update, /*!< in: update vector */
596
byte* log_ptr,/*!< in: pointer to mlog buffer: must
563
const upd_t* update, /* in: update vector */
564
byte* log_ptr,/* in: pointer to mlog buffer: must
597
565
contain at least MLOG_BUF_MARGIN bytes
598
566
of free space; the buffer is closed
599
567
within this function */
600
mtr_t* mtr) /*!< in: mtr into whose log to write */
568
mtr_t* mtr) /* in: mtr into whose log to write */
602
570
const upd_field_t* upd_field;
603
571
const dfield_t* new_val;
657
625
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 */
628
/*************************************************************************
629
Parses the log data written by row_upd_index_write_log. */
666
632
row_upd_index_parse(
667
633
/*================*/
668
byte* ptr, /*!< in: buffer */
669
byte* end_ptr,/*!< in: buffer end */
670
mem_heap_t* heap, /*!< in: memory heap where update vector is
634
/* out: log data end or NULL */
635
byte* ptr, /* in: buffer */
636
byte* end_ptr,/* in: buffer end */
637
mem_heap_t* heap, /* in: memory heap where update vector is
672
upd_t** update_out)/*!< out: update vector */
639
upd_t** update_out)/* out: update vector */
675
642
upd_field_t* upd_field;
740
#ifndef UNIV_HOTBACKUP
741
/***************************************************************//**
707
/*******************************************************************
742
708
Builds an update vector from those fields which in a secondary index entry
743
709
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 */
710
the fields as binary strings! */
748
713
row_upd_build_sec_rec_difference_binary(
749
714
/*====================================*/
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 */
715
/* out, own: update vector of differing
717
dict_index_t* index, /* in: index */
718
const dtuple_t* entry, /* in: entry to insert */
719
const rec_t* rec, /* in: secondary index record */
720
trx_t* trx, /* in: transaction */
721
mem_heap_t* heap) /* in: memory heap from which allocated */
756
723
upd_field_t* upd_field;
757
724
const dfield_t* dfield;
810
/***************************************************************//**
777
/*******************************************************************
811
778
Builds an update vector from those fields, excluding the roll ptr and
812
779
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
780
the equal ordering fields. NOTE: we compare the fields as binary strings! */
818
783
row_upd_build_difference_binary(
819
784
/*============================*/
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 */
785
/* out, own: update vector of differing
786
fields, excluding roll ptr and trx id */
787
dict_index_t* index, /* in: clustered index */
788
const dtuple_t* entry, /* in: entry to insert */
789
const rec_t* rec, /* in: clustered index record */
790
trx_t* trx, /* in: transaction */
791
mem_heap_t* heap) /* in: memory heap from which allocated */
826
793
upd_field_t* upd_field;
827
794
const dfield_t* dfield;
887
/***********************************************************//**
854
/***************************************************************
888
855
Fetch a prefix of an externally stored column. This is similar
889
856
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 */
857
of the column and must not be poisoned with the new values. */
894
860
row_upd_ext_fetch(
895
861
/*==============*/
896
const byte* data, /*!< in: 'internally' stored part of the
862
/* out: BLOB prefix */
863
const byte* data, /* in: 'internally' stored part of the
897
864
field containing also the reference to
898
865
the external part */
899
ulint local_len, /*!< in: length of data, in bytes */
900
ulint zip_size, /*!< in: nonzero=compressed BLOB
866
ulint local_len, /* in: length of data, in bytes */
867
ulint zip_size, /* in: nonzero=compressed BLOB
901
868
page size, zero for uncompressed
903
ulint* len, /*!< in: length of prefix to fetch;
870
ulint* len, /* in: length of prefix to fetch;
904
871
out: fetched length of the prefix */
905
mem_heap_t* heap) /*!< in: heap where to allocate */
872
mem_heap_t* heap) /* in: heap where to allocate */
907
874
byte* buf = mem_heap_alloc(heap, *len);
918
/***********************************************************//**
885
/***************************************************************
919
886
Replaces the new column value stored in the update vector in
920
887
the given index entry field. */
923
890
row_upd_index_replace_new_col_val(
924
891
/*==============================*/
925
dfield_t* dfield, /*!< in/out: data field
892
dfield_t* dfield, /* in/out: data field
926
893
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
894
const dict_field_t* field, /* in: index field */
895
const dict_col_t* col, /* in: field->col */
896
const upd_field_t* uf, /* in: update field */
897
mem_heap_t* heap, /* in: memory heap for allocating
931
898
and copying the new value */
932
ulint zip_size)/*!< in: compressed page
899
ulint zip_size)/* in: compressed page
933
900
size of the table, or 0 */
1011
/***********************************************************//**
978
/***************************************************************
1012
979
Replaces the new column values stored in the update vector to the index entry
1016
983
row_upd_index_replace_new_col_vals_index_pos(
1017
984
/*=========================================*/
1018
dtuple_t* entry, /*!< in/out: index entry where replaced;
985
dtuple_t* entry, /* in/out: index entry where replaced;
1019
986
the clustered index record must be
1020
987
covered by a lock or a page latch to
1021
988
prevent deletion (rollback or purge) */
1022
dict_index_t* index, /*!< in: index; NOTE that this may also be a
989
dict_index_t* index, /* in: index; NOTE that this may also be a
1023
990
non-clustered index */
1024
const upd_t* update, /*!< in: an update vector built for the index so
991
const upd_t* update, /* in: an update vector built for the index so
1025
992
that the field number in an upd_field is the
1026
993
index position */
1027
994
ibool order_only,
1028
/*!< in: if TRUE, limit the replacement to
995
/* in: if TRUE, limit the replacement to
1029
996
ordering fields of index; note that this
1030
997
does not work for non-clustered indexes. */
1031
mem_heap_t* heap) /*!< in: memory heap for allocating and
998
mem_heap_t* heap) /* in: memory heap for allocating and
1032
999
copying the new values */
1065
/***********************************************************//**
1032
/***************************************************************
1066
1033
Replaces the new column values stored in the update vector to the index entry
1070
1037
row_upd_index_replace_new_col_vals(
1071
1038
/*===============================*/
1072
dtuple_t* entry, /*!< in/out: index entry where replaced;
1039
dtuple_t* entry, /* in/out: index entry where replaced;
1073
1040
the clustered index record must be
1074
1041
covered by a lock or a page latch to
1075
1042
prevent deletion (rollback or purge) */
1076
dict_index_t* index, /*!< in: index; NOTE that this may also be a
1043
dict_index_t* index, /* in: index; NOTE that this may also be a
1077
1044
non-clustered index */
1078
const upd_t* update, /*!< in: an update vector built for the
1045
const upd_t* update, /* in: an update vector built for the
1079
1046
CLUSTERED index so that the field number in
1080
1047
an upd_field is the clustered index position */
1081
mem_heap_t* heap) /*!< in: memory heap for allocating and
1048
mem_heap_t* heap) /* in: memory heap for allocating and
1082
1049
copying the new values */
1110
/***********************************************************//**
1077
/***************************************************************
1111
1078
Replaces the new column values stored in the update vector. */
1114
1081
row_upd_replace(
1115
1082
/*============*/
1116
dtuple_t* row, /*!< in/out: row where replaced,
1083
dtuple_t* row, /* in/out: row where replaced,
1117
1084
indexed by col_no;
1118
1085
the clustered index record must be
1119
1086
covered by a lock or a page latch to
1120
1087
prevent deletion (rollback or purge) */
1121
row_ext_t** ext, /*!< out, own: NULL, or externally
1088
row_ext_t** ext, /* out, own: NULL, or externally
1122
1089
stored column prefixes */
1123
const dict_index_t* index, /*!< in: clustered index */
1124
const upd_t* update, /*!< in: an update vector built for the
1090
const dict_index_t* index, /* in: clustered index */
1091
const upd_t* update, /* in: an update vector built for the
1125
1092
clustered index */
1126
mem_heap_t* heap) /*!< in: memory heap */
1093
mem_heap_t* heap) /* in: memory heap */
1193
/***********************************************************//**
1160
/***************************************************************
1194
1161
Checks if an update vector changes an ordering field of an index record.
1196
1162
This function is fast if the update vector is short or the number of ordering
1197
1163
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 */
1164
NOTE: we compare the fields as binary strings! */
1202
1167
row_upd_changes_ord_field_binary(
1203
1168
/*=============================*/
1204
const dtuple_t* row, /*!< in: old value of row, or NULL if the
1169
/* out: TRUE if update vector changes
1170
an ordering field in the index record;
1171
NOTE: the fields are compared as binary
1173
const dtuple_t* row, /* in: old value of row, or NULL if the
1205
1174
row and the data values in update are not
1206
1175
known when this function is called, e.g., at
1207
1176
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
1177
dict_index_t* index, /* in: index of the record */
1178
const upd_t* update) /* in: update vector for the row; NOTE: the
1210
1179
field numbers in this MUST be clustered index
1262
/***********************************************************//**
1231
/***************************************************************
1263
1232
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
1233
NOTE: we compare the fields as binary strings! */
1269
1236
row_upd_changes_some_index_ord_field_binary(
1270
1237
/*========================================*/
1271
const dict_table_t* table, /*!< in: table */
1272
const upd_t* update) /*!< in: update vector for the row */
1238
/* out: TRUE if update vector
1239
may change an ordering field
1240
in an index record */
1241
const dict_table_t* table, /* in: table */
1242
const upd_t* update) /* in: update vector for the row */
1274
1244
upd_field_t* upd_field;
1275
1245
dict_index_t* index;
1295
/***********************************************************//**
1265
/***************************************************************
1296
1266
Checks if an update vector changes some of the first ordering fields of an
1297
1267
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 */
1268
that index does not contain column prefixes. */
1302
1271
row_upd_changes_first_fields_binary(
1303
1272
/*================================*/
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 */
1273
/* out: TRUE if changes */
1274
dtuple_t* entry, /* in: index entry */
1275
dict_index_t* index, /* in: index of entry */
1276
const upd_t* update, /* in: update vector for the row */
1277
ulint n) /* in: how many first fields to check */
1309
1279
ulint n_upd_fields;
1349
/*********************************************************************//**
1319
/*************************************************************************
1350
1320
Copies the column values from a record. */
1353
1323
row_upd_copy_columns(
1354
1324
/*=================*/
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
1325
rec_t* rec, /* in: record in a clustered index */
1326
const ulint* offsets,/* in: array returned by rec_get_offsets() */
1327
sym_node_t* column) /* in: first column in a column list, or
1364
1334
data = rec_get_nth_field(rec, offsets,
1365
1335
column->field_nos[SYM_CLUST_FIELD_NO],
1337
if (len == UNIV_SQL_NULL) {
1338
len = UNIV_SQL_NULL;
1367
1340
eval_node_copy_and_alloc_val(column, data, len);
1369
1342
column = UT_LIST_GET_NEXT(col_var_list, column);
1373
/*********************************************************************//**
1346
/*************************************************************************
1374
1347
Calculates the new values for fields to update. Note that row_upd_copy_columns
1375
1348
must have been called first. */
1378
1351
row_upd_eval_new_vals(
1379
1352
/*==================*/
1380
upd_t* update) /*!< in/out: update vector */
1353
upd_t* update) /* in/out: update vector */
1382
1355
que_node_t* exp;
1383
1356
upd_field_t* upd_field;
1426
1398
offsets = rec_get_offsets(rec, clust_index, offsets_,
1427
1399
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
1400
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
1443
NULL, ext, node->heap);
1401
NULL, &node->ext, node->heap);
1444
1402
if (node->is_delete) {
1445
1403
node->upd_row = NULL;
1446
1404
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 */
1416
/***************************************************************
1417
Updates a secondary index entry of a row. */
1464
1420
row_upd_sec_index_entry(
1465
1421
/*====================*/
1466
upd_node_t* node, /*!< in: row update node */
1467
que_thr_t* thr) /*!< in: query thread */
1422
/* out: DB_SUCCESS if operation successfully
1423
completed, else error code or DB_LOCK_WAIT */
1424
upd_node_t* node, /* in: row update node */
1425
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;
1429
dict_index_t* index;
1435
ulint err = DB_SUCCESS;
1437
trx_t* trx = thr_get_trx(thr);
1482
1439
index = node->index;
1484
referenced = row_upd_index_is_referenced(index, trx);
1441
check_ref = row_upd_index_is_referenced(index, trx);
1486
1443
heap = mem_heap_create(1024);
1489
1446
entry = row_build_index_entry(node->row, node->ext, index, heap);
1492
1450
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,
1452
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
1508
1454
btr_cur = btr_pcur_get_btr_cur(&pcur);
1510
1456
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. */
1458
if (UNIV_UNLIKELY(!found)) {
1521
1459
fputs("InnoDB: error in sec index entry update in\n"
1522
1460
"InnoDB: ", stderr);
1523
1461
dict_index_name_print(stderr, trx, index);
1535
1473
"InnoDB: Submit a detailed bug report"
1536
1474
" to http://bugs.mysql.com\n", stderr);
1539
1476
/* Delete mark the old index record; it can already be
1540
1477
delete marked if we return after a lock wait in
1541
1478
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,
1480
if (!rec_get_deleted_flag(rec,
1481
dict_table_is_comp(index->table))) {
1482
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
1484
if (err == DB_SUCCESS && check_ref) {
1486
ulint* offsets = rec_get_offsets(
1488
ULINT_UNDEFINED, &heap);
1557
1489
/* NOTE that the following call loses
1558
1490
the position of pcur ! */
1559
1491
err = row_upd_check_references_constraints(
1589
/***********************************************************//**
1520
/***************************************************************
1590
1521
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 */
1522
deletes it if this is a delete. */
1596
1525
row_upd_sec_step(
1597
1526
/*=============*/
1598
upd_node_t* node, /*!< in: row update node */
1599
que_thr_t* thr) /*!< in: query thread */
1527
/* out: DB_SUCCESS if operation successfully
1528
completed, else error code or DB_LOCK_WAIT */
1529
upd_node_t* node, /* in: row update node */
1530
que_thr_t* thr) /* in: query thread */
1601
1532
ut_ad((node->state == UPD_NODE_UPDATE_ALL_SEC)
1602
1533
|| (node->state == UPD_NODE_UPDATE_SOME_SEC));
1611
1542
return(DB_SUCCESS);
1614
/***********************************************************//**
1545
/***************************************************************
1615
1546
Marks the clustered index record deleted and inserts the updated version
1616
1547
of the record to the index. This function should be used when the ordering
1617
1548
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 */
1549
database applications. */
1623
1552
row_upd_clust_rec_by_insert(
1624
1553
/*========================*/
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
1554
/* out: DB_SUCCESS if operation successfully
1555
completed, else error code or DB_LOCK_WAIT */
1556
upd_node_t* node, /* in: row update node */
1557
dict_index_t* index, /* in: clustered index of the record */
1558
que_thr_t* thr, /* in: query thread */
1559
ibool check_ref,/* in: TRUE if index may be referenced in
1629
1560
a foreign key constraint */
1630
mtr_t* mtr) /*!< in: mtr; gets committed here */
1561
mtr_t* mtr) /* in: mtr; gets committed here */
1632
1563
mem_heap_t* heap = NULL;
1633
1564
btr_pcur_t* pcur;
1669
1599
index = dict_table_get_first_index(table);
1670
1600
offsets = rec_get_offsets(rec, index, offsets_,
1671
1601
ULINT_UNDEFINED, &heap);
1672
change_ownership = btr_cur_mark_extern_inherited_fields(
1673
btr_cur_get_page_zip(btr_cur), rec, index, offsets,
1602
btr_cur_mark_extern_inherited_fields(
1603
btr_cur_get_page_zip(btr_cur),
1604
rec, index, offsets, node->update, mtr);
1676
1606
/* NOTE that the following call loses
1677
1607
the position of pcur ! */
1679
1608
err = row_upd_check_references_constraints(
1680
1609
node, pcur, table, index, offsets, thr, mtr);
1682
1610
if (err != DB_SUCCESS) {
1684
1611
mtr_commit(mtr);
1686
1612
if (UNIV_LIKELY_NULL(heap)) {
1687
1613
mem_heap_free(heap);
1730
/***********************************************************//**
1654
/***************************************************************
1731
1655
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
1659
row_upd_clust_rec(
1738
1660
/*==============*/
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 */
1661
/* out: DB_SUCCESS if operation successfully
1662
completed, else error code or DB_LOCK_WAIT */
1663
upd_node_t* node, /* in: row update node */
1664
dict_index_t* index, /* in: clustered index */
1665
que_thr_t* thr, /* in: query thread */
1666
mtr_t* mtr) /* in: mtr; gets committed here */
1744
1668
mem_heap_t* heap = NULL;
1745
1669
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 */
1757
/***************************************************************
1758
Delete marks a clustered index record. */
1838
1761
row_upd_del_mark_clust_rec(
1839
1762
/*=======================*/
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
1763
/* out: DB_SUCCESS if operation successfully
1764
completed, else error code */
1765
upd_node_t* node, /* in: row update node */
1766
dict_index_t* index, /* in: clustered index */
1767
ulint* offsets,/* in/out: rec_get_offsets() for the
1843
1768
record under the cursor */
1844
que_thr_t* thr, /*!< in: query thread */
1846
/*!< in: TRUE if index may be referenced in
1769
que_thr_t* thr, /* in: query thread */
1770
ibool check_ref,/* in: TRUE if index may be referenced in
1847
1771
a foreign key constraint */
1848
mtr_t* mtr) /*!< in: mtr; gets committed here */
1772
mtr_t* mtr) /* in: mtr; gets committed here */
1850
1774
btr_pcur_t* pcur;
1851
1775
btr_cur_t* btr_cur;
1869
1793
err = btr_cur_del_mark_set_clust_rec(BTR_NO_LOCKING_FLAG,
1870
1794
btr_cur, TRUE, thr, mtr);
1871
if (err == DB_SUCCESS && referenced) {
1795
if (err == DB_SUCCESS && check_ref) {
1872
1796
/* 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);
1798
err = row_upd_check_references_constraints(node,
1878
1804
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 */
1809
/***************************************************************
1810
Updates the clustered index record. */
1889
1813
row_upd_clust_step(
1890
1814
/*===============*/
1891
upd_node_t* node, /*!< in: row update node */
1892
que_thr_t* thr) /*!< in: query thread */
1815
/* out: DB_SUCCESS if operation successfully
1816
completed, DB_LOCK_WAIT in case of a lock wait,
1818
upd_node_t* node, /* in: row update node */
1819
que_thr_t* thr) /* in: query thread */
1894
1821
dict_index_t* index;
1895
1822
btr_pcur_t* pcur;
1975
1903
/* NOTE: the following function calls will also commit mtr */
1977
1905
if (node->is_delete) {
1978
err = row_upd_del_mark_clust_rec(
1979
node, index, offsets, thr, referenced, mtr);
1906
err = row_upd_del_mark_clust_rec(node, index, offsets,
1907
thr, check_ref, mtr);
1981
1908
if (err == DB_SUCCESS) {
1982
1909
node->state = UPD_NODE_UPDATE_ALL_SEC;
1983
1910
node->index = dict_table_get_next_index(index);
2053
/***********************************************************//**
1979
/***************************************************************
2054
1980
Updates the affected index records of a row. When the control is transferred
2055
1981
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 */
1982
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 */
1987
/* out: DB_SUCCESS if operation successfully
1988
completed, else error code or DB_LOCK_WAIT */
1989
upd_node_t* node, /* in: row update node */
1990
que_thr_t* thr) /* in: query thread */
2066
1992
ulint err = DB_SUCCESS;