~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

New merge for TableShare

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2000, 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
11
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
12
 
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
16
16
 
17
17
*****************************************************************************/
18
18
 
52
52
#include "fil0fil.h"
53
53
#include "ibuf0ibuf.h"
54
54
 
55
 
#include <errno.h>
56
 
 
57
55
/** Provide optional 4.x backwards compatibility for 5.0 and above */
58
56
UNIV_INTERN ibool       row_rollback_on_timeout = FALSE;
59
57
 
95
93
        ((str1_len) == sizeof(str2_onstack) \
96
94
         && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
97
95
 
 
96
/*******************************************************************//**
 
97
Determine if the given name is a name reserved for MySQL system tables.
 
98
@return TRUE if name is a MySQL system table name */
 
99
static
 
100
ibool
 
101
row_mysql_is_system_table(
 
102
/*======================*/
 
103
        const char*     name)
 
104
{
 
105
        if (strncmp(name, "mysql/", 6) != 0) {
 
106
 
 
107
                return(FALSE);
 
108
        }
 
109
 
 
110
        return(0 == strcmp(name + 6, "host")
 
111
               || 0 == strcmp(name + 6, "user")
 
112
               || 0 == strcmp(name + 6, "db"));
 
113
}
 
114
 
98
115
/*********************************************************************//**
99
116
If a table is not yet in the drop list, adds the table to the list of tables
100
117
which the master thread drops in background. We need this on Unix because in
249
266
}
250
267
 
251
268
/**************************************************************//**
252
 
Pad a column with spaces. */
253
 
UNIV_INTERN
254
 
void
255
 
row_mysql_pad_col(
256
 
/*==============*/
257
 
        ulint   mbminlen,       /*!< in: minimum size of a character,
258
 
                                in bytes */
259
 
        byte*   pad,            /*!< out: padded buffer */
260
 
        ulint   len)            /*!< in: number of bytes to pad */
261
 
{
262
 
        const byte*     pad_end;
263
 
 
264
 
        switch (UNIV_EXPECT(mbminlen, 1)) {
265
 
        default:
266
 
                ut_error;
267
 
        case 1:
268
 
                /* space=0x20 */
269
 
                memset(pad, 0x20, len);
270
 
                break;
271
 
        case 2:
272
 
                /* space=0x0020 */
273
 
                pad_end = pad + len;
274
 
                ut_a(!(len % 2));
275
 
                do {
276
 
                        *pad++ = 0x00;
277
 
                        *pad++ = 0x20;
278
 
                } while (pad < pad_end);
279
 
                break;
280
 
        case 4:
281
 
                /* space=0x00000020 */
282
 
                pad_end = pad + len;
283
 
                ut_a(!(len % 4));
284
 
                do {
285
 
                        *pad++ = 0x00;
286
 
                        *pad++ = 0x00;
287
 
                        *pad++ = 0x00;
288
 
                        *pad++ = 0x20;
289
 
                } while (pad < pad_end);
290
 
                break;
291
 
        }
292
 
}
293
 
 
294
 
/**************************************************************//**
295
269
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
270
The counterpart of this function is row_sel_field_store_in_mysql_format() in
297
271
row0sel.c.
383
357
                        /* Remove trailing spaces from old style VARCHAR
384
358
                        columns. */
385
359
 
386
 
                        /* Handle Unicode strings differently. */
 
360
                        /* Handle UCS2 strings differently. */
387
361
                        ulint   mbminlen        = dtype_get_mbminlen(dtype);
388
362
 
389
363
                        ptr = mysql_data;
390
364
 
391
 
                        switch (mbminlen) {
392
 
                        default:
393
 
                                ut_error;
394
 
                        case 4:
395
 
                                /* space=0x00000020 */
396
 
                                /* Trim "half-chars", just in case. */
397
 
                                col_len &= ~3;
398
 
 
399
 
                                while (col_len >= 4
400
 
                                       && ptr[col_len - 4] == 0x00
401
 
                                       && ptr[col_len - 3] == 0x00
402
 
                                       && ptr[col_len - 2] == 0x00
403
 
                                       && ptr[col_len - 1] == 0x20) {
404
 
                                        col_len -= 4;
405
 
                                }
406
 
                                break;
407
 
                        case 2:
 
365
                        if (mbminlen == 2) {
408
366
                                /* space=0x0020 */
409
367
                                /* Trim "half-chars", just in case. */
410
368
                                col_len &= ~1;
413
371
                                       && ptr[col_len - 1] == 0x20) {
414
372
                                        col_len -= 2;
415
373
                                }
416
 
                                break;
417
 
                        case 1:
 
374
                        } else {
 
375
                                ut_a(mbminlen == 1);
418
376
                                /* space=0x20 */
419
377
                                while (col_len > 0
420
378
                                       && ptr[col_len - 1] == 0x20) {
527
485
/****************************************************************//**
528
486
Handles user errors and lock waits detected by the database engine.
529
487
@return TRUE if it was a lock wait and we should continue running the
530
 
query thread and in that case the thr is ALREADY in the running state. */
 
488
query thread */
531
489
UNIV_INTERN
532
490
ibool
533
491
row_mysql_handle_errors(
552
510
        switch (err) {
553
511
        case DB_LOCK_WAIT_TIMEOUT:
554
512
                if (row_rollback_on_timeout) {
555
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
513
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
556
514
                        break;
557
515
                }
558
516
                /* fall through */
564
522
        case DB_CANNOT_ADD_CONSTRAINT:
565
523
        case DB_TOO_MANY_CONCURRENT_TRXS:
566
524
        case DB_OUT_OF_FILE_SPACE:
567
 
        case DB_INTERRUPTED:
568
525
                if (savept) {
569
526
                        /* Roll back the latest, possibly incomplete
570
527
                        insertion or update */
571
528
 
572
 
                        trx_general_rollback_for_mysql(trx, savept);
 
529
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
573
530
                }
574
531
                /* MySQL will roll back the latest SQL statement */
575
532
                break;
591
548
                /* Roll back the whole transaction; this resolution was added
592
549
                to version 3.23.43 */
593
550
 
594
 
                trx_general_rollback_for_mysql(trx, NULL);
 
551
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
595
552
                break;
596
553
 
597
554
        case DB_MUST_GET_MORE_FILE_SPACE:
618
575
                      "InnoDB: " REFMAN "forcing-recovery.html"
619
576
                      " for help.\n", stderr);
620
577
                break;
621
 
        case DB_FOREIGN_EXCEED_MAX_CASCADE:
622
 
                fprintf(stderr, "InnoDB: Cannot delete/update rows with"
623
 
                        " cascading foreign key constraints that exceed max"
624
 
                        " depth of %lu\n"
625
 
                        "Please drop excessive foreign constraints"
626
 
                        " and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
627
 
                break;
628
578
        default:
629
579
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
630
580
                        (ulong) err);
674
624
 
675
625
        prebuilt->select_lock_type = LOCK_NONE;
676
626
        prebuilt->stored_select_lock_type = 99999999;
677
 
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
 
                         sizeof prebuilt->stored_select_lock_type);
679
627
 
680
628
        prebuilt->search_tuple = dtuple_create(
681
629
                heap, 2 * dict_table_get_n_cols(table));
840
788
        }
841
789
}
842
790
 
843
 
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
844
 
 
845
791
/*********************************************************************//**
846
792
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
793
has not yet been built in the prebuilt struct, then this function first
848
794
builds it.
849
795
@return prebuilt dtuple; the column type information is also set in it */
 
796
static
850
797
dtuple_t*
851
798
row_get_prebuilt_insert_row(
852
799
/*========================*/
919
866
}
920
867
 
921
868
/*********************************************************************//**
922
 
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
923
 
function should be called at the the end of an SQL statement, by the
924
 
connection thread that owns the transaction (trx->mysql_thd). */
 
869
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
925
870
UNIV_INTERN
926
871
void
927
872
row_unlock_table_autoinc_for_mysql(
928
873
/*===============================*/
929
874
        trx_t*  trx)    /*!< in/out: transaction */
930
875
{
931
 
        if (lock_trx_holds_autoinc_locks(trx)) {
932
 
                mutex_enter(&kernel_mutex);
933
 
 
934
 
                lock_release_autoinc_locks(trx);
935
 
 
936
 
                mutex_exit(&kernel_mutex);
937
 
        }
 
876
        mutex_enter(&kernel_mutex);
 
877
 
 
878
        lock_release_autoinc_locks(trx);
 
879
 
 
880
        mutex_exit(&kernel_mutex);
938
881
}
939
882
 
940
883
/*********************************************************************//**
1431
1374
run_again:
1432
1375
        thr->run_node = node;
1433
1376
        thr->prev_node = node;
1434
 
        thr->fk_cascade_depth = 0;
1435
1377
 
1436
1378
        row_upd_step(thr);
1437
1379
 
1438
 
        /* The recursive call for cascading update/delete happens
1439
 
        in above row_upd_step(), reset the counter once we come
1440
 
        out of the recursive call, so it does not accumulate for
1441
 
        different row deletes */
1442
 
        thr->fk_cascade_depth = 0;
1443
 
 
1444
1380
        err = trx->error_state;
1445
1381
 
1446
 
        /* Reset fk_cascade_depth back to 0 */
1447
 
        thr->fk_cascade_depth = 0;
1448
 
 
1449
1382
        if (err != DB_SUCCESS) {
1450
1383
                que_thr_stop_for_mysql(thr);
1451
1384
 
1482
1415
                srv_n_rows_updated++;
1483
1416
        }
1484
1417
 
1485
 
        /* We update table statistics only if it is a DELETE or UPDATE
1486
 
        that changes indexed columns, UPDATEs that change only non-indexed
1487
 
        columns would not affect statistics. */
1488
 
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1489
 
                row_update_statistics_if_needed(prebuilt->table);
1490
 
        }
 
