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 4/20/1996 Heikki Tuuri
24
7
*******************************************************/
51
33
#define ROW_INS_PREV 1
52
34
#define ROW_INS_NEXT 2
37
/*********************************************************************
38
This prototype is copied from /mysql/sql/ha_innodb.cc.
39
Invalidates the MySQL query cache for the table.
40
NOTE that the exact prototype of this function has to be in
41
/innobase/row/row0ins.c! */
44
innobase_invalidate_query_cache(
45
/*============================*/
46
trx_t* trx, /* in: transaction which modifies the table */
47
char* full_name, /* in: concatenation of database name, null
48
char '\0', table name, null char'\0';
49
NOTE that in Windows this is always
51
ulint full_name_len); /* in: full name length where also the null
54
54
/*************************************************************************
55
IMPORTANT NOTE: Any operation that generates redo MUST check that there
56
is enough space in the redo log before for that operation. This is
57
done by calling log_free_check(). The reason for checking the
58
availability of the redo log space before the start of the operation is
59
that we MUST not hold any synchonization objects when performing the
61
If you make a change in this module make sure that no codepath is
62
introduced where a call to log_free_check() is bypassed. */
64
/*********************************************************************//**
65
Creates an insert node struct.
66
@return own: insert node struct */
55
Creates an insert node struct. */
71
ulint ins_type, /*!< in: INS_VALUES, ... */
72
dict_table_t* table, /*!< in: table where to insert */
73
mem_heap_t* heap) /*!< in: mem heap where created */
60
/* out, own: insert node struct */
61
ulint ins_type, /* in: INS_VALUES, ... */
62
dict_table_t* table, /* in: table where to insert */
63
mem_heap_t* heap) /* in: mem heap where created */
77
node = static_cast<ins_node_t *>(mem_heap_alloc(heap, sizeof(ins_node_t)));
67
node = mem_heap_alloc(heap, sizeof(ins_node_t));
79
69
node->common.type = QUE_NODE_INSERT;
99
/***********************************************************//**
89
/***************************************************************
100
90
Creates an entry template for each index of a table. */
103
93
ins_node_create_entry_list(
104
94
/*=======================*/
105
ins_node_t* node) /*!< in: row insert node */
95
ins_node_t* node) /* in: row insert node */
107
97
dict_index_t* index;
125
/*****************************************************************//**
115
/*********************************************************************
126
116
Adds system field buffers to a row. */
129
119
row_ins_alloc_sys_fields(
130
120
/*=====================*/
131
ins_node_t* node) /*!< in: insert node */
121
ins_node_t* node) /* in: insert node */
134
124
dict_table_t* table;
151
141
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
153
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROW_ID_LEN));
143
ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN);
155
145
dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);
161
151
col = dict_table_get_sys_col(table, DATA_TRX_ID);
163
153
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
164
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_TRX_ID_LEN));
154
ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
166
156
dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);
172
162
col = dict_table_get_sys_col(table, DATA_ROLL_PTR);
174
164
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
175
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN));
165
ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
177
167
dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);
180
/*********************************************************************//**
170
/*************************************************************************
181
171
Sets a new row to insert for an INS_DIRECT node. This function is only used
182
172
if we have constructed the row separately, which is a rare case; this
183
173
function is quite slow. */
186
176
ins_node_set_new_row(
187
177
/*=================*/
188
ins_node_t* node, /*!< in: insert node */
189
dtuple_t* row) /*!< in: new row (or first row) for the node */
178
ins_node_t* node, /* in: insert node */
179
dtuple_t* row) /* in: new row (or first row) for the node */
191
181
node->state = INS_NODE_SET_IX_LOCK;
192
182
node->index = NULL;
207
197
/* As we allocated a new trx id buf, the trx id should be written
200
node->trx_id = ut_dulint_zero;
213
/*******************************************************************//**
203
/***********************************************************************
214
204
Does an insert operation by updating a delete-marked existing record
215
205
in the index. This situation can occur if the delete-marked record is
216
kept in the index for consistent reads.
217
@return DB_SUCCESS or error code */
206
kept in the index for consistent reads. */
220
209
row_ins_sec_index_entry_by_modify(
221
210
/*==============================*/
222
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
211
/* out: DB_SUCCESS or error code */
212
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
223
213
depending on whether mtr holds just a leaf
224
214
latch or also a tree latch */
225
btr_cur_t* cursor, /*!< in: B-tree cursor */
226
const dtuple_t* entry, /*!< in: index entry to insert */
227
que_thr_t* thr, /*!< in: query thread */
228
mtr_t* mtr) /*!< in: mtr; must be committed before
215
btr_cur_t* cursor, /* in: B-tree cursor */
216
const dtuple_t* entry, /* in: index entry to insert */
217
que_thr_t* thr, /* in: query thread */
218
mtr_t* mtr) /* in: mtr; must be committed before
229
219
latching any further pages */
231
221
big_rec_t* dummy_big_rec;
284
/*******************************************************************//**
274
/***********************************************************************
285
275
Does an insert operation by delete unmarking and updating a delete marked
286
276
existing record in the index. This situation can occur if the delete marked
287
record is kept in the index for consistent reads.
288
@return DB_SUCCESS, DB_FAIL, or error code */
277
record is kept in the index for consistent reads. */
291
280
row_ins_clust_index_entry_by_modify(
292
281
/*================================*/
293
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
282
/* out: DB_SUCCESS, DB_FAIL, or error code */
283
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
294
284
depending on whether mtr holds just a leaf
295
285
latch or also a tree latch */
296
btr_cur_t* cursor, /*!< in: B-tree cursor */
297
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
298
big_rec_t** big_rec,/*!< out: possible big rec vector of fields
286
btr_cur_t* cursor, /* in: B-tree cursor */
287
mem_heap_t** heap, /* in/out: pointer to memory heap, or NULL */
288
big_rec_t** big_rec,/* out: possible big rec vector of fields
299
289
which have to be stored externally by the
301
const dtuple_t* entry, /*!< in: index entry to insert */
302
que_thr_t* thr, /*!< in: query thread */
303
mtr_t* mtr) /*!< in: mtr; must be committed before
291
const dtuple_t* entry, /* in: index entry to insert */
292
que_thr_t* thr, /* in: query thread */
293
mtr_t* mtr) /* in: mtr; must be committed before
304
294
latching any further pages */
356
/*********************************************************************//**
346
/*************************************************************************
357
347
Returns TRUE if in a cascaded update/delete an ancestor node of node
358
updates (not DELETE, but UPDATE) table.
359
@return TRUE if an ancestor updates table */
348
updates (not DELETE, but UPDATE) table. */
362
351
row_ins_cascade_ancestor_updates_table(
363
352
/*===================================*/
364
que_node_t* node, /*!< in: node in a query graph */
365
dict_table_t* table) /*!< in: table */
353
/* out: TRUE if an ancestor updates table */
354
que_node_t* node, /* in: node in a query graph */
355
dict_table_t* table) /* in: table */
367
357
que_node_t* parent;
368
358
upd_node_t* upd_node;
389
/*********************************************************************//**
379
/*************************************************************************
390
380
Returns the number of ancestor UPDATE or DELETE nodes of a
391
cascaded update/delete node.
392
@return number of ancestors */
381
cascaded update/delete node. */
395
384
row_ins_cascade_n_ancestors(
396
385
/*========================*/
397
que_node_t* node) /*!< in: node in a query graph */
386
/* out: number of ancestors */
387
que_node_t* node) /* in: node in a query graph */
399
389
que_node_t* parent;
400
390
ulint n_ancestors = 0;
412
402
return(n_ancestors);
415
/******************************************************************//**
405
/**********************************************************************
416
406
Calculates the update vector node->cascade->update for a child table in
418
@return number of fields in the calculated update vector; the value
419
can also be 0 if no foreign key fields changed; the returned value is
420
ULINT_UNDEFINED if the column type in the child table is too short to
421
fit the new value in the parent table: that means the update fails */
407
a cascaded update. */
424
410
row_ins_cascade_calc_update_vec(
425
411
/*============================*/
426
upd_node_t* node, /*!< in: update node of the parent
412
/* out: number of fields in the
413
calculated update vector; the value
414
can also be 0 if no foreign key
415
fields changed; the returned value
416
is ULINT_UNDEFINED if the column
417
type in the child table is too short
418
to fit the new value in the parent
419
table: that means the update fails */
420
upd_node_t* node, /* in: update node of the parent
428
dict_foreign_t* foreign, /*!< in: foreign key constraint whose
422
dict_foreign_t* foreign, /* in: foreign key constraint whose
430
mem_heap_t* heap) /*!< in: memory heap to use as
424
mem_heap_t* heap) /* in: memory heap to use as
431
425
temporary storage */
433
427
upd_node_t* cascade = node->cascade_node;
516
510
if (!dfield_is_null(&ufield->new_val)
517
511
&& dtype_get_at_most_n_mbchars(
518
col->prtype, col->mbminmaxlen,
513
col->mbminlen, col->mbmaxlen,
521
static_cast<const char *>(dfield_get_data(&ufield->new_val)))
516
dfield_get_data(&ufield->new_val))
524
519
return(ULINT_UNDEFINED);
539
534
if (min_size > ufield_len) {
546
padded_data = static_cast<unsigned char *>(mem_heap_alloc(
549
pad = padded_data + ufield_len;
550
pad_len = min_size - ufield_len;
541
pad_start = padded_data + ufield_len;
542
pad_end = padded_data + min_size;
552
544
memcpy(padded_data,
553
545
dfield_get_data(&ufield
557
mbminlen = dict_col_get_mbminlen(col);
559
ut_ad(!(ufield_len % mbminlen));
560
ut_ad(!(min_size % mbminlen));
563
&& dtype_get_charset_coll(
565
== DATA_MYSQL_BINARY_CHARSET_COLL) {
566
/* Do not pad BINARY columns */
547
dfield_get_len(&ufield
550
switch (UNIV_EXPECT(col->mbminlen,1)) {
567
553
return(ULINT_UNDEFINED);
556
(dtype_get_charset_coll(
558
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
561
return(ULINT_UNDEFINED);
565
memset(pad_start, 0x20,
566
pad_end - pad_start);
570
ut_a(!(ufield_len % 2));
571
ut_a(!(min_size % 2));
575
} while (pad_start < pad_end);
570
row_mysql_pad_col(mbminlen,
572
579
dfield_set_data(&ufield->new_val,
573
580
padded_data, min_size);
583
590
return(n_fields_updated);
586
/*********************************************************************//**
593
/*************************************************************************
587
594
Set detailed error message associated with foreign key errors for
588
595
the given transaction. */
591
598
row_ins_set_detailed(
592
599
/*=================*/
593
trx_t* trx, /*!< in: transaction */
594
dict_foreign_t* foreign) /*!< in: foreign key constraint */
600
trx_t* trx, /* in: transaction */
601
dict_foreign_t* foreign) /* in: foreign key constraint */
596
603
mutex_enter(&srv_misc_tmpfile_mutex);
597
604
rewind(srv_misc_tmpfile);
609
616
mutex_exit(&srv_misc_tmpfile_mutex);
612
/*********************************************************************//**
619
/*************************************************************************
613
620
Reports a foreign key error associated with an update or a delete of a
614
621
parent table index entry. */
617
624
row_ins_foreign_report_err(
618
625
/*=======================*/
619
const char* errstr, /*!< in: error string from the viewpoint
626
const char* errstr, /* in: error string from the viewpoint
620
627
of the parent table */
621
que_thr_t* thr, /*!< in: query thread whose run_node
628
que_thr_t* thr, /* in: query thread whose run_node
622
629
is an update node */
623
dict_foreign_t* foreign, /*!< in: foreign key constraint */
624
const rec_t* rec, /*!< in: a matching index record in the
630
dict_foreign_t* foreign, /* in: foreign key constraint */
631
const rec_t* rec, /* in: a matching index record in the
626
const dtuple_t* entry) /*!< in: index entry in the parent
633
const dtuple_t* entry) /* in: index entry in the parent
629
636
FILE* ef = dict_foreign_err_file;
665
672
mutex_exit(&dict_foreign_err_mutex);
668
/*********************************************************************//**
675
/*************************************************************************
669
676
Reports a foreign key error to dict_foreign_err_file when we are trying
670
677
to add an index entry to a child table. Note that the adding may be the result
671
678
of an update, too. */
674
681
row_ins_foreign_report_add_err(
675
682
/*===========================*/
676
trx_t* trx, /*!< in: transaction */
677
dict_foreign_t* foreign, /*!< in: foreign key constraint */
678
const rec_t* rec, /*!< in: a record in the parent table:
683
trx_t* trx, /* in: transaction */
684
dict_foreign_t* foreign, /* in: foreign key constraint */
685
const rec_t* rec, /* in: a record in the parent table:
679
686
it does not match entry because we
680
687
have an error! */
681
const dtuple_t* entry) /*!< in: index entry to insert in the
688
const dtuple_t* entry) /* in: index entry to insert in the
684
691
FILE* ef = dict_foreign_err_file;
723
730
mutex_exit(&dict_foreign_err_mutex);
726
/*********************************************************************//**
733
/*************************************************************************
727
734
Invalidate the query cache for the given table. */
730
737
row_ins_invalidate_query_cache(
731
738
/*===========================*/
732
que_thr_t* unused, /*!< in: query thread whose run_node
739
que_thr_t* thr, /* in: query thread whose run_node
733
740
is an update node */
734
const char* name) /*!< in: table name prefixed with
741
const char* name) /* in: table name prefixed with
735
742
database name and a '/' character */
739
746
ulint len = strlen(name) + 1;
743
748
buf = mem_strdupl(name, len);
745
750
ptr = strchr(buf, '/');
754
/* We call a function in ha_innodb.cc */
755
#ifndef UNIV_HOTBACKUP
756
innobase_invalidate_query_cache(thr_get_trx(thr), buf, len);
752
/*********************************************************************//**
761
/*************************************************************************
753
762
Perform referential actions or checks when a parent row is deleted or updated
754
763
and the constraint had an ON DELETE or ON UPDATE condition which was not
756
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
759
767
row_ins_foreign_check_on_constraint(
760
768
/*================================*/
761
que_thr_t* thr, /*!< in: query thread whose run_node
769
/* out: DB_SUCCESS, DB_LOCK_WAIT,
771
que_thr_t* thr, /* in: query thread whose run_node
762
772
is an update node */
763
dict_foreign_t* foreign, /*!< in: foreign key constraint whose
773
dict_foreign_t* foreign, /* in: foreign key constraint whose
765
btr_pcur_t* pcur, /*!< in: cursor placed on a matching
775
btr_pcur_t* pcur, /* in: cursor placed on a matching
766
776
index record in the child table */
767
dtuple_t* entry, /*!< in: index entry in the parent
777
dtuple_t* entry, /* in: index entry in the parent
769
mtr_t* mtr) /*!< in: mtr holding the latch of pcur
779
mtr_t* mtr) /* in: mtr holding the latch of pcur
772
782
upd_node_t* node;
1118
/*********************************************************************//**
1128
/*************************************************************************
1119
1129
Sets a shared lock on a record. Used in locking possible duplicate key
1120
records and also in checking foreign key constraints.
1121
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1130
records and also in checking foreign key constraints. */
1124
1133
row_ins_set_shared_rec_lock(
1125
1134
/*========================*/
1126
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1135
/* out: DB_SUCCESS or error code */
1136
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1127
1137
LOCK_REC_NOT_GAP type lock */
1128
const buf_block_t* block, /*!< in: buffer block of rec */
1129
const rec_t* rec, /*!< in: record */
1130
dict_index_t* index, /*!< in: index */
1131
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1132
que_thr_t* thr) /*!< in: query thread */
1138
const buf_block_t* block, /* in: buffer block of rec */
1139
const rec_t* rec, /* in: record */
1140
dict_index_t* index, /* in: index */
1141
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1142
que_thr_t* thr) /* in: query thread */
1136
1146
ut_ad(rec_offs_validate(rec, index, offsets));
1149
/*********************************************************************//**
1159
#ifndef UNIV_HOTBACKUP
1160
/*************************************************************************
1150
1161
Sets a exclusive lock on a record. Used in locking possible duplicate key
1152
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1155
1165
row_ins_set_exclusive_rec_lock(
1156
1166
/*===========================*/
1157
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1167
/* out: DB_SUCCESS or error code */
1168
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1158
1169
LOCK_REC_NOT_GAP type lock */
1159
const buf_block_t* block, /*!< in: buffer block of rec */
1160
const rec_t* rec, /*!< in: record */
1161
dict_index_t* index, /*!< in: index */
1162
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1163
que_thr_t* thr) /*!< in: query thread */
1170
const buf_block_t* block, /* in: buffer block of rec */
1171
const rec_t* rec, /* in: record */
1172
dict_index_t* index, /* in: index */
1173
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1174
que_thr_t* thr) /* in: query thread */
1167
1178
ut_ad(rec_offs_validate(rec, index, offsets));
1190
#endif /* !UNIV_HOTBACKUP */
1180
/***************************************************************//**
1192
/*******************************************************************
1181
1193
Checks if foreign key constraint fails for an index entry. Sets shared locks
1182
1194
which lock either the success or the failure of the constraint. NOTE that
1183
the caller must have a shared latch on dict_operation_lock.
1184
@return DB_SUCCESS, DB_NO_REFERENCED_ROW, or DB_ROW_IS_REFERENCED */
1195
the caller must have a shared latch on dict_operation_lock. */
1187
1198
row_ins_check_foreign_constraint(
1188
1199
/*=============================*/
1189
ibool check_ref,/*!< in: TRUE if we want to check that
1201
DB_NO_REFERENCED_ROW,
1202
or DB_ROW_IS_REFERENCED */
1203
ibool check_ref,/* in: TRUE if we want to check that
1190
1204
the referenced table is ok, FALSE if we
1191
want to check the foreign key table */
1192
dict_foreign_t* foreign,/*!< in: foreign constraint; NOTE that the
1205
want to to check the foreign key table */
1206
dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the
1193
1207
tables mentioned in it must be in the
1194
1208
dictionary cache if they exist at all */
1195
dict_table_t* table, /*!< in: if check_ref is TRUE, then the foreign
1209
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
1196
1210
table, else the referenced table */
1197
dtuple_t* entry, /*!< in: index entry for index */
1198
que_thr_t* thr) /*!< in: query thread */
1211
dtuple_t* entry, /* in: index entry for index */
1212
que_thr_t* thr) /* in: query thread */
1200
1214
upd_node_t* upd_node;
1201
1215
dict_table_t* check_table;
1202
1216
dict_index_t* check_index;
1203
1217
ulint n_fields_cmp;
1204
1218
btr_pcur_t pcur;
1240
1255
if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
1241
upd_node = static_cast<upd_node_t *>(thr->run_node);
1256
upd_node = thr->run_node;
1243
1258
if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
1244
1259
/* If a cascaded update is done as defined by a
1333
1348
/* Scan index records and check if there is a matching record */
1336
1351
const rec_t* rec = btr_pcur_get_rec(&pcur);
1337
1352
const buf_block_t* block = btr_pcur_get_block(&pcur);
1339
1354
if (page_rec_is_infimum(rec)) {
1344
1359
offsets = rec_get_offsets(rec, check_index,
1382
1393
LOCK_REC_NOT_GAP, block,
1383
1394
rec, check_index, offsets, thr);
1386
case DB_SUCCESS_LOCKED_REC:
1396
if (err != DB_SUCCESS) {
1393
1401
if (check_ref) {
1394
1402
err = DB_SUCCESS;
1397
1405
} else if (foreign->type != 0) {
1398
1406
/* There is an ON UPDATE or ON DELETE
1399
1407
condition: check them in a separate
1432
1440
thr, foreign, rec, entry);
1434
1442
err = DB_ROW_IS_REFERENCED;
1441
1449
err = row_ins_set_shared_rec_lock(
1442
1450
LOCK_GAP, block,
1443
1451
rec, check_index, offsets, thr);
1446
case DB_SUCCESS_LOCKED_REC:
1449
err = DB_NO_REFERENCED_ROW;
1450
row_ins_foreign_report_add_err(
1451
trx, foreign, rec, entry);
1459
} while (btr_pcur_move_to_next(&pcur, &mtr));
1462
row_ins_foreign_report_add_err(
1463
trx, foreign, btr_pcur_get_rec(&pcur), entry);
1464
err = DB_NO_REFERENCED_ROW;
1452
if (err != DB_SUCCESS) {
1458
err = DB_NO_REFERENCED_ROW;
1459
row_ins_foreign_report_add_err(
1460
trx, foreign, rec, entry);
1470
moved = btr_pcur_move_to_next(&pcur, &mtr);
1474
rec = btr_pcur_get_rec(&pcur);
1475
row_ins_foreign_report_add_err(
1476
trx, foreign, rec, entry);
1477
err = DB_NO_REFERENCED_ROW;
1470
1486
btr_pcur_close(&pcur);
1472
1488
mtr_commit(&mtr);
1500
/***************************************************************//**
1516
/*******************************************************************
1501
1517
Checks if foreign key constraints fail for an index entry. If index
1502
1518
is not mentioned in any constraint, this function does nothing,
1503
1519
Otherwise does searches to the indexes of referenced tables and
1504
1520
sets shared locks which lock either the success or the failure of
1506
@return DB_SUCCESS or error code */
1509
1524
row_ins_check_foreign_constraints(
1510
1525
/*==============================*/
1511
dict_table_t* table, /*!< in: table */
1512
dict_index_t* index, /*!< in: index */
1513
dtuple_t* entry, /*!< in: index entry for index */
1514
que_thr_t* thr) /*!< in: query thread */
1526
/* out: DB_SUCCESS or error code */
1527
dict_table_t* table, /* in: table */
1528
dict_index_t* index, /* in: index */
1529
dtuple_t* entry, /* in: index entry for index */
1530
que_thr_t* thr) /* in: query thread */
1516
1532
dict_foreign_t* foreign;
1579
1595
return(DB_SUCCESS);
1582
/***************************************************************//**
1598
#ifndef UNIV_HOTBACKUP
1599
/*******************************************************************
1583
1600
Checks if a unique key violation to rec would occur at the index entry
1585
@return TRUE if error */
1588
1604
row_ins_dupl_error_with_rec(
1589
1605
/*========================*/
1590
const rec_t* rec, /*!< in: user record; NOTE that we assume
1606
/* out: TRUE if error */
1607
const rec_t* rec, /* in: user record; NOTE that we assume
1591
1608
that the caller already has a record lock on
1593
const dtuple_t* entry, /*!< in: entry to insert */
1594
dict_index_t* index, /*!< in: index */
1595
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
1610
const dtuple_t* entry, /* in: entry to insert */
1611
dict_index_t* index, /* in: index */
1612
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
1597
1614
ulint matched_fields;
1598
1615
ulint matched_bytes;
1631
1648
return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
1650
#endif /* !UNIV_HOTBACKUP */
1634
/***************************************************************//**
1652
/*******************************************************************
1635
1653
Scans a unique non-clustered index at a given index entry to determine
1636
1654
whether a uniqueness violation has occurred for the key value of the entry.
1637
Set shared locks on possible duplicate records.
1638
@return DB_SUCCESS, DB_DUPLICATE_KEY, or DB_LOCK_WAIT */
1655
Set shared locks on possible duplicate records. */
1641
1658
row_ins_scan_sec_index_for_duplicate(
1642
1659
/*=================================*/
1643
dict_index_t* index, /*!< in: non-clustered unique index */
1644
dtuple_t* entry, /*!< in: index entry */
1645
que_thr_t* thr) /*!< in: query thread */
1660
/* out: DB_SUCCESS, DB_DUPLICATE_KEY, or
1662
dict_index_t* index, /* in: non-clustered unique index */
1663
dtuple_t* entry, /* in: index entry */
1664
que_thr_t* thr) /* in: query thread */
1666
#ifndef UNIV_HOTBACKUP
1647
1667
ulint n_unique;
1755
1773
dtuple_set_n_fields_cmp(entry, n_fields_cmp);
1776
#else /* UNIV_HOTBACKUP */
1777
/* This function depends on MySQL code that is not included in
1778
InnoDB Hot Backup builds. Besides, this function should never
1779
be called in InnoDB Hot Backup. */
1782
#endif /* UNIV_HOTBACKUP */
1760
/***************************************************************//**
1785
/*******************************************************************
1761
1786
Checks if a unique key violation error would occur at an index entry
1762
1787
insert. Sets shared locks on possible duplicate records. Works only
1763
for a clustered index!
1764
@return DB_SUCCESS if no error, DB_DUPLICATE_KEY if error,
1765
DB_LOCK_WAIT if we have to wait for a lock on a possible duplicate
1788
for a clustered index! */
1769
1791
row_ins_duplicate_error_in_clust(
1770
1792
/*=============================*/
1771
btr_cur_t* cursor, /*!< in: B-tree cursor */
1772
const dtuple_t* entry, /*!< in: entry to insert */
1773
que_thr_t* thr, /*!< in: query thread */
1774
mtr_t* mtr) /*!< in: mtr */
1793
/* out: DB_SUCCESS if no error,
1794
DB_DUPLICATE_KEY if error, DB_LOCK_WAIT if we
1795
have to wait for a lock on a possible
1797
btr_cur_t* cursor, /* in: B-tree cursor */
1798
dtuple_t* entry, /* in: entry to insert */
1799
que_thr_t* thr, /* in: query thread */
1800
mtr_t* mtr) /* in: mtr */
1802
#ifndef UNIV_HOTBACKUP
1778
1805
ulint n_unique;
1904
1923
mem_heap_free(heap);
1926
#else /* UNIV_HOTBACKUP */
1927
/* This function depends on MySQL code that is not included in
1928
InnoDB Hot Backup builds. Besides, this function should never
1929
be called in InnoDB Hot Backup. */
1932
#endif /* UNIV_HOTBACKUP */
1909
/***************************************************************//**
1935
/*******************************************************************
1910
1936
Checks if an index entry has long enough common prefix with an existing
1911
1937
record so that the intended insert of the entry must be changed to a modify of
1912
1938
the existing record. In the case of a clustered index, the prefix must be
1913
1939
n_unique fields long, and in the case of a secondary index, all fields must be
1915
@return 0 if no update, ROW_INS_PREV if previous should be updated;
1916
currently we do the search so that only the low_match record can match
1917
enough to the search tuple, not the next record */
1920
1943
row_ins_must_modify(
1921
1944
/*================*/
1922
btr_cur_t* cursor) /*!< in: B-tree cursor */
1945
/* out: 0 if no update, ROW_INS_PREV if
1946
previous should be updated; currently we
1947
do the search so that only the low_match
1948
record can match enough to the search tuple,
1949
not the next record */
1950
btr_cur_t* cursor) /* in: B-tree cursor */
1924
1952
ulint enough_match;
1949
/***************************************************************//**
1977
/*******************************************************************
1950
1978
Tries to insert an index entry to an index. If the index is clustered
1951
1979
and a record with the same unique key is found, the other record is
1952
1980
necessarily marked deleted by a committed transaction, or a unique key
1954
1982
existing record, and we must write an undo log record on the delete
1955
1983
marked record. If the index is secondary, and a record with exactly the
1956
1984
same fields is found, the other record is necessarily marked deleted.
1957
It is then unmarked. Otherwise, the entry is just inserted to the index.
1958
@return DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL if pessimistic retry needed,
1985
It is then unmarked. Otherwise, the entry is just inserted to the index. */
1962
1988
row_ins_index_entry_low(
1963
1989
/*====================*/
1964
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
1990
/* out: DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL
1991
if pessimistic retry needed, or error code */
1992
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
1965
1993
depending on whether we wish optimistic or
1966
1994
pessimistic descent down the index tree */
1967
dict_index_t* index, /*!< in: index */
1968
dtuple_t* entry, /*!< in/out: index entry to insert */
1969
ulint n_ext, /*!< in: number of externally stored columns */
1970
que_thr_t* thr) /*!< in: query thread */
1995
dict_index_t* index, /* in: index */
1996
dtuple_t* entry, /* in: index entry to insert */
1997
ulint n_ext, /* in: number of externally stored columns */
1998
que_thr_t* thr) /* in: query thread */
1972
2000
btr_cur_t cursor;
2001
ulint ignore_sec_unique = 0;
1974
2002
ulint modify = 0; /* remove warning */
1975
2003
rec_t* insert_rec;
1990
2018
the function will return in both low_match and up_match of the
1991
2019
cursor sensible values */
1993
if (dict_index_is_clust(index)) {
1995
} else if (!(thr_get_trx(thr)->check_unique_secondary)) {
1996
search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
1998
search_mode = mode | BTR_INSERT;
2021
if (!(thr_get_trx(thr)->check_unique_secondary)) {
2022
ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
2001
2025
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2003
&cursor, 0, __FILE__, __LINE__, &mtr);
2026
mode | BTR_INSERT | ignore_sec_unique,
2005
2029
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
2006
2030
/* The insertion was made to the insert buffer already during
2007
2031
the search: we are done */
2009
ut_ad(search_mode & BTR_INSERT);
2010
2033
err = DB_SUCCESS;
2012
2035
goto function_exit;
2110
2132
mtr_commit(&mtr);
2112
2134
if (UNIV_LIKELY_NULL(big_rec)) {
2114
2136
ulint* offsets;
2115
2137
mtr_start(&mtr);
2117
2139
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2118
BTR_MODIFY_TREE, &cursor, 0,
2119
__FILE__, __LINE__, &mtr);
2120
exit_rec = btr_cur_get_rec(&cursor);
2121
offsets = rec_get_offsets(exit_rec, index, NULL,
2140
BTR_MODIFY_TREE, &cursor, 0, &mtr);
2141
rec = btr_cur_get_rec(&cursor);
2142
offsets = rec_get_offsets(rec, index, NULL,
2122
2143
ULINT_UNDEFINED, &heap);
2124
2145
err = btr_store_big_rec_extern_fields(
2125
2146
index, btr_cur_get_block(&cursor),
2126
exit_rec, offsets, big_rec, &mtr);
2147
rec, offsets, big_rec, &mtr);
2129
2150
dtuple_big_rec_free(big_rec);
2143
/***************************************************************//**
2164
/*******************************************************************
2144
2165
Inserts an index entry to index. Tries first optimistic, then pessimistic
2145
2166
descent down the tree. If the entry matches enough to a delete marked record,
2146
2167
performs the insert by updating or delete unmarking the delete marked
2148
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DUPLICATE_KEY, or some other error code */
2151
2171
row_ins_index_entry(
2152
2172
/*================*/
2153
dict_index_t* index, /*!< in: index */
2154
dtuple_t* entry, /*!< in/out: index entry to insert */
2155
ulint n_ext, /*!< in: number of externally stored columns */
2156
ibool foreign,/*!< in: TRUE=check foreign key constraints
2157
(foreign=FALSE only during CREATE INDEX) */
2158
que_thr_t* thr) /*!< in: query thread */
2173
/* out: DB_SUCCESS, DB_LOCK_WAIT,
2174
DB_DUPLICATE_KEY, or some other error code */
2175
dict_index_t* index, /* in: index */
2176
dtuple_t* entry, /* in: index entry to insert */
2177
ulint n_ext, /* in: number of externally stored columns */
2178
ibool foreign,/* in: TRUE=check foreign key constraints */
2179
que_thr_t* thr) /* in: query thread */
2162
2183
if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2163
err = static_cast<db_err>(row_ins_check_foreign_constraints(index->table, index,
2184
err = row_ins_check_foreign_constraints(index->table, index,
2165
2186
if (err != DB_SUCCESS) {
2171
2192
/* Try first optimistic descent to the B-tree */
2173
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2194
err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2175
2196
if (err != DB_FAIL) {
2180
2201
/* Try then pessimistic descent to the B-tree */
2182
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2203
err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2187
/***********************************************************//**
2208
/***************************************************************
2188
2209
Sets the values of the dtuple fields in entry from the values of appropriate
2189
2210
columns in row. */
2192
2213
row_ins_index_entry_set_vals(
2193
2214
/*=========================*/
2194
dict_index_t* index, /*!< in: index */
2195
dtuple_t* entry, /*!< in: index entry to make */
2196
const dtuple_t* row) /*!< in: row */
2215
dict_index_t* index, /* in: index */
2216
dtuple_t* entry, /* in: index entry to make */
2217
const dtuple_t* row) /* in: row */
2198
2219
ulint n_fields;
2221
2242
= dict_field_get_col(ind_field);
2223
2244
len = dtype_get_at_most_n_mbchars(
2224
col->prtype, col->mbminmaxlen,
2245
col->prtype, col->mbminlen, col->mbmaxlen,
2225
2246
ind_field->prefix_len,
2226
len, static_cast<const char *>(dfield_get_data(row_field)));
2247
len, dfield_get_data(row_field));
2228
2249
ut_ad(!dfield_is_ext(row_field));
2239
/***********************************************************//**
2240
Inserts a single index entry to the table.
2241
@return DB_SUCCESS if operation successfully completed, else error
2242
code or DB_LOCK_WAIT */
2260
/***************************************************************
2261
Inserts a single index entry to the table. */
2245
2264
row_ins_index_entry_step(
2246
2265
/*=====================*/
2247
ins_node_t* node, /*!< in: row insert node */
2248
que_thr_t* thr) /*!< in: query thread */
2266
/* out: DB_SUCCESS if operation successfully
2267
completed, else error code or DB_LOCK_WAIT */
2268
ins_node_t* node, /* in: row insert node */
2269
que_thr_t* thr) /* in: query thread */
2252
2273
ut_ad(dtuple_check_typed(node->row));
2256
2277
ut_ad(dtuple_check_typed(node->entry));
2258
err = static_cast<db_err>(row_ins_index_entry(node->index, node->entry, 0, TRUE, thr));
2279
err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
2263
/***********************************************************//**
2284
/***************************************************************
2264
2285
Allocates a row id for row and inits the node->index field. */
2267
2288
row_ins_alloc_row_id_step(
2268
2289
/*======================*/
2269
ins_node_t* node) /*!< in: row insert node */
2290
ins_node_t* node) /* in: row insert node */
2273
2294
ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
2286
2307
dict_sys_write_row_id(node->row_id_buf, row_id);
2289
/***********************************************************//**
2310
/***************************************************************
2290
2311
Gets a row to insert from the values list. */
2293
2314
row_ins_get_row_from_values(
2294
2315
/*========================*/
2295
ins_node_t* node) /*!< in: row insert node */
2316
ins_node_t* node) /* in: row insert node */
2297
2318
que_node_t* list_node;
2298
2319
dfield_t* dfield;
2322
/***********************************************************//**
2343
/***************************************************************
2323
2344
Gets a row to insert from the select list. */
2326
2347
row_ins_get_row_from_select(
2327
2348
/*========================*/
2328
ins_node_t* node) /*!< in: row insert node */
2349
ins_node_t* node) /* in: row insert node */
2330
2351
que_node_t* list_node;
2331
2352
dfield_t* dfield;
2353
/***********************************************************//**
2354
Inserts a row to a table.
2355
@return DB_SUCCESS if operation successfully completed, else error
2356
code or DB_LOCK_WAIT */
2374
/***************************************************************
2375
Inserts a row to a table. */
2361
ins_node_t* node, /*!< in: row insert node */
2362
que_thr_t* thr) /*!< in: query thread */
2380
/* out: DB_SUCCESS if operation successfully
2381
completed, else error code or DB_LOCK_WAIT */
2382
ins_node_t* node, /* in: row insert node */
2383
que_thr_t* thr) /* in: query thread */
2405
2426
return(DB_SUCCESS);
2408
/***********************************************************//**
2429
/***************************************************************
2409
2430
Inserts a row to a table. This is a high-level function used in SQL execution
2411
@return query thread to run next or NULL */
2416
que_thr_t* thr) /*!< in: query thread */
2436
/* out: query thread to run next or NULL */
2437
que_thr_t* thr) /* in: query thread */
2418
2439
ins_node_t* node;
2419
2440
que_node_t* parent;
2455
2476
/* It may be that the current session has not yet started
2456
2477
its transaction, or it has been committed: */
2458
if (trx->id == node->trx_id) {
2479
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
2459
2480
/* No need to do IX-locking */