~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/row/row0ins.c

  • Committer: Andrew Hutchings
  • Date: 2010-11-09 13:38:01 UTC
  • mto: (1919.1.2 trunk)
  • mto: This revision was merged to the branch mainline in revision 1920.
  • Revision ID: andrew@linuxjedi.co.uk-20101109133801-byjzsao76346395x
Add FLUSH GLOBAL STATUS; command
Clears the global status variables for the server

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
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
53
53
 
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
60
 
check.
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. */
63
54
 
64
55
/*********************************************************************//**
65
56
Creates an insert node struct.
87
78
 
88
79
        node->select = NULL;
89
80
 
90
 
        node->trx_id = 0;
 
81
        node->trx_id = ut_dulint_zero;
91
82
 
92
83
        node->entry_sys_heap = mem_heap_create(128);
93
84
 
207
198
        /* As we allocated a new trx id buf, the trx id should be written
208
199
        there again: */
209
200
 
210
 
        node->trx_id = 0;
 
201
        node->trx_id = ut_dulint_zero;
211
202
}
212
203
 
213
204
/*******************************************************************//**
515
506
 
516
507
                                if (!dfield_is_null(&ufield->new_val)
517
508
                                    && dtype_get_at_most_n_mbchars(
518
 
                                        col->prtype, col->mbminmaxlen,
 
509
                                        col->prtype,
 
510
                                        col->mbminlen, col->mbmaxlen,
519
511
                                        col->len,
520
512
                                        ufield_len,
521
513
                                        dfield_get_data(&ufield->new_val))
538
530
 
539
531
                                if (min_size > ufield_len) {
540
532
 
541
 
                                        byte*   pad;
542
 
                                        ulint   pad_len;
543
 
                                        byte*   padded_data;
544
 
                                        ulint   mbminlen;
545
 
 
546
 
                                        padded_data = mem_heap_alloc(
547
 
                                                heap, min_size);
548
 
 
549
 
                                        pad = padded_data + ufield_len;
550
 
                                        pad_len = min_size - ufield_len;
 
533
                                        char*           pad_start;
 
534
                                        const char*     pad_end;
 
535
                                        char*           padded_data
 
536
                                                = mem_heap_alloc(
 
537
                                                        heap, min_size);
 
538
                                        pad_start = padded_data + ufield_len;
 
539
                                        pad_end = padded_data + min_size;
551
540
 
552
541
                                        memcpy(padded_data,
553
542
                                               dfield_get_data(&ufield
554
543
                                                               ->new_val),
555
 
                                               ufield_len);
556
 
 
557
 
                                        mbminlen = dict_col_get_mbminlen(col);
558
 
 
559
 
                                        ut_ad(!(ufield_len % mbminlen));
560
 
                                        ut_ad(!(min_size % mbminlen));
561
 
 
562
 
                                        if (mbminlen == 1
563
 
                                            && dtype_get_charset_coll(
564
 
                                                    col->prtype)
565
 
                                            == DATA_MYSQL_BINARY_CHARSET_COLL) {
566
 
                                                /* Do not pad BINARY columns */
 
544
                                               dfield_get_len(&ufield
 
545
                                                              ->new_val));
 
546
 
 
547
                                        switch (UNIV_EXPECT(col->mbminlen,1)) {
 
548
                                        default:
 
549
                                                ut_error;
567
550
                                                return(ULINT_UNDEFINED);
 
551
                                        case 1:
 
552
                                                if (UNIV_UNLIKELY
 
553
                                                    (dtype_get_charset_coll(
 
554
                                                            col->prtype)
 
555
                                                     == DATA_MYSQL_BINARY_CHARSET_COLL)) {
 
556
                                                        /* Do not pad BINARY
 
557
                                                        columns. */
 
558
                                                        return(ULINT_UNDEFINED);
 
559
                                                }
 
560
 
 
561
                                                /* space=0x20 */
 
562
                                                memset(pad_start, 0x20,
 
563
                                                       pad_end - pad_start);
 
564
                                                break;
 
565
                                        case 2:
 
566
                                                /* space=0x0020 */
 
567
                                                ut_a(!(ufield_len % 2));
 
568
                                                ut_a(!(min_size % 2));
 
569
                                                do {
 
570
                                                        *pad_start++ = 0x00;
 
571
                                                        *pad_start++ = 0x20;
 
572
                                                } while (pad_start < pad_end);
 
573
                                                break;
568
574
                                        }