1418
        row_update_statistics_if_needed(prebuilt->table);
1491
1419
 
1492
1420
        trx->op_info = "";
1493
1421
 
1495
1423
}
1496
1424
 
1497
1425
/*********************************************************************//**
1498
 
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1499
 
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1500
 
Before calling this function row_search_for_mysql() must have
1501
 
initialized prebuilt->new_rec_locks to store the information which new
1502
 
record locks really were set. This function removes a newly set
1503
 
clustered index record lock under prebuilt->pcur or
1504
 
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
1505
 
releases the latest clustered index record lock we set.
1506
 
@return error code or DB_SUCCESS */
 
1426
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
 
1427
this session is using a READ COMMITTED isolation level. Before
 
1428
calling this function we must use trx_reset_new_rec_lock_info() and
 
1429
trx_register_new_rec_lock() to store the information which new record locks
 
1430
really were set. This function removes a newly set lock under prebuilt->pcur,
 
1431
and also under prebuilt->clust_pcur. Currently, this is only used and tested
 
1432
in the case of an UPDATE or a DELETE statement, where the row lock is of the
 
1433
LOCK_X type.
 
1434
Thus, this implements a 'mini-rollback' that releases the latest record
 
1435
locks we set.
 
1436
@return error code or DB_SUCCESS */
1507
1437
UNIV_INTERN
1508
1438
int
1509
1439
row_unlock_for_mysql(
1510
1440
/*=================*/
1511
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1441
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1512
1442
                                        handle */
1513
 
        ibool           has_latches_on_recs)/*!< in: TRUE if called so
1514
 
                                        that we have the latches on
1515
 
                                        the records under pcur and
1516
 
                                        clust_pcur, and we do not need
1517
 
                                        to reposition the cursors. */
 
