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