569
575
 
570
 
                                        row_mysql_pad_col(mbminlen,
571
 
                                                          pad, pad_len);
572
576
                                        dfield_set_data(&ufield->new_val,
573
577
                                                        padded_data, min_size);
574
578
                                }
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 */
1122
1126
static
1123
 
enum db_err
 
1127
ulint
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 */
1133
1137
{
1134
 
        enum db_err     err;
 
1138
        ulint   err;
1135
1139
 
1136
1140
        ut_ad(rec_offs_validate(rec, index, offsets));
1137
1141
 
1149
1153
/*********************************************************************//**
1150
1154
Sets a exclusive lock on a record. Used in locking possible duplicate key
1151
1155
records
1152
 
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
 
1156
@return DB_SUCCESS or error code */
1153
1157
static
1154
 
enum db_err
 
1158
ulint
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 */
1164
1168
{
1165
 
        enum db_err     err;
 
1169
        ulint   err;
1166
1170
 
1167
1171
        ut_ad(rec_offs_validate(rec, index, offsets));
1168
1172
 
1202
1206
        dict_index_t*   check_index;
1203
1207
        ulint           n_fields_cmp;
1204
1208
        btr_pcur_t      pcur;
 
1209
        ibool           moved;
1205
1210
        int             cmp;
1206
1211
        ulint           err;
1207
1212
        ulint           i;
1332
1337
 
1333
1338
        /* Scan index records and check if there is a matching record */
1334
1339
 
1335
 
        do {
 
1340
        for (;;) {
1336
1341
                const rec_t*            rec = btr_pcur_get_rec(&pcur);
1337
1342
                const buf_block_t*      block = btr_pcur_get_block(&pcur);
1338
1343
 
1339
1344
                if (page_rec_is_infimum(rec)) {
1340
1345
 
1341
 
                        continue;
 
1346
                        goto next_rec;
1342
1347
                }
1343
1348
 
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,
1351
1356
                                                          offsets, thr);
1352
 
                        switch (err) {
1353
 
                        case DB_SUCCESS_LOCKED_REC:
1354
 
                        case DB_SUCCESS:
1355
 
                                continue;
1356
 
                        default:
1357
 
                                goto end_scan;
 
1357
                        if (err != DB_SUCCESS) {
 
1358
 
 
1359
                                break;
1358
1360
                        }
 
1361
 
 
1362
                        goto next_rec;
1359
1363
                }
1360
1364
 
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);
1369
 
                                switch (err) {
1370
 
                                case DB_SUCCESS_LOCKED_REC:
1371
 
                                case DB_SUCCESS:
 
1373
                                if (err != DB_SUCCESS) {
 
1374
 
1372
1375
                                        break;
1373
 
                                default:
1374
 
                                        goto end_scan;
1375
1376
                                }
1376
1377
                        } else {
1377
1378
                                /* Found a matching record. Lock only
1382
1383
                                        LOCK_REC_NOT_GAP, block,
1383
1384
                                        rec, check_index, offsets, thr);
1384
1385
 
1385
 
                                switch (err) {
1386
 
                                case DB_SUCCESS_LOCKED_REC:
1387
 
                                case DB_SUCCESS:
 
1386
                                if (err != DB_SUCCESS) {
 
1387
 
1388
1388
                                        break;
1389
 
                                default:
1390
 
                                        goto end_scan;
1391
1389
                                }
1392
1390
 
1393
1391
                                if (check_ref) {
1394
1392
                                        err = DB_SUCCESS;
1395
1393
 
1396
 
                                        goto end_scan;
 
1394
                                        break;
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
1419
1417
                                                        err = DB_FOREIGN_DUPLICATE_KEY;
1420
1418
                                                }
1421
1419
 
1422
 
                                                goto end_scan;
 
1420
                                                break;
1423
1421
                                        }
1424
1422
 
1425
1423
                                        /* row_ins_foreign_check_on_constraint
1432
1430
                                                thr, foreign, rec, entry);
1433
1431
 
1434
1432
                                        err = DB_ROW_IS_REFERENCED;
1435
 
                                        goto end_scan;
 
1433
                                        break;
1436
1434
                                }
1437
1435
                        }
1438
 
                } else {
1439
 
                        ut_a(cmp < 0);
 
1436
                }
1440
1437
 
 
1438
                if (cmp < 0) {
1441
1439
                        err = row_ins_set_shared_rec_lock(
1442
1440
                                LOCK_GAP, block,
1443
1441
                                rec, check_index, offsets, thr);
1444
 
 
1445
 
                        switch (err) {
1446
 
                        case DB_SUCCESS_LOCKED_REC:
1447
 
                        case DB_SUCCESS:
1448
 
                                if (check_ref) {
1449
 
                                        err = DB_NO_REFERENCED_ROW;
1450
 
                                        row_ins_foreign_report_add_err(
1451
 
                                                trx, foreign, rec, entry);
1452
 
                                } else {
1453
 
                                        err = DB_SUCCESS;
1454
 
                                }
1455
 
                        }
1456
 
 
1457
 
                        goto end_scan;
1458
 
                }
1459
 
        } while (btr_pcur_move_to_next(&pcur, &mtr));
1460
 
 
1461
 
        if (check_ref) {
1462
 
                row_ins_foreign_report_add_err(
1463
 
                        trx, foreign, btr_pcur_get_rec(&pcur), entry);
1464
 
                err = DB_NO_REFERENCED_ROW;
1465
 
        } else {
1466
 
                err = DB_SUCCESS;
 
1442
                        if (err != DB_SUCCESS) {
 
1443
 
 
1444
                                break;
 
1445
                        }
 
1446
 
 
1447
                        if (check_ref) {
 
1448
                                err = DB_NO_REFERENCED_ROW;
 
1449
                                row_ins_foreign_report_add_err(
 
1450
                                        trx, foreign, rec, entry);
 
1451
                        } else {
 
1452
                                err = DB_SUCCESS;
 
1453
                        }
 
1454
 
 
1455
                        break;
 
1456
                }
 
1457
 
 
1458
                ut_a(cmp == 0);
 
1459
next_rec:
 
1460
                moved = btr_pcur_move_to_next(&pcur, &mtr);
 
1461
 
 
1462
                if (!moved) {
 
1463
                        if (check_ref) {
 
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;
 
1468
                        } else {
 
1469
                                err = DB_SUCCESS;
 
1470
                        }
 
1471
 
 
1472
                        break;
 
1473
                }
1467
1474
        }
1468
1475
 
1469
 
end_scan:
1470
1476
        btr_pcur_close(&pcur);
1471
1477
 
1472
1478
        mtr_commit(&mtr);
1714
1720
                                rec, index, offsets, thr);
1715
1721
                }
1716
1722
 
1717
 
                switch (err) {
1718
 
                case DB_SUCCESS_LOCKED_REC:
1719
 
                        err = DB_SUCCESS;
1720
 
                case DB_SUCCESS:
 
1723
                if (err != DB_SUCCESS) {
 
1724
 
1721
1725
                        break;
1722
 
                default:
1723
 
                        goto end_scan;
1724
1726
                }
1725
1727
 
1726
1728
                if (page_rec_is_supremum(rec)) {
1737
1739
 
1738
1740
                                thr_get_trx(thr)->error_info = index;
1739
1741
 
1740
 
                                goto end_scan;
 
1742
                                break;
1741
1743
                        }
1742
 
                } else {
1743
 
                        ut_a(cmp < 0);
1744
 
                        goto end_scan;
1745
 
                }
 
1744
                }
 
1745
 
 
1746
                if (cmp < 0) {
 
1747
                        break;
 
1748
                }
 
1749
 
 
1750
                ut_a(cmp == 0);
1746
1751
        } while (btr_pcur_move_to_next(&pcur, &mtr));
1747
1752
 
1748
 
end_scan:
1749
1753
        if (UNIV_LIKELY_NULL(heap)) {
1750
1754
                mem_heap_free(heap);
1751
1755
        }
1834
1838
                                        cursor->index, offsets, thr);
1835
1839
                        }
1836
1840
 
1837
 
                        switch (err) {
1838
 
                        case DB_SUCCESS_LOCKED_REC:
1839
 
                        case DB_SUCCESS:
1840
 
                                break;
1841
 
                        default:
 
1841
                        if (err != DB_SUCCESS) {
1842
1842
                                goto func_exit;
1843
1843
                        }
1844
1844
 
1878
1878
                                        rec, cursor->index, offsets, thr);
1879
1879
                        }
1880
1880
 
1881
 
                        switch (err) {
1882
 
                        case DB_SUCCESS_LOCKED_REC:
1883
 
                        case DB_SUCCESS:
1884
 
                                break;
1885
 
                        default:
 
1881
                        if (err != DB_SUCCESS) {
1886
1882
                                goto func_exit;
1887
1883
                        }
1888
1884
 
1970
1966
        que_thr_t*      thr)    /*!< in: query thread */
1971
1967
{
1972
1968
        btr_cur_t       cursor;
1973
 
        ulint           search_mode;
 
1969
        ulint           ignore_sec_unique       = 0;
1974
1970
        ulint           modify = 0; /* remove warning */
1975
1971
        rec_t*          insert_rec;
1976
1972
        rec_t*          rec;
1990
1986
        the function will return in both low_match and up_match of the
1991
1987
        cursor sensible values */
1992
1988
 
1993
 
        if (dict_index_is_clust(index)) {
1994
 
                search_mode = mode;
1995
 
        } else if (!(thr_get_trx(thr)->check_unique_secondary)) {
1996
 
                search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
1997
 
        } else {
1998
 
                search_mode = mode | BTR_INSERT;
 
1989
        if (!(thr_get_trx(thr)->check_unique_secondary)) {
 
1990
                ignore_sec_unique = BTR_IGNORE_SEC_UNIQUE;
1999
1991
        }
2000
1992
 
2001
1993
        btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
2002
 
                                    search_mode,
2003
 
                                    &cursor, 0, __FILE__, __LINE__, &mtr);
 
1994
                                    mode | BTR_INSERT | ignore_sec_unique,
 
1995
                                    &cursor, 0, &mtr);
2004
1996
 
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 */
2008
2000
 
2009
 
                ut_ad(search_mode & BTR_INSERT);
2010
2001
                err = DB_SUCCESS;
2011
2002
 
2012
2003
                goto function_exit;
2059
2050
                        btr_cur_search_to_nth_level(index, 0, entry,
2060
2051
                                                    PAGE_CUR_LE,
2061
2052
                                                    mode | BTR_INSERT,
2062
 
                                                    &cursor, 0,
2063
 
                                                    __FILE__, __LINE__, &mtr);
 
2053
                                                    &cursor, 0, &mtr);
2064
2054
                }
2065
2055
        }
2066
2056
 
2115
2105
                mtr_start(&mtr);
2116
2106
 
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 */
2158
2147
{
2159
 
        enum db_err     err;
 
2148
        ulint   err;
2160
2149
 
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);
2221
2210
 
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));
2226
2215
 
2246
2235
        ins_node_t*     node,   /*!< in: row insert node */
2247
2236
        que_thr_t*      thr)    /*!< in: query thread */
2248
2237
{
2249
 
        enum db_err     err;
 
2238
        ulint   err;
2250
2239
 
2251
2240
        ut_ad(dtuple_check_typed(node->row));
2252
2241
 
2267
2256
/*======================*/
2268
2257
        ins_node_t*     node)   /*!< in: row insert node */
2269
2258
{
2270
 
        row_id_t        row_id;
 
2259
        dulint  row_id;
2271
2260
 
2272
2261
        ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
2273
2262
 
2454
2443
                /* It may be that the current session has not yet started
2455
2444
                its transaction, or it has been committed: */
2456
2445
 
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 */
2459
2448
 
2460
2449
                        goto same_trx;