1443
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
 
1444
                                        the latches on the records under pcur
 
1445
                                        and clust_pcur, and we do not need to
 
1446
                                        reposition the cursors. */
1518
1447
{
1519
1448
        btr_pcur_t*     pcur            = prebuilt->pcur;
1520
1449
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1525
1454
 
1526
1455
        if (UNIV_UNLIKELY
1527
1456
            (!srv_locks_unsafe_for_binlog
1528
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1457
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1529
1458
 
1530
1459
                fprintf(stderr,
1531
1460
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1597
1526
                        }
1598
1527
                }
1599
1528
 
1600
 
                if (rec_trx_id != trx->id) {
 
1529
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1601
1530
                        /* We did not update the record: unlock it */
1602
1531
 
1603
1532
                        rec = btr_pcur_get_rec(pcur);
1641
1570
        trx_t*  trx;
1642
1571
 
1643
1572
        trx = thr_get_trx(thr);
1644
 
 
1645
 
        /* Increment fk_cascade_depth to record the recursive call depth on
1646
 
        a single update/delete that affects multiple tables chained
1647
 
        together with foreign key relations. */
1648
 
        thr->fk_cascade_depth++;
1649
 
 
1650
 
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1651
 
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1652
 
        }
1653
1573
run_again:
1654
1574
        thr->run_node = node;
1655
1575
        thr->prev_node = node;
1656
1576
 
1657
1577
        row_upd_step(thr);
1658
1578
 
1659
 
        /* The recursive call for cascading update/delete happens
1660
 
        in above row_upd_step(), reset the counter once we come
1661
 
        out of the recursive call, so it does not accumulate for
1662
 
        different row deletes */
1663
 
        thr->fk_cascade_depth = 0;
1664
 
 
1665
1579
        err = trx->error_state;
1666
1580
 
1667
1581
        /* Note that the cascade node is a subnode of another InnoDB
1727
1641
}
1728
1642
 
1729
1643
/*********************************************************************//**
 
1644
Calculates the key number used inside MySQL for an Innobase index. We have
 
1645
to take into account if we generated a default clustered index for the table
 
1646
@return the key number used inside MySQL */
 
1647
UNIV_INTERN
 
1648
ulint
 
1649
row_get_mysql_key_number_for_index(
 
1650
/*===============================*/
 
1651
        const dict_index_t*     index)  /*!< in: index */
 
1652
{
 
1653
        const dict_index_t*     ind;
 
1654
        ulint                   i;
 
1655
 
 
1656
        ut_a(index);
 
1657
 
 
1658
        i = 0;
 
1659
        ind = dict_table_get_first_index(index->table);
 
1660
 
 
1661
        while (index != ind) {
 
1662
                ind = dict_table_get_next_index(ind);
 
1663
                i++;
 
1664
        }
 
1665
 
 
1666
        if (row_table_got_default_clust_index(index->table)) {
 
1667
                ut_a(i > 0);
 
1668
                i--;
 
1669
        }
 
1670
 
 
1671
        return(i);
 
1672
}
 
1673
 
 
1674
/*********************************************************************//**
1730
1675
Locks the data dictionary in shared mode from modifications, for performing
1731
1676
foreign key check, rollback, or other operation invisible to MySQL. */
1732
1677
UNIV_INTERN
1822
1767
        const char*     table_name;
1823
1768
        ulint           table_name_len;
1824
1769
        ulint           err;
 
1770
        ulint           i;
1825
1771
 
1826
1772
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1827
1773
#ifdef UNIV_SYNC_DEBUG
1836
1782
                      " by the user.\n"
1837
1783
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1838
1784
                      " is replaced with raw.\n", stderr);
 
1785
err_exit:
1839
1786
                dict_mem_table_free(table);
1840
1787
                trx_commit_for_mysql(trx);
1841
1788
 
1844
1791
 
1845
1792
        trx->op_info = "creating table";
1846
1793
 
 
1794
        if (row_mysql_is_system_table(table->name)) {
 
1795
 
 
1796
                fprintf(stderr,
 
1797
                        "InnoDB: Error: trying to create a MySQL system"
 
1798
                        " table %s of type InnoDB.\n"
 
1799
                        "InnoDB: MySQL system tables must be"
 
1800
                        " of the MyISAM type!\n",
 
1801
                        table->name);
 
1802
                goto err_exit;
 
1803
        }
 
1804
 
 
1805
        /* Check that no reserved column names are used. */
 
1806
        for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
 
1807
                if (dict_col_name_is_reserved(
 
1808
                            dict_table_get_col_name(table, i))) {
 
1809
 
 
1810
                        goto err_exit;
 
1811
                }
 
1812
        }
 
