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
51
51
#define ROW_INS_PREV 1
52
52
#define ROW_INS_NEXT 2
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
55
/*********************************************************************//**
65
56
Creates an insert node struct.
516
507
if (!dfield_is_null(&ufield->new_val)
517
508
&& dtype_get_at_most_n_mbchars(
518
col->prtype, col->mbminmaxlen,
510
col->mbminlen, col->mbmaxlen,
521
513
dfield_get_data(&ufield->new_val))
539
531
if (min_size > ufield_len) {
546
padded_data = mem_heap_alloc(
549
pad = padded_data + ufield_len;
550
pad_len = min_size - ufield_len;
538
pad_start = padded_data + ufield_len;
539
pad_end = padded_data + min_size;
552
541
memcpy(padded_data,
553
542
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 */
544
dfield_get_len(&ufield
547
switch (UNIV_EXPECT(col->mbminlen,1)) {
567
550
return(ULINT_UNDEFINED);
553
(dtype_get_charset_coll(
555
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
558
return(ULINT_UNDEFINED);
562
memset(pad_start, 0x20,
563
pad_end - pad_start);
567
ut_a(!(ufield_len % 2));
568
ut_a(!(min_size % 2));
572
} while (pad_start < pad_end);
570
row_mysql_pad_col(mbminlen,
572
576
dfield_set_data(&ufield->new_val,
573
577
padded_data, min_size);
1118
1122
/*********************************************************************//**
1119
1123
Sets a shared lock on a record. Used in locking possible duplicate key
1120
1124
records and also in checking foreign key constraints.
1121
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1125
@return DB_SUCCESS or error code */
1124
1128
row_ins_set_shared_rec_lock(
1125
1129
/*========================*/
1126
1130
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1131
1135
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1132
1136
que_thr_t* thr) /*!< in: query thread */
1136
1140
ut_ad(rec_offs_validate(rec, index, offsets));
1149
1153
/*********************************************************************//**
1150
1154
Sets a exclusive lock on a record. Used in locking possible duplicate key
1152
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
1156
@return DB_SUCCESS or error code */
1155
1159
row_ins_set_exclusive_rec_lock(
1156
1160
/*===========================*/
1157
1161
ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or
1162
1166
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
1163
1167
que_thr_t* thr) /*!< in: query thread */
1167
1171
ut_ad(rec_offs_validate(rec, index, offsets));
1333
1338
/* Scan index records and check if there is a matching record */
1336
1341
const rec_t* rec = btr_pcur_get_rec(&pcur);
1337
1342
const buf_block_t* block = btr_pcur_get_block(&pcur);
1339
1344
if (page_rec_is_infimum(rec)) {
1344
1349
offsets = rec_get_offsets(rec, check_index,
1349
1354
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block,
1350
1355
rec, check_index,
1353
case DB_SUCCESS_LOCKED_REC:
1357
if (err != DB_SUCCESS) {
1361
1365
cmp = cmp_dtuple_rec(entry, rec, offsets);
1366
1370
err = row_ins_set_shared_rec_lock(
1367
1371
LOCK_ORDINARY, block,
1368
1372
rec, check_index, offsets, thr);
1370
case DB_SUCCESS_LOCKED_REC:
1373
if (err != DB_SUCCESS) {
1377
1378
/* Found a matching record. Lock only
1382
1383
LOCK_REC_NOT_GAP, block,
1383
1384
rec, check_index, offsets, thr);
1386
case DB_SUCCESS_LOCKED_REC:
1386
if (err != DB_SUCCESS) {
1393
1391
if (check_ref) {
1394
1392
err = DB_SUCCESS;
1397
1395
} else if (foreign->type != 0) {
1398
1396
/* There is an ON UPDATE or ON DELETE
1399
1397
condition: check them in a separate
1432
1430
thr, foreign, rec, entry);
1434
1432
err = DB_ROW_IS_REFERENCED;
1441
1439
err = row_ins_set_shared_rec_lock(
1442
1440
LOCK_GAP, block,
1443
1441
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;
1442
if (err != DB_SUCCESS) {
1448
err = DB_NO_REFERENCED_ROW;
1449
row_ins_foreign_report_add_err(
1450
trx, foreign, rec, entry);
1460
moved = btr_pcur_move_to_next(&pcur, &mtr);
1464
rec = btr_pcur_get_rec(&pcur);
1465
row_ins_foreign_report_add_err(
1466
trx, foreign, rec, entry);
1467
err = DB_NO_REFERENCED_ROW;
1470
1476
btr_pcur_close(&pcur);
1472
1478
mtr_commit(&mtr);
1990
1986
the function will return in both low_match and up_match of the
1991
1987
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;
1989
if (!(thr_get_trx(thr)->check_unique_secondary)) {
1990
ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
2001
1993
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2003
&cursor, 0, __FILE__, __LINE__, &mtr);
1994
mode | BTR_INSERT | ignore_sec_unique,
2005
1997
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
2006
1998
/* The insertion was made to the insert buffer already during
2007
1999
the search: we are done */
2009
ut_ad(search_mode & BTR_INSERT);
2010
2001
err = DB_SUCCESS;
2012
2003
goto function_exit;
2115
2105
mtr_start(&mtr);
2117
2107
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2118
BTR_MODIFY_TREE, &cursor, 0,
2119
__FILE__, __LINE__, &mtr);
2108
BTR_MODIFY_TREE, &cursor, 0, &mtr);
2120
2109
rec = btr_cur_get_rec(&cursor);
2121
2110
offsets = rec_get_offsets(rec, index, NULL,
2122
2111
ULINT_UNDEFINED, &heap);
2156
2145
ibool foreign,/*!< in: TRUE=check foreign key constraints */
2157
2146
que_thr_t* thr) /*!< in: query thread */
2161
2150
if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
2162
2151
err = row_ins_check_foreign_constraints(index->table, index,
2220
2209
= dict_field_get_col(ind_field);
2222
2211
len = dtype_get_at_most_n_mbchars(
2223
col->prtype, col->mbminmaxlen,
2212
col->prtype, col->mbminlen, col->mbmaxlen,
2224
2213
ind_field->prefix_len,
2225
2214
len, dfield_get_data(row_field));
2454
2443
/* It may be that the current session has not yet started
2455
2444
its transaction, or it has been committed: */
2457
if (trx->id == node->trx_id) {
2446
if (UT_DULINT_EQ(trx->id, node->trx_id)) {
2458
2447
/* No need to do IX-locking */