1
1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
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
/******************************************************
21
20
Insert into a table
23
22
Created 4/20/1996 Heikki Tuuri
51
49
#define ROW_INS_PREV 1
52
50
#define ROW_INS_NEXT 2
54
53
/*************************************************************************
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 */
54
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 */
59
/* out, own: insert node struct */
60
ulint ins_type, /* in: INS_VALUES, ... */
61
dict_table_t* table, /* in: table where to insert */
62
mem_heap_t* heap) /* in: mem heap where created */
77
node = static_cast<ins_node_t *>(mem_heap_alloc(heap, sizeof(ins_node_t)));
66
node = mem_heap_alloc(heap, sizeof(ins_node_t));
79
68
node->common.type = QUE_NODE_INSERT;
99
/***********************************************************//**
88
/***************************************************************
100
89
Creates an entry template for each index of a table. */
103
92
ins_node_create_entry_list(
104
93
/*=======================*/
105
ins_node_t* node) /*!< in: row insert node */
94
ins_node_t* node) /* in: row insert node */
107
96
dict_index_t* index;
125
/*****************************************************************//**
114
/*********************************************************************
126
115
Adds system field buffers to a row. */
129
118
row_ins_alloc_sys_fields(
130
119
/*=====================*/
131
ins_node_t* node) /*!< in: insert node */
120
ins_node_t* node) /* in: insert node */
134
123
dict_table_t* table;
151
140
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
153
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROW_ID_LEN));
142
ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN);
155
144
dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);
161
150
col = dict_table_get_sys_col(table, DATA_TRX_ID);
163
152
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
164
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_TRX_ID_LEN));
153
ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN);
166
155
dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);
172
161
col = dict_table_get_sys_col(table, DATA_ROLL_PTR);
174
163
dfield = dtuple_get_nth_field(row, dict_col_get_no(col));
175
ptr = static_cast<byte *>(mem_heap_zalloc(heap, DATA_ROLL_PTR_LEN));
164
ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);
177
166
dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);
180
/*********************************************************************//**
169
/*************************************************************************
181
170
Sets a new row to insert for an INS_DIRECT node. This function is only used
182
171
if we have constructed the row separately, which is a rare case; this
183
172
function is quite slow. */
186
175
ins_node_set_new_row(
187
176
/*=================*/
188
ins_node_t* node, /*!< in: insert node */
189
dtuple_t* row) /*!< in: new row (or first row) for the node */
177
ins_node_t* node, /* in: insert node */
178
dtuple_t* row) /* in: new row (or first row) for the node */
191
180
node->state = INS_NODE_SET_IX_LOCK;
192
181
node->index = NULL;
207
196
/* As we allocated a new trx id buf, the trx id should be written
199
node->trx_id = ut_dulint_zero;
213
/*******************************************************************//**
202
/***********************************************************************
214
203
Does an insert operation by updating a delete-marked existing record
215
204
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 */
205
kept in the index for consistent reads. */
220
208
row_ins_sec_index_entry_by_modify(
221
209
/*==============================*/
222
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
210
/* out: DB_SUCCESS or error code */
211
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
223
212
depending on whether mtr holds just a leaf
224
213
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
214
btr_cur_t* cursor, /* in: B-tree cursor */
215
const dtuple_t* entry, /* in: index entry to insert */
216
que_thr_t* thr, /* in: query thread */
217
mtr_t* mtr) /* in: mtr; must be committed before
229
218
latching any further pages */
231
220
big_rec_t* dummy_big_rec;
284
/*******************************************************************//**
273
/***********************************************************************
285
274
Does an insert operation by delete unmarking and updating a delete marked
286
275
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 */
276
record is kept in the index for consistent reads. */
291
279
row_ins_clust_index_entry_by_modify(
292
280
/*================================*/
293
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
281
/* out: DB_SUCCESS, DB_FAIL, or error code */
282
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
294
283
depending on whether mtr holds just a leaf
295
284
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
285
btr_cur_t* cursor, /* in: B-tree cursor */
286
mem_heap_t** heap, /* in/out: pointer to memory heap, or NULL */
287
big_rec_t** big_rec,/* out: possible big rec vector of fields
299
288
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
290
const dtuple_t* entry, /* in: index entry to insert */
291
que_thr_t* thr, /* in: query thread */
292
mtr_t* mtr) /* in: mtr; must be committed before
304
293
latching any further pages */
356
/*********************************************************************//**
345
/*************************************************************************
357
346
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 */
347
updates (not DELETE, but UPDATE) table. */
362
350
row_ins_cascade_ancestor_updates_table(
363
351
/*===================================*/
364
que_node_t* node, /*!< in: node in a query graph */
365
dict_table_t* table) /*!< in: table */
352
/* out: TRUE if an ancestor updates table */
353
que_node_t* node, /* in: node in a query graph */
354
dict_table_t* table) /* in: table */
367
356
que_node_t* parent;
368
357
upd_node_t* upd_node;
389
/*********************************************************************//**
378
/*************************************************************************
390
379
Returns the number of ancestor UPDATE or DELETE nodes of a
391
cascaded update/delete node.
392
@return number of ancestors */
380
cascaded update/delete node. */
395
383
row_ins_cascade_n_ancestors(
396
384
/*========================*/
397
que_node_t* node) /*!< in: node in a query graph */
385
/* out: number of ancestors */
386
que_node_t* node) /* in: node in a query graph */
399
388
que_node_t* parent;
400
389
ulint n_ancestors = 0;
412
401
return(n_ancestors);
415
/******************************************************************//**
404
/**********************************************************************
416
405
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 */
406
a cascaded update. */
424
409
row_ins_cascade_calc_update_vec(
425
410
/*============================*/
426
upd_node_t* node, /*!< in: update node of the parent
411
/* out: number of fields in the
412
calculated update vector; the value
413
can also be 0 if no foreign key
414
fields changed; the returned value
415
is ULINT_UNDEFINED if the column
416
type in the child table is too short
417
to fit the new value in the parent
418
table: that means the update fails */
419
upd_node_t* node, /* in: update node of the parent
428
dict_foreign_t* foreign, /*!< in: foreign key constraint whose
421
dict_foreign_t* foreign, /* in: foreign key constraint whose
430
mem_heap_t* heap) /*!< in: memory heap to use as
423
mem_heap_t* heap) /* in: memory heap to use as
431
424
temporary storage */
433
426
upd_node_t* cascade = node->cascade_node;
516
509
if (!dfield_is_null(&ufield->new_val)
517
510
&& dtype_get_at_most_n_mbchars(
518
col->prtype, col->mbminmaxlen,
512
col->mbminlen, col->mbmaxlen,
521
static_cast<const char *>(dfield_get_data(&ufield->new_val)))
515
dfield_get_data(&ufield->new_val))
524
518
return(ULINT_UNDEFINED);
539
533
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;
540
pad_start = padded_data + ufield_len;
541
pad_end = padded_data + min_size;
552
543
memcpy(padded_data,
553
544
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 */
546
dfield_get_len(&ufield
549
switch (UNIV_EXPECT(col->mbminlen,1)) {
567
552
return(ULINT_UNDEFINED);
555
(dtype_get_charset_coll(
557
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
560
return(ULINT_UNDEFINED);
564
memset(pad_start, 0x20,
565
pad_end - pad_start);
569
ut_a(!(ufield_len % 2));
570
ut_a(!(min_size % 2));
574
} while (pad_start < pad_end);
570
row_mysql_pad_col(mbminlen,
572
578
dfield_set_data(&ufield->new_val,
573
579
padded_data, min_size);
583
589
return(n_fields_updated);
586
/*********************************************************************//**
592
/*************************************************************************
587
593
Set detailed error message associated with foreign key errors for
588
594
the given transaction. */
591
597
row_ins_set_detailed(
592
598
/*=================*/
593
trx_t* trx, /*!< in: transaction */
594
dict_foreign_t* foreign) /*!< in: foreign key constraint */
599
trx_t* trx, /* in: transaction */
600
dict_foreign_t* foreign) /* in: foreign key constraint */
596
602
mutex_enter(&srv_misc_tmpfile_mutex);
597
603
rewind(srv_misc_tmpfile);
609
615
mutex_exit(&srv_misc_tmpfile_mutex);
612
/*********************************************************************//**
618
/*************************************************************************
613
619
Reports a foreign key error associated with an update or a delete of a
614
620
parent table index entry. */
617
623
row_ins_foreign_report_err(
618
624
/*=======================*/
619
const char* errstr, /*!< in: error string from the viewpoint
625
const char* errstr, /* in: error string from the viewpoint
620
626
of the parent table */
621
que_thr_t* thr, /*!< in: query thread whose run_node
627
que_thr_t* thr, /* in: query thread whose run_node
622
628
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
629
dict_foreign_t* foreign, /* in: foreign key constraint */
630
const rec_t* rec, /* in: a matching index record in the
626
const dtuple_t* entry) /*!< in: index entry in the parent
632
const dtuple_t* entry) /* in: index entry in the parent
629
635
FILE* ef = dict_foreign_err_file;
665
671
mutex_exit(&dict_foreign_err_mutex);
668
/*********************************************************************//**
674
/*************************************************************************
669
675
Reports a foreign key error to dict_foreign_err_file when we are trying
670
676
to add an index entry to a child table. Note that the adding may be the result
671
677
of an update, too. */
674
680
row_ins_foreign_report_add_err(
675
681
/*===========================*/
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:
682
trx_t* trx, /* in: transaction */
683
dict_foreign_t* foreign, /* in: foreign key constraint */
684
const rec_t* rec, /* in: a record in the parent table:
679
685
it does not match entry because we
680
686
have an error! */
681
const dtuple_t* entry) /*!< in: index entry to insert in the
687
const dtuple_t* entry) /* in: index entry to insert in the
684
690
FILE* ef = dict_foreign_err_file;
723
729
mutex_exit(&dict_foreign_err_mutex);
726
/*********************************************************************//**
732
/*************************************************************************
727
733
Invalidate the query cache for the given table. */
730
736
row_ins_invalidate_query_cache(
731
737
/*===========================*/
732
que_thr_t* unused, /*!< in: query thread whose run_node
738
que_thr_t* unused, /* in: query thread whose run_node
733
739
is an update node */
734
const char* name) /*!< in: table name prefixed with
740
const char* name) /* in: table name prefixed with
735
741
database name and a '/' character */
752
/*********************************************************************//**
758
/*************************************************************************
753
759
Perform referential actions or checks when a parent row is deleted or updated
754
760
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
764
row_ins_foreign_check_on_constraint(
760
765
/*================================*/
761
que_thr_t* thr, /*!< in: query thread whose run_node
766
/* out: DB_SUCCESS, DB_LOCK_WAIT,
768
que_thr_t* thr, /* in: query thread whose run_node
762
769
is an update node */
763
dict_foreign_t* foreign, /*!< in: foreign key constraint whose
770
dict_foreign_t* foreign, /* in: foreign key constraint whose
765
btr_pcur_t* pcur, /*!< in: cursor placed on a matching
772
btr_pcur_t* pcur, /* in: cursor placed on a matching
766
773
index record in the child table */
767
dtuple_t* entry, /*!< in: index entry in the parent
774
dtuple_t* entry, /* in: index entry in the parent
769
mtr_t* mtr) /*!< in: mtr holding the latch of pcur
776
mtr_t* mtr) /* in: mtr holding the latch of pcur
772
779
upd_node_t* node;
802
809
row_ins_invalidate_query_cache(thr, table->name);
804
node = static_cast<upd_node_t *>(thr->run_node);
811
node = thr->run_node;
806
813
if (node->is_delete && 0 == (foreign->type
807
814
& (DICT_FOREIGN_ON_DELETE_CASCADE
1118
/*********************************************************************//**
1125
/*************************************************************************
1119
1126
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 */
1127
records and also in checking foreign key constraints. */
1124
1130
row_ins_set_shared_rec_lock(
1125
1131
/*========================*/
1126
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1132
/* out: DB_SUCCESS or error code */
1133
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1127
1134
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 */
1135
const buf_block_t* block, /* in: buffer block of rec */
1136
const rec_t* rec, /* in: record */
1137
dict_index_t* index, /* in: index */
1138
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1139
que_thr_t* thr) /* in: query thread */
1136
1143
ut_ad(rec_offs_validate(rec, index, offsets));
1149
/*********************************************************************//**
1156
#ifndef UNIV_HOTBACKUP
1157
/*************************************************************************
1150
1158
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
1162
row_ins_set_exclusive_rec_lock(
1156
1163
/*===========================*/
1157
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1164
/* out: DB_SUCCESS or error code */
1165
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
1158
1166
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 */
1167
const buf_block_t* block, /* in: buffer block of rec */
1168
const rec_t* rec, /* in: record */
1169
dict_index_t* index, /* in: index */
1170
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
1171
que_thr_t* thr) /* in: query thread */
1167
1175
ut_ad(rec_offs_validate(rec, index, offsets));
1187
#endif /* !UNIV_HOTBACKUP */
1180
/***************************************************************//**
1189
/*******************************************************************
1181
1190
Checks if foreign key constraint fails for an index entry. Sets shared locks
1182
1191
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 */
1192
the caller must have a shared latch on dict_operation_lock. */
1187
1195
row_ins_check_foreign_constraint(
1188
1196
/*=============================*/
1189
ibool check_ref,/*!< in: TRUE if we want to check that
1198
DB_NO_REFERENCED_ROW,
1199
or DB_ROW_IS_REFERENCED */
1200
ibool check_ref,/* in: TRUE if we want to check that
1190
1201
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
1202
want to to check the foreign key table */
1203
dict_foreign_t* foreign,/* in: foreign constraint; NOTE that the
1193
1204
tables mentioned in it must be in the
1194
1205
dictionary cache if they exist at all */
1195
dict_table_t* table, /*!< in: if check_ref is TRUE, then the foreign
1206
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
1196
1207
table, else the referenced table */
1197
dtuple_t* entry, /*!< in: index entry for index */
1198
que_thr_t* thr) /*!< in: query thread */
1208
dtuple_t* entry, /* in: index entry for index */
1209
que_thr_t* thr) /* in: query thread */
1200
1211
upd_node_t* upd_node;
1201
1212
dict_table_t* check_table;
1202
1213
dict_index_t* check_index;
1203
1214
ulint n_fields_cmp;
1204
1215
btr_pcur_t pcur;
1240
1252
if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
1241
upd_node = static_cast<upd_node_t *>(thr->run_node);
1253
upd_node = thr->run_node;
1243
1255
if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
1244
1256
/* If a cascaded update is done as defined by a
1333
1345
/* Scan index records and check if there is a matching record */
1336
1348
const rec_t* rec = btr_pcur_get_rec(&pcur);
1337
1349
const buf_block_t* block = btr_pcur_get_block(&pcur);
1339
1351
if (page_rec_is_infimum(rec)) {
1344
1356
offsets = rec_get_offsets(rec, check_index,
1349
1361
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
1350
1362
rec, check_index,
1353
case DB_SUCCESS_LOCKED_REC:
1364
if (err != DB_SUCCESS) {
1361
1372
cmp = cmp_dtuple_rec(entry, rec, offsets);
1366
1377
err = row_ins_set_shared_rec_lock(
1367
1378
LOCK_ORDINARY, block,
1368
1379
rec, check_index, offsets, thr);
1370
case DB_SUCCESS_LOCKED_REC:
1380
if (err != DB_SUCCESS) {
1377
1385
/* Found a matching record. Lock only
1382
1390
LOCK_REC_NOT_GAP, block,
1383
1391
rec, check_index, offsets, thr);
1386
case DB_SUCCESS_LOCKED_REC:
1393
if (err != DB_SUCCESS) {
1393
1398
if (check_ref) {
1394
1399
err = DB_SUCCESS;
1397
1402
} else if (foreign->type != 0) {
1398
1403
/* There is an ON UPDATE or ON DELETE
1399
1404
condition: check them in a separate
1432
1437
thr, foreign, rec, entry);
1434
1439
err = DB_ROW_IS_REFERENCED;
1441
1446
err = row_ins_set_shared_rec_lock(
1442
1447
LOCK_GAP, block,
1443
1448
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;
1449
if (err != DB_SUCCESS) {
1455
err = DB_NO_REFERENCED_ROW;
1456
row_ins_foreign_report_add_err(
1457
trx, foreign, rec, entry);
1467
moved = btr_pcur_move_to_next(&pcur, &mtr);
1471
rec = btr_pcur_get_rec(&pcur);
1472
row_ins_foreign_report_add_err(
1473
trx, foreign, rec, entry);
1474
err = DB_NO_REFERENCED_ROW;
1470
1483
btr_pcur_close(&pcur);
1472
1485
mtr_commit(&mtr);
1500
/***************************************************************//**
1513
/*******************************************************************
1501
1514
Checks if foreign key constraints fail for an index entry. If index
1502
1515
is not mentioned in any constraint, this function does nothing,
1503
1516
Otherwise does searches to the indexes of referenced tables and
1504
1517
sets shared locks which lock either the success or the failure of
1506
@return DB_SUCCESS or error code */
1509
1521
row_ins_check_foreign_constraints(
1510
1522
/*==============================*/
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 */
1523
/* out: DB_SUCCESS or error code */
1524
dict_table_t* table, /* in: table */
1525
dict_index_t* index, /* in: index */
1526
dtuple_t* entry, /* in: index entry for index */
1527
que_thr_t* thr) /* in: query thread */
1516
1529
dict_foreign_t* foreign;
1579
1592
return(DB_SUCCESS);
1582
/***************************************************************//**
1595
#ifndef UNIV_HOTBACKUP
1596
/*******************************************************************
1583
1597
Checks if a unique key violation to rec would occur at the index entry
1585
@return TRUE if error */
1588
1601
row_ins_dupl_error_with_rec(
1589
1602
/*========================*/
1590
const rec_t* rec, /*!< in: user record; NOTE that we assume
1603
/* out: TRUE if error */
1604
const rec_t* rec, /* in: user record; NOTE that we assume
1591
1605
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) */
1607
const dtuple_t* entry, /* in: entry to insert */
1608
dict_index_t* index, /* in: index */
1609
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
1597
1611
ulint matched_fields;
1598
1612
ulint matched_bytes;
1631
1645
return(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
1647
#endif /* !UNIV_HOTBACKUP */
1634
/***************************************************************//**
1649
/*******************************************************************
1635
1650
Scans a unique non-clustered index at a given index entry to determine
1636
1651
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 */
1652
Set shared locks on possible duplicate records. */
1641
1655
row_ins_scan_sec_index_for_duplicate(
1642
1656
/*=================================*/
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 */
1657
/* out: DB_SUCCESS, DB_DUPLICATE_KEY, or
1659
dict_index_t* index, /* in: non-clustered unique index */
1660
dtuple_t* entry, /* in: index entry */
1661
que_thr_t* thr) /* in: query thread */
1663
#ifndef UNIV_HOTBACKUP
1647
1664
ulint n_unique;
1755
1770
dtuple_set_n_fields_cmp(entry, n_fields_cmp);
1773
#else /* UNIV_HOTBACKUP */
1774
/* This function depends on MySQL code that is not included in
1775
InnoDB Hot Backup builds. Besides, this function should never
1776
be called in InnoDB Hot Backup. */
1779
#endif /* UNIV_HOTBACKUP */
1760
/***************************************************************//**
1782
/*******************************************************************
1761
1783
Checks if a unique key violation error would occur at an index entry
1762
1784
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
1785
for a clustered index! */
1769
1788
row_ins_duplicate_error_in_clust(
1770
1789
/*=============================*/
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 */
1790
/* out: DB_SUCCESS if no error,
1791
DB_DUPLICATE_KEY if error, DB_LOCK_WAIT if we
1792
have to wait for a lock on a possible
1794
btr_cur_t* cursor, /* in: B-tree cursor */
1795
dtuple_t* entry, /* in: entry to insert */
1796
que_thr_t* thr, /* in: query thread */
1797
mtr_t* mtr) /* in: mtr */
1799
#ifndef UNIV_HOTBACKUP
1778
1802
ulint n_unique;
1904
1920
mem_heap_free(heap);
1923
#else /* UNIV_HOTBACKUP */
1924
/* This function depends on MySQL code that is not included in
1925
InnoDB Hot Backup builds. Besides, this function should never
1926
be called in InnoDB Hot Backup. */
1929
#endif /* UNIV_HOTBACKUP */
1909
/***************************************************************//**
1932
/*******************************************************************
1910
1933
Checks if an index entry has long enough common prefix with an existing
1911
1934
record so that the intended insert of the entry must be changed to a modify of
1912
1935
the existing record. In the case of a clustered index, the prefix must be
1913
1936
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
1940
row_ins_must_modify(
1921
1941
/*================*/
1922
btr_cur_t* cursor) /*!< in: B-tree cursor */
1942
/* out: 0 if no update, ROW_INS_PREV if
1943
previous should be updated; currently we
1944
do the search so that only the low_match
1945
record can match enough to the search tuple,
1946
not the next record */
1947
btr_cur_t* cursor) /* in: B-tree cursor */
1924
1949
ulint enough_match;
1949
/***************************************************************//**
1974
/*******************************************************************
1950
1975
Tries to insert an index entry to an index. If the index is clustered
1951
1976
and a record with the same unique key is found, the other record is
1952
1977
necessarily marked deleted by a committed transaction, or a unique key
1954
1979
existing record, and we must write an undo log record on the delete
1955
1980
marked record. If the index is secondary, and a record with exactly the
1956
1981
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,
1982
It is then unmarked. Otherwise, the entry is just inserted to the index. */
1962
1985
row_ins_index_entry_low(
1963
1986
/*====================*/
1964
ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
1987
/* out: DB_SUCCESS, DB_LOCK_WAIT, DB_FAIL
1988
if pessimistic retry needed, or error code */
1989
ulint mode, /* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
1965
1990
depending on whether we wish optimistic or
1966
1991
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 */
1992
dict_index_t* index, /* in: index */
1993
dtuple_t* entry, /* in: index entry to insert */
1994
ulint n_ext, /* in: number of externally stored columns */
1995
que_thr_t* thr) /* in: query thread */
1972
1997
btr_cur_t cursor;
1998
ulint ignore_sec_unique = 0;
1974
1999
ulint modify = 0; /* remove warning */
1975
2000
rec_t* insert_rec;
1990
2015
the function will return in both low_match and up_match of the
1991
2016
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;
2018
if (!(thr_get_trx(thr)->check_unique_secondary)) {
2019
ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
2001
2022
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2003
&cursor, 0, __FILE__, __LINE__, &mtr);
2023
mode | BTR_INSERT | ignore_sec_unique,
2005
2026
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
2006
2027
/* The insertion was made to the insert buffer already during
2007
2028
the search: we are done */
2009
ut_ad(search_mode & BTR_INSERT);
2010
2030
err = DB_SUCCESS;
2012
2032
goto function_exit;
2110
2129
mtr_commit(&mtr);
2112
2131
if (UNIV_LIKELY_NULL(big_rec)) {
2114
2133
ulint* offsets;
2115
2134
mtr_start(&mtr);
2117
2136
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,
2137
BTR_MODIFY_TREE, &cursor, 0, &mtr);
2138
rec = btr_cur_get_rec(&cursor);
2139
offsets = rec_get_offsets(rec, index, NULL,
2122
2140
ULINT_UNDEFINED, &heap);
2124
2142
err = btr_store_big_rec_extern_fields(
2125
2143
index, btr_cur_get_block(&cursor),
2126
exit_rec, offsets, big_rec, &mtr);
2144
rec, offsets, big_rec, &mtr);
2129
2147
dtuple_big_rec_free(big_rec);
2143
/***************************************************************//**
2161
/*******************************************************************
2144
2162
Inserts an index entry to index. Tries first optimistic, then pessimistic
2145
2163
descent down the tree. If the entry matches enough to a delete marked record,
2146
2164
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
2168
row_ins_index_entry(
2152
2169
/*================*/
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 */
2170
/* out: DB_SUCCESS, DB_LOCK_WAIT,
2171
DB_DUPLICATE_KEY, or some other error code */
2172
dict_index_t* index, /* in: index */
2173
dtuple_t* entry, /* in: index entry to insert */
2174
ulint n_ext, /* in: number of externally stored columns */
2175
ibool foreign,/* in: TRUE=check foreign key constraints */
2176
que_thr_t* thr) /* in: query thread */
2162
2180
if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2163
err = static_cast<db_err>(row_ins_check_foreign_constraints(index->table, index,
2181
err = row_ins_check_foreign_constraints(index->table, index,
2165
2183
if (err != DB_SUCCESS) {
2171
2189
/* Try first optimistic descent to the B-tree */
2173
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2191
err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
2175
2193
if (err != DB_FAIL) {
2180
2198
/* Try then pessimistic descent to the B-tree */
2182
err = static_cast<db_err>(row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2200
err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
2187
/***********************************************************//**
2205
/***************************************************************
2188
2206
Sets the values of the dtuple fields in entry from the values of appropriate
2189
2207
columns in row. */
2192
2210
row_ins_index_entry_set_vals(
2193
2211
/*=========================*/
2194
dict_index_t* index, /*!< in: index */
2195
dtuple_t* entry, /*!< in: index entry to make */
2196
const dtuple_t* row) /*!< in: row */
2212
dict_index_t* index, /* in: index */
2213
dtuple_t* entry, /* in: index entry to make */
2214
const dtuple_t* row) /* in: row */
2198
2216
ulint n_fields;
2221
2239
= dict_field_get_col(ind_field);
2223
2241
len = dtype_get_at_most_n_mbchars(
2224
col->prtype, col->mbminmaxlen,
2242
col->prtype, col->mbminlen, col->mbmaxlen,
2225
2243
ind_field->prefix_len,
2226
len, static_cast<const char *>(dfield_get_data(row_field)));
2244
len, dfield_get_data(row_field));
2228
2246
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 */
2257
/***************************************************************
2258
Inserts a single index entry to the table. */
2245
2261
row_ins_index_entry_step(
2246
2262
/*=====================*/
2247
ins_node_t* node, /*!< in: row insert node */
2248
que_thr_t* thr) /*!< in: query thread */
2263
/* out: DB_SUCCESS if operation successfully
2264
completed, else error code or DB_LOCK_WAIT */
2265
ins_node_t* node, /* in: row insert node */
2266
que_thr_t* thr) /* in: query thread */
2252
2270
ut_ad(dtuple_check_typed(node->row));
2256
2274
ut_ad(dtuple_check_typed(node->entry));
2258
err = static_cast<db_err>(row_ins_index_entry(node->index, node->entry, 0, TRUE, thr));
2276
err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
2263
/***********************************************************//**
2281
/***************************************************************
2264
2282
Allocates a row id for row and inits the node->index field. */
2267
2285
row_ins_alloc_row_id_step(
2268
2286
/*======================*/
2269
ins_node_t* node) /*!< in: row insert node */
2287
ins_node_t* node) /* in: row insert node */
2273
2291
ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
2286
2304
dict_sys_write_row_id(node->row_id_buf, row_id);
2289
/***********************************************************//**
2307
/***************************************************************
2290
2308
Gets a row to insert from the values list. */
2293
2311
row_ins_get_row_from_values(
2294
2312
/*========================*/
2295
ins_node_t* node) /*!< in: row insert node */
2313
ins_node_t* node) /* in: row insert node */
2297
2315
que_node_t* list_node;
2298
2316
dfield_t* dfield;
2322
/***********************************************************//**
2340
/***************************************************************
2323
2341
Gets a row to insert from the select list. */
2326
2344
row_ins_get_row_from_select(
2327
2345
/*========================*/
2328
ins_node_t* node) /*!< in: row insert node */
2346
ins_node_t* node) /* in: row insert node */
2330
2348
que_node_t* list_node;
2331
2349
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 */
2371
/***************************************************************
2372
Inserts a row to a table. */
2361
ins_node_t* node, /*!< in: row insert node */
2362
que_thr_t* thr) /*!< in: query thread */
2377
/* out: DB_SUCCESS if operation successfully
2378
completed, else error code or DB_LOCK_WAIT */
2379
ins_node_t* node, /* in: row insert node */
2380
que_thr_t* thr) /* in: query thread */
2405
2423
return(DB_SUCCESS);
2408
/***********************************************************//**
2426
/***************************************************************
2409
2427
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 */
2433
/* out: query thread to run next or NULL */
2434
que_thr_t* thr) /* in: query thread */
2418
2436
ins_node_t* node;
2419
2437
que_node_t* parent;
2455
2473
/* It may be that the current session has not yet started
2456
2474
its transaction, or it has been committed: */
2458
if (trx->id == node->trx_id) {
2476
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
2459
2477
/* No need to do IX-locking */