1813
 
1847
1814
        trx_start_if_not_started(trx);
1848
1815
 
1849
1816
        /* The table name is prefixed with the database name and a '/'.
1918
1885
 
1919
1886
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1920
1887
                trx->error_state = DB_SUCCESS;
1921
 
                trx_general_rollback_for_mysql(trx, NULL);
1922
 
                /* TO DO: free table?  The code below will dereference
1923
 
                table->name, though. */
 
1888
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1924
1889
        }
1925
1890
 
1926
1891
        switch (err) {
1939
1904
                break;
1940
1905
 
1941
1906
        case DB_DUPLICATE_KEY:
 
1907
                ut_print_timestamp(stderr);
 
1908
                fputs("  InnoDB: Error: table ", stderr);
 
1909
                ut_print_name(stderr, trx, TRUE, table->name);
 
1910
                fputs(" already exists in InnoDB internal\n"
 
1911
                      "InnoDB: data dictionary. Have you deleted"
 
1912
                      " the .frm file\n"
 
1913
                      "InnoDB: and not used DROP TABLE?"
 
1914
                      " Have you used DROP DATABASE\n"
 
1915
                      "InnoDB: for InnoDB tables in"
 
1916
                      " MySQL version <= 3.23.43?\n"
 
1917
                      "InnoDB: See the Restrictions section"
 
1918
                      " of the InnoDB manual.\n"
 
1919
                      "InnoDB: You can drop the orphaned table"
 
1920
                      " inside InnoDB by\n"
 
1921
                      "InnoDB: creating an InnoDB table with"
 
1922
                      " the same name in another\n"
 
1923
                      "InnoDB: database and copying the .frm file"
 
1924
                      " to the current database.\n"
 
1925
                      "InnoDB: Then MySQL thinks the table exists,"
 
1926
                      " and DROP TABLE will\n"
 
1927
                      "InnoDB: succeed.\n"
 
1928
                      "InnoDB: You can look for further help from\n"
 
1929
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
1930
                      stderr);
 
1931
 
1942
1932
                /* We may also get err == DB_ERROR if the .ibd file for the
1943
1933
                table already exists */
1944
1934
 
2063
2053
 
2064
2054
                trx->error_state = DB_SUCCESS;
2065
2055
 
2066
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2056
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2067
2057
 
2068
2058
                row_drop_table_for_mysql(table_name, trx, FALSE);
2069
2059
 
2084
2074
the foreign key constraints declared in the string. This function
2085
2075
should be called after the indexes for a table have been created.
2086
2076
Each foreign key constraint must be accompanied with indexes in
2087
 
both participating tables. The indexes are allowed to contain more
 
2077
bot participating tables. The indexes are allowed to contain more
2088
2078
fields than mentioned in the constraint. Check also that foreign key
2089
2079
constraints which reference this table are ok.
2090
2080
@return error code or DB_SUCCESS */
2098
2088
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2099
2089
                                        table2 can be written also with the
2100
2090
                                        database name before it: test.table2 */
2101
 
        size_t          sql_length,     /*!< in: length of sql_string */
2102
2091
        const char*     name,           /*!< in: table full name in the
2103
2092
                                        normalized form
2104
2093
                                        database_name/table_name */
2120
2109
 
2121
2110
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2122
2111
 
2123
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2124
 
                                              name, reject_fks);
 
2112
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2113
                                              reject_fks);
2125
2114
        if (err == DB_SUCCESS) {
2126
2115
                /* Check that also referencing constraints are ok */
2127
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2116
                err = dict_load_foreigns(name, TRUE);
2128
2117
        }
2129
2118
 
2130
2119
        if (err != DB_SUCCESS) {
2132
2121
 
2133
2122
                trx->error_state = DB_SUCCESS;
2134
2123
 
2135
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2124
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2136
2125
 
2137
2126
                row_drop_table_for_mysql(name, trx, FALSE);
2138
2127
 
2351
2340
        trx_t*          trx)    /*!< in: transaction handle */
2352
2341
{
2353
2342
        dict_foreign_t* foreign;
2354
 
        table_id_t      new_id;
 
2343
        dulint          new_id;
2355
2344
        dict_table_t*   table;
2356
2345
        ibool           success;
2357
2346
        ulint           err;
2465
2454
                goto funct_exit;
2466
2455
        }
2467
2456
 
2468
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2457
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2469
2458
 
2470
2459
        /* Remove all locks except the table-level S and X locks. */
2471
2460
        lock_remove_all_on_table(table, FALSE);
2473
2462
        info = pars_info_create();
2474
2463
 
2475
2464
        pars_info_add_str_literal(info, "table_name", name);
2476
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2465
        pars_info_add_dulint_literal(info, "new_id", new_id);
2477
2466
 
2478
2467
        err = que_eval_sql(info,
2479
2468
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2499
2488
 
2500
2489
        if (err != DB_SUCCESS) {
2501
2490
                trx->error_state = DB_SUCCESS;
2502
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2491
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2503
2492
                trx->error_state = DB_SUCCESS;
2504
2493
        } else {
2505
2494
                dict_table_change_id_in_cache(table, new_id);
2508
2497
 
2509
2498
                if (!success) {
2510
2499
                        trx->error_state = DB_SUCCESS;
2511
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
2500
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
2512
2501
                        trx->error_state = DB_SUCCESS;
2513
2502
 
2514
2503
                        err = DB_ERROR;
2687
2676
        dict_index_t*   sys_index;
2688
2677
        btr_pcur_t      pcur;
2689
2678
        mtr_t           mtr;
2690
 
        table_id_t      new_id;
 
2679
        dulint          new_id;
2691
2680
        ulint           recreate_space = 0;
2692
2681
        pars_info_t*    info = NULL;
2693
2682
 
2817
2806
 
2818
2807
        trx->table_id = table->id;
2819
2808
 
2820
 
        /* Lock all index trees for this table, as we will
2821
 
        truncate the table/index and possibly change their metadata.
2822
 
        All DML/DDL are blocked by table level lock, with
2823
 
        a few exceptions such as queries into information schema
2824
 
        about the table, MySQL could try to access index stats
2825
 
        for this kind of query, we need to use index locks to
2826
 
        sync up */
2827
 
        dict_table_x_lock_indexes(table);
2828
 
 
2829
2809
        if (table->space && !table->dir_path_of_temp_table) {
2830
2810
                /* Discard and create the single-table tablespace. */
2831
2811
                ulint   space   = table->space;
2836
2816
 
2837
2817
                        dict_index_t*   index;
2838
2818
 
2839
 
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2819
                        space = 0;
2840
2820
 
2841
 
                        if (space == ULINT_UNDEFINED
2842
 
                            || fil_create_new_single_table_tablespace(
2843
 
                                    space, table->name, FALSE, flags,
 
2821
                        if (fil_create_new_single_table_tablespace(
 
2822
                                    &space, table->name, FALSE, flags,
2844
2823
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2845
 
                                dict_table_x_unlock_indexes(table);
2846
2824
                                ut_print_timestamp(stderr);
2847
2825
                                fprintf(stderr,
2848
2826
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2946
2924
 
2947
2925
        mem_heap_free(heap);
2948
2926
 
2949
 
        /* Done with index truncation, release index tree locks,
2950
 
        subsequent work relates to table level metadata change */
2951
 
        dict_table_x_unlock_indexes(table);
2952
 
 
2953
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2927
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2954
2928
 
2955
2929
        info = pars_info_create();
2956
2930
 
2957
2931
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2958
 
        pars_info_add_ull_literal(info, "old_id", table->id);
2959
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2932
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2933
        pars_info_add_dulint_literal(info, "new_id", new_id);
2960
2934
 
2961
2935
        err = que_eval_sql(info,
2962
2936
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2975
2949
 
2976
2950
        if (err != DB_SUCCESS) {
2977
2951
                trx->error_state = DB_SUCCESS;
2978
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2952
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2979
2953
                trx->error_state = DB_SUCCESS;
2980
2954
                ut_print_timestamp(stderr);
2981
2955
                fputs("  InnoDB: Unable to assign a new identifier to table ",
3316
3290
                           "END;\n"
3317
3291
                           , FALSE, trx);
3318
3292
 
3319
 
        switch (err) {
3320
 
                ibool           is_temp;
 
3293
        if (err != DB_SUCCESS) {
 
3294
                ut_a(err == DB_OUT_OF_FILE_SPACE);
 
3295
 
 
3296
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3297
 
 
3298
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3299
 
 
3300
                ut_error;
 
3301
        } else {
 
3302
                ibool           is_path;
3321
3303
                const char*     name_or_path;
3322
3304
                mem_heap_t*     heap;
3323
3305
 
3324
 
        case DB_SUCCESS:
3325
 
 
3326
3306
                heap = mem_heap_create(200);
3327
3307
 
3328
3308
                /* Clone the name, in case it has been allocated
3332
3312
                space_id = table->space;
3333
3313
 
3334
3314
                if (table->dir_path_of_temp_table != NULL) {
 
3315
                        is_path = TRUE;
3335
3316
                        name_or_path = mem_heap_strdup(
3336
3317
                                heap, table->dir_path_of_temp_table);
3337
 
                        is_temp = TRUE;
3338
3318
                } else {
 
3319
                        is_path = FALSE;
3339
3320
                        name_or_path = name;
3340
 
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
3341
 
                                & DICT_TF2_TEMPORARY;
3342
3321
                }
3343
3322
 
3344
3323
                dict_table_remove_from_cache(table);
3345
3324
 
3346
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3325
                if (dict_load_table(name) != NULL) {
3347
3326
                        ut_print_timestamp(stderr);
3348
3327
                        fputs("  InnoDB: Error: not able to remove table ",
3349
3328
                              stderr);
3358
3337
                if (err == DB_SUCCESS && space_id > 0) {
3359
3338
                        if (!fil_space_for_table_exists_in_mem(space_id,
3360
3339
                                                               name_or_path,
3361
 
                                                               is_temp, FALSE,
3362
 
                                                               !is_temp)) {
 
3340
                                                               is_path,
 
3341
                                                               FALSE, TRUE)) {
3363
3342
                                err = DB_SUCCESS;
3364
3343
 
3365
3344
                                fprintf(stderr,
3388
3367
                }
3389
3368
 
3390
3369
                mem_heap_free(heap);
3391
 
                break;
3392
 
 
3393
 
        case DB_TOO_MANY_CONCURRENT_TRXS:
3394
 
                /* Cannot even find a free slot for the
3395
 
                the undo log. We can directly exit here
3396
 
                and return the DB_TOO_MANY_CONCURRENT_TRXS
3397
 
                error. */
3398
 
                break;
3399
 
 
3400
 
        case DB_OUT_OF_FILE_SPACE:
3401
 
                err = DB_MUST_GET_MORE_FILE_SPACE;
3402
 
 
3403
 
                row_mysql_handle_errors(&err, trx, NULL, NULL);
3404
 
 
3405
 
                /* Fall through to raise error */
3406
 
 
3407
 
        default:
3408
 
                /* No other possible error returns */
3409
 
                ut_error;
3410
3370
        }
3411
 
 
3412
3371
funct_exit:
3413
3372
 
3414
3373
        if (locked_dictionary) {
3424
3383
        return((int) err);
3425
3384
}
3426
3385
 
3427
 
/*********************************************************************//**
3428
 
Drop all temporary tables during crash recovery. */
3429
 
UNIV_INTERN
3430
 
void
3431
 
row_mysql_drop_temp_tables(void)
3432
 
/*============================*/
3433
 
{
3434
 
        trx_t*          trx;
3435
 
        btr_pcur_t      pcur;
3436
 
        mtr_t           mtr;
3437
 
        mem_heap_t*     heap;
3438
 
 
3439
 
        trx = trx_allocate_for_background();
3440
 
        trx->op_info = "dropping temporary tables";
3441
 
        row_mysql_lock_data_dictionary(trx);
3442
 
 
3443
 
        heap = mem_heap_create(200);
3444
 
 
3445
 
        mtr_start(&mtr);
3446
 
 
3447
 
        btr_pcur_open_at_index_side(
3448
 
                TRUE,
3449
 
                dict_table_get_first_index(dict_sys->sys_tables),
3450
 
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
3451
 
 
3452
 
        for (;;) {
3453
 
                const rec_t*    rec;
3454
 
                const byte*     field;
3455
 
                ulint           len;
3456
 
                const char*     table_name;
3457
 
                dict_table_t*   table;
3458
 
 
3459
 
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3460
 
 
3461
 
                if (!btr_pcur_is_on_user_rec(&pcur)) {
3462
 
                        break;
3463
 
                }
3464
 
 
3465
 
                rec = btr_pcur_get_rec(&pcur);
3466
 
                field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
3467
 
                if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
3468
 
                        continue;
3469
 
                }
3470
 
 
3471
 
                /* Because this is not a ROW_FORMAT=REDUNDANT table,
3472
 
                the is_temp flag is valid.  Examine it. */
3473
 
 
3474
 
                field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
3475
 
                if (len != 4
3476
 
                    || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
3477
 
                        continue;
3478
 
                }
3479
 
 
3480
 
                /* This is a temporary table. */
3481
 
                field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
3482
 
                if (len == UNIV_SQL_NULL || len == 0) {
3483
 
                        /* Corrupted SYS_TABLES.NAME */
3484
 
                        continue;
3485
 
                }
3486
 
 
3487
 
                table_name = mem_heap_strdupl(heap, (const char*) field, len);
3488
 
 
3489
 
                btr_pcur_store_position(&pcur, &mtr);
3490
 
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
3491
 
 
3492
 
                table = dict_load_table(table_name, TRUE);
3493
 
 
3494
 
                if (table) {
3495
 
                        row_drop_table_for_mysql(table_name, trx, FALSE);
3496
 
                        trx_commit_for_mysql(trx);
3497
 
                }
3498
 
 
3499
 
                mtr_start(&mtr);
3500
 
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
3501
 
                                          &pcur, &mtr);
3502
 
        }
3503
 
 
3504
 
        btr_pcur_close(&pcur);
3505
 
        mtr_commit(&mtr);
3506
 
        mem_heap_free(heap);
3507
 
        row_mysql_unlock_data_dictionary(trx);
3508
 
        trx_free_for_background(trx);
3509
 
}
3510
 
 
3511
3386
/*******************************************************************//**
3512
3387
Drop all foreign keys in a database, see Bug#18942.
3513
3388
Called at the end of row_drop_database_for_mysql().
3596
3471
        while ((table_name = dict_get_first_table_name_in_db(name))) {
3597
3472
                ut_a(memcmp(table_name, name, namelen) == 0);
3598
3473
 
3599
 
                // For the time being I would like to see how often we see
3600
 
                // lost temporary tables. --Brian
3601
 
                fprintf(stderr, "Dropping lost temporary table %s\n", table_name);
3602
 
 
3603
3474
                table = dict_table_get_low(table_name);
3604
3475
 
3605
3476
                ut_a(table);
3771
3642
                      stderr);
3772
3643
 
3773
3644
                goto funct_exit;
 
3645
        } else if (row_mysql_is_system_table(new_name)) {
 
3646
 
 
3647
                fprintf(stderr,
 
3648
                        "InnoDB: Error: trying to create a MySQL"
 
3649
                        " system table %s of type InnoDB.\n"
 
3650
                        "InnoDB: MySQL system tables must be"
 
3651
                        " of the MyISAM type!\n",
 
3652
                        new_name);
 
3653
 
 
3654
                goto funct_exit;
3774
3655
        }
3775
3656
 
3776
3657
        trx->op_info = "renaming table";
3983
3864
                              "InnoDB: succeed.\n", stderr);
3984
3865
                }
3985
3866
                trx->error_state = DB_SUCCESS;
3986
 
                trx_general_rollback_for_mysql(trx, NULL);
 
3867
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
3987
3868
                trx->error_state = DB_SUCCESS;
3988
3869
        } else {
3989
3870
                /* The following call will also rename the .ibd data file if
3992
3873
                if (!dict_table_rename_in_cache(table, new_name,
3993
3874
                                                !new_is_tmp)) {
3994
3875
                        trx->error_state = DB_SUCCESS;
3995
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3876
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
3996
3877
                        trx->error_state = DB_SUCCESS;
3997
3878
                        goto funct_exit;
3998
3879
                }
4001
3882
                an ALTER, not in a RENAME. */
4002
3883
 
4003
3884
                err = dict_load_foreigns(
4004
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3885
                        new_name, !old_is_tmp || trx->check_foreigns);
4005
3886
 
4006
3887
                if (err != DB_SUCCESS) {
4007
3888
                        ut_print_timestamp(stderr);
4032
3913
                        ut_a(dict_table_rename_in_cache(table,
4033
3914
                                                        old_name, FALSE));
4034
3915
                        trx->error_state = DB_SUCCESS;
4035
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3916
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
4036
3917
                        trx->error_state = DB_SUCCESS;
4037
3918
                }
4038
3919
        }
4057
3938
constraint is not broken, and calculates the number of index entries
4058
3939
in the read view of the current transaction.
4059
3940
@return TRUE if ok */
4060
 
UNIV_INTERN
 
3941
static
4061
3942
ibool
4062
 
row_check_index_for_mysql(
4063
 
/*======================*/
4064
 
        row_prebuilt_t*         prebuilt,       /*!< in: prebuilt struct
4065
 
                                                in MySQL handle */
4066
 
        const dict_index_t*     index,          /*!< in: index */
4067
 
        ulint*                  n_rows)         /*!< out: number of entries
4068
 
                                                seen in the consistent read */
 
3943
row_scan_and_check_index(
 
3944
/*=====================*/
 
3945
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
 
3946
        dict_index_t*   index,          /*!< in: index */
 
3947
        ulint*          n_rows)         /*!< out: number of entries seen in the
 
3948
                                        current consistent read */
4069
3949
{
4070
3950
        dtuple_t*       prev_entry      = NULL;
4071
3951
        ulint           matched_fields;
4086
3966
 
4087
3967
        *n_rows = 0;
4088
3968
 
 
3969
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
3970
                /* A newly created index may lack some delete-marked
 
3971
                records that may exist in the read view of
 
3972
                prebuilt->trx.  Thus, such indexes must not be
 
3973
                accessed by consistent read. */
 
3974
                return(is_ok);
 
3975
        }
 
3976
 
4089
3977
        buf = mem_alloc(UNIV_PAGE_SIZE);
4090
3978
        heap = mem_heap_create(100);
4091
3979
 
 
3980
        /* Make a dummy template in prebuilt, which we will use
 
3981
        in scanning the index entries */
 
3982
 
 
3983
        prebuilt->index = index;
 
3984
        /* row_merge_is_index_usable() was already checked above. */
 
3985
        prebuilt->index_usable = TRUE;
 
3986
        prebuilt->sql_stat_start = TRUE;
 
3987
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
 
3988
        prebuilt->n_template = 0;
 
3989
        prebuilt->need_to_access_clustered = FALSE;
 
3990
 
 
3991
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
3992
 
 
3993
        prebuilt->select_lock_type = LOCK_NONE;
4092
3994
        cnt = 1000;
4093
3995
 
4094
3996
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4207
4109
}
4208
4110
 
4209
4111
/*********************************************************************//**
 
4112
Checks a table for corruption.
 
4113
@return DB_ERROR or DB_SUCCESS */
 
4114
UNIV_INTERN
 
4115
ulint
 
4116
row_check_table_for_mysql(
 
4117
/*======================*/
 
4118
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
 
4119
                                        handle */
 
4120
{
 
4121
        dict_table_t*   table           = prebuilt->table;
 
4122
        dict_index_t*   index;
 
4123
        ulint           n_rows;
 
4124
        ulint           n_rows_in_table = ULINT_UNDEFINED;
 
4125
        ulint           ret             = DB_SUCCESS;
 
4126
        ulint           old_isolation_level;
 
4127
 
 
4128
        if (table->ibd_file_missing) {
 
4129
                ut_print_timestamp(stderr);
 
4130
                fprintf(stderr, "  InnoDB: Error:\n"
 
4131
                        "InnoDB: MySQL is trying to use a table handle"
 
4132
                        " but the .ibd file for\n"
 
4133
                        "InnoDB: table %s does not exist.\n"
 
4134
                        "InnoDB: Have you deleted the .ibd file"
 
4135
                        " from the database directory under\n"
 
4136
                        "InnoDB: the MySQL datadir, or have you"
 
4137
                        " used DISCARD TABLESPACE?\n"
 
4138
                        "InnoDB: Look from\n"
 
4139
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
 
4140
                        "InnoDB: how you can resolve the problem.\n",
 
4141
                        table->name);
 
4142
                return(DB_ERROR);
 
4143
        }
 
4144
 
 
4145
        prebuilt->trx->op_info = "checking table";
 
4146
 
 
4147
        old_isolation_level = prebuilt->trx->isolation_level;
 
4148
 
 
4149
        /* We must run the index record counts at an isolation level
 
4150
        >= READ COMMITTED, because a dirty read can see a wrong number
 
4151
        of records in some index; to play safe, we use always
 
4152
        REPEATABLE READ here */
 
4153
 
 
4154
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
 
4155
 
 
4156
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
 
4157
        mutex_enter(&kernel_mutex);
 
4158
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
 
4159
        mutex_exit(&kernel_mutex);
 
4160
 
 
4161
        index = dict_table_get_first_index(table);
 
4162
 
 
4163
        while (index != NULL) {
 
4164
                /* fputs("Validating index ", stderr);
 
4165
                ut_print_name(stderr, trx, FALSE, index->name);
 
4166
                putc('\n', stderr); */
 
4167
 
 
4168
                if (!btr_validate_index(index, prebuilt->trx)) {
 
4169
                        ret = DB_ERROR;
 
4170
                } else {
 
4171
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
 
4172
                                ret = DB_ERROR;
 
4173
                        }
 
4174
 
 
4175
                        if (trx_is_interrupted(prebuilt->trx)) {
 
4176
                                break;
 
4177
                        }
 
4178
 
 
4179
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
 
4180
                        index->name); */
 
4181
 
 
4182
                        if (index == dict_table_get_first_index(table)) {
 
4183
                                n_rows_in_table = n_rows;
 
4184
                        } else if (n_rows != n_rows_in_table) {
 
4185
 
 
4186
                                ret = DB_ERROR;
 
4187
 
 
4188
                                fputs("Error: ", stderr);
 
4189
                                dict_index_name_print(stderr,
 
4190
                                                      prebuilt->trx, index);
 
4191
                                fprintf(stderr,
 
4192
                                        " contains %lu entries,"
 
4193
                                        " should be %lu\n",
 
4194
                                        (ulong) n_rows,
 
4195
                                        (ulong) n_rows_in_table);
 
4196
                        }
 
4197
                }
 
4198
 
 
4199
                index = dict_table_get_next_index(index);
 
4200
        }
 
4201
 
 
4202
        /* Restore the original isolation level */
 
4203
        prebuilt->trx->isolation_level = old_isolation_level;
 
4204
 
 
4205
        /* We validate also the whole adaptive hash index for all tables
 
4206
        at every CHECK TABLE */
 
4207
 
 
4208
        if (!btr_search_validate()) {
 
4209
 
 
4210
                ret = DB_ERROR;
 
4211
        }
 
4212
 
 
4213
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
 
4214
        mutex_enter(&kernel_mutex);
 
4215
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
4216
        mutex_exit(&kernel_mutex);
 
4217
 
 
4218
        prebuilt->trx->op_info = "";
 
4219
 
 
4220
        return(ret);
 
4221
}
 
4222
 
 
4223
/*********************************************************************//**
4210
4224
Determines if a table is a magic monitor table.
4211
4225
@return TRUE if monitor table */
4212
4226
UNIV_INTERN