~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Separated BlitzCursor code out to it's own file.

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
 
95
95
        ((str1_len) == sizeof(str2_onstack) \
96
96
         && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
97
97
 
 
98
/*******************************************************************//**
 
99
Determine if the given name is a name reserved for MySQL system tables.
 
100
@return TRUE if name is a MySQL system table name */
 
101
static
 
102
ibool
 
103
row_mysql_is_system_table(
 
104
/*======================*/
 
105
        const char*     name)
 
106
{
 
107
        if (strncmp(name, "mysql/", 6) != 0) {
 
108
 
 
109
                return(FALSE);
 
110
        }
 
111
 
 
112
        return(0 == strcmp(name + 6, "host")
 
113
               || 0 == strcmp(name + 6, "user")
 
114
               || 0 == strcmp(name + 6, "db"));
 
115
}
 
116
 
98
117
/*********************************************************************//**
99
118
If a table is not yet in the drop list, adds the table to the list of tables
100
119
which the master thread drops in background. We need this on Unix because in
249
268
}
250
269
 
251
270
/**************************************************************//**
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
271
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
272
The counterpart of this function is row_sel_field_store_in_mysql_format() in
297
273
row0sel.c.
383
359
                        /* Remove trailing spaces from old style VARCHAR
384
360
                        columns. */
385
361
 
386
 
                        /* Handle Unicode strings differently. */
 
362
                        /* Handle UCS2 strings differently. */
387
363
                        ulint   mbminlen        = dtype_get_mbminlen(dtype);
388
364
 
389
365
                        ptr = mysql_data;
390
366
 
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:
 
367
                        if (mbminlen == 2) {
408
368
                                /* space=0x0020 */
409
369
                                /* Trim "half-chars", just in case. */
410
370
                                col_len &= ~1;
413
373
                                       && ptr[col_len - 1] == 0x20) {
414
374
                                        col_len -= 2;
415
375
                                }
416
 
                                break;
417
 
                        case 1:
 
376
                        } else {
 
377
                                ut_a(mbminlen == 1);
418
378
                                /* space=0x20 */
419
379
                                while (col_len > 0
420
380
                                       && ptr[col_len - 1] == 0x20) {
527
487
/****************************************************************//**
528
488
Handles user errors and lock waits detected by the database engine.
529
489
@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. */
 
490
query thread */
531
491
UNIV_INTERN
532
492
ibool
533
493
row_mysql_handle_errors(
552
512
        switch (err) {
553
513
        case DB_LOCK_WAIT_TIMEOUT:
554
514
                if (row_rollback_on_timeout) {
555
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
515
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
556
516
                        break;
557
517
                }
558
518
                /* fall through */
564
524
        case DB_CANNOT_ADD_CONSTRAINT:
565
525
        case DB_TOO_MANY_CONCURRENT_TRXS:
566
526
        case DB_OUT_OF_FILE_SPACE:
567
 
        case DB_INTERRUPTED:
568
527
                if (savept) {
569
528
                        /* Roll back the latest, possibly incomplete
570
529
                        insertion or update */
571
530
 
572
 
                        trx_general_rollback_for_mysql(trx, savept);
 
531
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
573
532
                }
574
533
                /* MySQL will roll back the latest SQL statement */
575
534
                break;
591
550
                /* Roll back the whole transaction; this resolution was added
592
551
                to version 3.23.43 */
593
552
 
594
 
                trx_general_rollback_for_mysql(trx, NULL);
 
553
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
595
554
                break;
596
555
 
597
556
        case DB_MUST_GET_MORE_FILE_SPACE:
618
577
                      "InnoDB: " REFMAN "forcing-recovery.html"
619
578
                      " for help.\n", stderr);
620
579
                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
580
        default:
629
581
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
630
582
                        (ulong) err);
674
626
 
675
627
        prebuilt->select_lock_type = LOCK_NONE;
676
628
        prebuilt->stored_select_lock_type = 99999999;
677
 
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
 
                         sizeof prebuilt->stored_select_lock_type);
679
629
 
680
630
        prebuilt->search_tuple = dtuple_create(
681
631
                heap, 2 * dict_table_get_n_cols(table));
840
790
        }
841
791
}
842
792
 
843
 
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
844
 
 
845
793
/*********************************************************************//**
846
794
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
795
has not yet been built in the prebuilt struct, then this function first
848
796
builds it.
849
797
@return prebuilt dtuple; the column type information is also set in it */
 
798
static
850
799
dtuple_t*
851
800
row_get_prebuilt_insert_row(
852
801
/*========================*/
919
868
}
920
869
 
921
870
/*********************************************************************//**
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). */
 
871
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
925
872
UNIV_INTERN
926
873
void
927
874
row_unlock_table_autoinc_for_mysql(
928
875
/*===============================*/
929
876
        trx_t*  trx)    /*!< in/out: transaction */
930
877
{
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
 
        }
 
878
        mutex_enter(&kernel_mutex);
 
879
 
 
880
        lock_release_autoinc_locks(trx);
 
881
 
 
882
        mutex_exit(&kernel_mutex);
938
883
}
939
884
 
940
885
/*********************************************************************//**
1431
1376
run_again:
1432
1377
        thr->run_node = node;
1433
1378
        thr->prev_node = node;
1434
 
        thr->fk_cascade_depth = 0;
1435
1379
 
1436
1380
        row_upd_step(thr);
1437
1381
 
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
1382
        err = trx->error_state;
1445
1383
 
1446
 
        /* Reset fk_cascade_depth back to 0 */
1447
 
        thr->fk_cascade_depth = 0;
1448
 
 
1449
1384
        if (err != DB_SUCCESS) {
1450
1385
                que_thr_stop_for_mysql(thr);
1451
1386
 
1482
1417
                srv_n_rows_updated++;
1483
1418
        }
1484
1419
 
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
 
        }
 
1420
        row_update_statistics_if_needed(prebuilt->table);
1491
1421
 
1492
1422
        trx->op_info = "";
1493
1423
 
1495
1425
}
1496
1426
 
1497
1427
/*********************************************************************//**
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 */
 
1428
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
 
1429
this session is using a READ COMMITTED isolation level. Before
 
1430
calling this function we must use trx_reset_new_rec_lock_info() and
 
1431
trx_register_new_rec_lock() to store the information which new record locks
 
1432
really were set. This function removes a newly set lock under prebuilt->pcur,
 
1433
and also under prebuilt->clust_pcur. Currently, this is only used and tested
 
1434
in the case of an UPDATE or a DELETE statement, where the row lock is of the
 
1435
LOCK_X type.
 
1436
Thus, this implements a 'mini-rollback' that releases the latest record
 
1437
locks we set.
 
1438
@return error code or DB_SUCCESS */
1507
1439
UNIV_INTERN
1508
1440
int
1509
1441
row_unlock_for_mysql(
1510
1442
/*=================*/
1511
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1443
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1512
1444
                                        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. */
 
1445
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
 
1446
                                        the latches on the records under pcur
 
1447
                                        and clust_pcur, and we do not need to
 
1448
                                        reposition the cursors. */
1518
1449
{
1519
1450
        btr_pcur_t*     pcur            = prebuilt->pcur;
1520
1451
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1525
1456
 
1526
1457
        if (UNIV_UNLIKELY
1527
1458
            (!srv_locks_unsafe_for_binlog
1528
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1459
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1529
1460
 
1530
1461
                fprintf(stderr,
1531
1462
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1597
1528
                        }
1598
1529
                }
1599
1530
 
1600
 
                if (rec_trx_id != trx->id) {
 
1531
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1601
1532
                        /* We did not update the record: unlock it */
1602
1533
 
1603
1534
                        rec = btr_pcur_get_rec(pcur);
1641
1572
        trx_t*  trx;
1642
1573
 
1643
1574
        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
1575
run_again:
1654
1576
        thr->run_node = node;
1655
1577
        thr->prev_node = node;
1656
1578
 
1657
1579
        row_upd_step(thr);
1658
1580
 
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
1581
        err = trx->error_state;
1666
1582
 
1667
1583
        /* Note that the cascade node is a subnode of another InnoDB
1727
1643
}
1728
1644
 
1729
1645
/*********************************************************************//**
 
1646
Calculates the key number used inside MySQL for an Innobase index. We have
 
1647
to take into account if we generated a default clustered index for the table
 
1648
@return the key number used inside MySQL */
 
1649
UNIV_INTERN
 
1650
ulint
 
1651
row_get_mysql_key_number_for_index(
 
1652
/*===============================*/
 
1653
        const dict_index_t*     index)  /*!< in: index */
 
1654
{
 
1655
        const dict_index_t*     ind;
 
1656
        ulint                   i;
 
1657
 
 
1658
        ut_a(index);
 
1659
 
 
1660
        i = 0;
 
1661
        ind = dict_table_get_first_index(index->table);
 
1662
 
 
1663
        while (index != ind) {
 
1664
                ind = dict_table_get_next_index(ind);
 
1665
                i++;
 
1666
        }
 
1667
 
 
1668
        if (row_table_got_default_clust_index(index->table)) {
 
1669
                ut_a(i > 0);
 
1670
                i--;
 
1671
        }
 
1672
 
 
1673
        return(i);
 
1674
}
 
1675
 
 
1676
/*********************************************************************//**
1730
1677
Locks the data dictionary in shared mode from modifications, for performing
1731
1678
foreign key check, rollback, or other operation invisible to MySQL. */
1732
1679
UNIV_INTERN
1822
1769
        const char*     table_name;
1823
1770
        ulint           table_name_len;
1824
1771
        ulint           err;
 
1772
        ulint           i;
1825
1773
 
1826
1774
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1827
1775
#ifdef UNIV_SYNC_DEBUG
1836
1784
                      " by the user.\n"
1837
1785
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1838
1786
                      " is replaced with raw.\n", stderr);
 
1787
err_exit:
1839
1788
                dict_mem_table_free(table);
1840
1789
                trx_commit_for_mysql(trx);
1841
1790
 
1844
1793
 
1845
1794
        trx->op_info = "creating table";
1846
1795
 
 
1796
        if (row_mysql_is_system_table(table->name)) {
 
1797
 
 
1798
                fprintf(stderr,
 
1799
                        "InnoDB: Error: trying to create a MySQL system"
 
1800
                        " table %s of type InnoDB.\n"
 
1801
                        "InnoDB: MySQL system tables must be"
 
1802
                        " of the MyISAM type!\n",
 
1803
                        table->name);
 
1804
                goto err_exit;
 
1805
        }
 
1806
 
 
1807
        /* Check that no reserved column names are used. */
 
1808
        for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
 
1809
                if (dict_col_name_is_reserved(
 
1810
                            dict_table_get_col_name(table, i))) {
 
1811
 
 
1812
                        goto err_exit;
 
1813
                }
 
1814
        }
 
1815
 
1847
1816
        trx_start_if_not_started(trx);
1848
1817
 
1849
1818
        /* The table name is prefixed with the database name and a '/'.
1918
1887
 
1919
1888
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1920
1889
                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. */
 
1890
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1924
1891
        }
1925
1892
 
1926
1893
        switch (err) {
1939
1906
                break;
1940
1907
 
1941
1908
        case DB_DUPLICATE_KEY:
 
1909
                ut_print_timestamp(stderr);
 
1910
                fputs("  InnoDB: Error: table ", stderr);
 
1911
                ut_print_name(stderr, trx, TRUE, table->name);
 
1912
                fputs(" already exists in InnoDB internal\n"
 
1913
                      "InnoDB: data dictionary. Have you deleted"
 
1914
                      " the .frm file\n"
 
1915
                      "InnoDB: and not used DROP TABLE?"
 
1916
                      " Have you used DROP DATABASE\n"
 
1917
                      "InnoDB: for InnoDB tables in"
 
1918
                      " MySQL version <= 3.23.43?\n"
 
1919
                      "InnoDB: See the Restrictions section"
 
1920
                      " of the InnoDB manual.\n"
 
1921
                      "InnoDB: You can drop the orphaned table"
 
1922
                      " inside InnoDB by\n"
 
1923
                      "InnoDB: creating an InnoDB table with"
 
1924
                      " the same name in another\n"
 
1925
                      "InnoDB: database and copying the .frm file"
 
1926
                      " to the current database.\n"
 
1927
                      "InnoDB: Then MySQL thinks the table exists,"
 
1928
                      " and DROP TABLE will\n"
 
1929
                      "InnoDB: succeed.\n"
 
1930
                      "InnoDB: You can look for further help from\n"
 
1931
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
1932
                      stderr);
 
1933
 
1942
1934
                /* We may also get err == DB_ERROR if the .ibd file for the
1943
1935
                table already exists */
1944
1936
 
2063
2055
 
2064
2056
                trx->error_state = DB_SUCCESS;
2065
2057
 
2066
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2058
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2067
2059
 
2068
2060
                row_drop_table_for_mysql(table_name, trx, FALSE);
2069
2061
 
2084
2076
the foreign key constraints declared in the string. This function
2085
2077
should be called after the indexes for a table have been created.
2086
2078
Each foreign key constraint must be accompanied with indexes in
2087
 
both participating tables. The indexes are allowed to contain more
 
2079
bot participating tables. The indexes are allowed to contain more
2088
2080
fields than mentioned in the constraint. Check also that foreign key
2089
2081
constraints which reference this table are ok.
2090
2082
@return error code or DB_SUCCESS */
2098
2090
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2099
2091
                                        table2 can be written also with the
2100
2092
                                        database name before it: test.table2 */
2101
 
        size_t          sql_length,     /*!< in: length of sql_string */
2102
2093
        const char*     name,           /*!< in: table full name in the
2103
2094
                                        normalized form
2104
2095
                                        database_name/table_name */
2120
2111
 
2121
2112
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2122
2113
 
2123
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2124
 
                                              name, reject_fks);
 
2114
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2115
                                              reject_fks);
2125
2116
        if (err == DB_SUCCESS) {
2126
2117
                /* Check that also referencing constraints are ok */
2127
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2118
                err = dict_load_foreigns(name, TRUE);
2128
2119
        }
2129
2120
 
2130
2121
        if (err != DB_SUCCESS) {
2132
2123
 
2133
2124
                trx->error_state = DB_SUCCESS;
2134
2125
 
2135
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2126
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2136
2127
 
2137
2128
                row_drop_table_for_mysql(name, trx, FALSE);
2138
2129
 
2351
2342
        trx_t*          trx)    /*!< in: transaction handle */
2352
2343
{
2353
2344
        dict_foreign_t* foreign;
2354
 
        table_id_t      new_id;
 
2345
        dulint          new_id;
2355
2346
        dict_table_t*   table;
2356
2347
        ibool           success;
2357
2348
        ulint           err;
2465
2456
                goto funct_exit;
2466
2457
        }
2467
2458
 
2468
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2459
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2469
2460
 
2470
2461
        /* Remove all locks except the table-level S and X locks. */
2471
2462
        lock_remove_all_on_table(table, FALSE);
2473
2464
        info = pars_info_create();
2474
2465
 
2475
2466
        pars_info_add_str_literal(info, "table_name", name);
2476
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2467
        pars_info_add_dulint_literal(info, "new_id", new_id);
2477
2468
 
2478
2469
        err = que_eval_sql(info,
2479
2470
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2499
2490
 
2500
2491
        if (err != DB_SUCCESS) {
2501
2492
                trx->error_state = DB_SUCCESS;
2502
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2493
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2503
2494
                trx->error_state = DB_SUCCESS;
2504
2495
        } else {
2505
2496
                dict_table_change_id_in_cache(table, new_id);
2508
2499
 
2509
2500
                if (!success) {
2510
2501
                        trx->error_state = DB_SUCCESS;
2511
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
2502
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
2512
2503
                        trx->error_state = DB_SUCCESS;
2513
2504
 
2514
2505
                        err = DB_ERROR;
2687
2678
        dict_index_t*   sys_index;
2688
2679
        btr_pcur_t      pcur;
2689
2680
        mtr_t           mtr;
2690
 
        table_id_t      new_id;
 
2681
        dulint          new_id;
2691
2682
        ulint           recreate_space = 0;
2692
2683
        pars_info_t*    info = NULL;
2693
2684
 
2817
2808
 
2818
2809
        trx->table_id = table->id;
2819
2810
 
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
2811
        if (table->space && !table->dir_path_of_temp_table) {
2830
2812
                /* Discard and create the single-table tablespace. */
2831
2813
                ulint   space   = table->space;
2836
2818
 
2837
2819
                        dict_index_t*   index;
2838
2820
 
2839
 
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2821
                        space = 0;
2840
2822
 
2841
 
                        if (space == ULINT_UNDEFINED
2842
 
                            || fil_create_new_single_table_tablespace(
2843
 
                                    space, table->name, FALSE, flags,
 
2823
                        if (fil_create_new_single_table_tablespace(
 
2824
                                    &space, table->name, FALSE, flags,
2844
2825
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2845
 
                                dict_table_x_unlock_indexes(table);
2846
2826
                                ut_print_timestamp(stderr);
2847
2827
                                fprintf(stderr,
2848
2828
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2946
2926
 
2947
2927
        mem_heap_free(heap);
2948
2928
 
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);
 
2929
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2954
2930
 
2955
2931
        info = pars_info_create();
2956
2932
 
2957
2933
        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);
 
2934
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2935
        pars_info_add_dulint_literal(info, "new_id", new_id);
2960
2936
 
2961
2937
        err = que_eval_sql(info,
2962
2938
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2975
2951
 
2976
2952
        if (err != DB_SUCCESS) {
2977
2953
                trx->error_state = DB_SUCCESS;
2978
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2954
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2979
2955
                trx->error_state = DB_SUCCESS;
2980
2956
                ut_print_timestamp(stderr);
2981
2957
                fputs("  InnoDB: Unable to assign a new identifier to table ",
3316
3292
                           "END;\n"
3317
3293
                           , FALSE, trx);
3318
3294
 
3319
 
        switch (err) {
3320
 
                ibool           is_temp;
 
3295
        if (err != DB_SUCCESS) {
 
3296
                ut_a(err == DB_OUT_OF_FILE_SPACE);
 
3297
 
 
3298
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3299
 
 
3300
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3301
 
 
3302
                ut_error;
 
3303
        } else {
 
3304
                ibool           is_path;
3321
3305
                const char*     name_or_path;
3322
3306
                mem_heap_t*     heap;
3323
3307
 
3324
 
        case DB_SUCCESS:
3325
 
 
3326
3308
                heap = mem_heap_create(200);
3327
3309
 
3328
3310
                /* Clone the name, in case it has been allocated
3332
3314
                space_id = table->space;
3333
3315
 
3334
3316
                if (table->dir_path_of_temp_table != NULL) {
 
3317
                        is_path = TRUE;
3335
3318
                        name_or_path = mem_heap_strdup(
3336
3319
                                heap, table->dir_path_of_temp_table);
3337
 
                        is_temp = TRUE;
3338
3320
                } else {
 
3321
                        is_path = FALSE;
3339
3322
                        name_or_path = name;
3340
 
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
3341
 
                                & DICT_TF2_TEMPORARY;
3342
3323
                }
3343
3324
 
3344
3325
                dict_table_remove_from_cache(table);
3345
3326
 
3346
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3327
                if (dict_load_table(name) != NULL) {
3347
3328
                        ut_print_timestamp(stderr);
3348
3329
                        fputs("  InnoDB: Error: not able to remove table ",
3349
3330
                              stderr);
3358
3339
                if (err == DB_SUCCESS && space_id > 0) {
3359
3340
                        if (!fil_space_for_table_exists_in_mem(space_id,
3360
3341
                                                               name_or_path,
3361
 
                                                               is_temp, FALSE,
3362
 
                                                               !is_temp)) {
 
3342
                                                               is_path,
 
3343
                                                               FALSE, TRUE)) {
3363
3344
                                err = DB_SUCCESS;
3364
3345
 
3365
3346
                                fprintf(stderr,
3388
3369
                }
3389
3370
 
3390
3371
                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
3372
        }
3411
 
 
3412
3373
funct_exit:
3413
3374
 
3414
3375
        if (locked_dictionary) {
3424
3385
        return((int) err);
3425
3386
}
3426
3387
 
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
3388
/*******************************************************************//**
3512
3389
Drop all foreign keys in a database, see Bug#18942.
3513
3390
Called at the end of row_drop_database_for_mysql().
3596
3473
        while ((table_name = dict_get_first_table_name_in_db(name))) {
3597
3474
                ut_a(memcmp(table_name, name, namelen) == 0);
3598
3475
 
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
3476
                table = dict_table_get_low(table_name);
3604
3477
 
3605
3478
                ut_a(table);
3771
3644
                      stderr);
3772
3645
 
3773
3646
                goto funct_exit;
 
3647
        } else if (row_mysql_is_system_table(new_name)) {
 
3648
 
 
3649
                fprintf(stderr,
 
3650
                        "InnoDB: Error: trying to create a MySQL"
 
3651
                        " system table %s of type InnoDB.\n"
 
3652
                        "InnoDB: MySQL system tables must be"
 
3653
                        " of the MyISAM type!\n",
 
3654
                        new_name);
 
3655
 
 
3656
                goto funct_exit;
3774
3657
        }
3775
3658
 
3776
3659
        trx->op_info = "renaming table";
3983
3866
                              "InnoDB: succeed.\n", stderr);
3984
3867
                }
3985
3868
                trx->error_state = DB_SUCCESS;
3986
 
                trx_general_rollback_for_mysql(trx, NULL);
 
3869
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
3987
3870
                trx->error_state = DB_SUCCESS;
3988
3871
        } else {
3989
3872
                /* The following call will also rename the .ibd data file if
3992
3875
                if (!dict_table_rename_in_cache(table, new_name,
3993
3876
                                                !new_is_tmp)) {
3994
3877
                        trx->error_state = DB_SUCCESS;
3995
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3878
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
3996
3879
                        trx->error_state = DB_SUCCESS;
3997
3880
                        goto funct_exit;
3998
3881
                }
4001
3884
                an ALTER, not in a RENAME. */
4002
3885
 
4003
3886
                err = dict_load_foreigns(
4004
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3887
                        new_name, !old_is_tmp || trx->check_foreigns);
4005
3888
 
4006
3889
                if (err != DB_SUCCESS) {
4007
3890
                        ut_print_timestamp(stderr);
4032
3915
                        ut_a(dict_table_rename_in_cache(table,
4033
3916
                                                        old_name, FALSE));
4034
3917
                        trx->error_state = DB_SUCCESS;
4035
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3918
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
4036
3919
                        trx->error_state = DB_SUCCESS;
4037
3920
                }
4038
3921
        }
4057
3940
constraint is not broken, and calculates the number of index entries
4058
3941
in the read view of the current transaction.
4059
3942
@return TRUE if ok */
4060
 
UNIV_INTERN
 
3943
static
4061
3944
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 */
 
3945
row_scan_and_check_index(
 
3946
/*=====================*/
 
3947
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
 
3948
        dict_index_t*   index,          /*!< in: index */
 
3949
        ulint*          n_rows)         /*!< out: number of entries seen in the
 
3950
                                        current consistent read */
4069
3951
{
4070
3952
        dtuple_t*       prev_entry      = NULL;
4071
3953
        ulint           matched_fields;
4086
3968
 
4087
3969
        *n_rows = 0;
4088
3970
 
 
3971
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
3972
                /* A newly created index may lack some delete-marked
 
3973
                records that may exist in the read view of
 
3974
                prebuilt->trx.  Thus, such indexes must not be
 
3975
                accessed by consistent read. */
 
3976
                return(is_ok);
 
3977
        }
 
3978
 
4089
3979
        buf = mem_alloc(UNIV_PAGE_SIZE);
4090
3980
        heap = mem_heap_create(100);
4091
3981
 
 
3982
        /* Make a dummy template in prebuilt, which we will use
 
3983
        in scanning the index entries */
 
3984
 
 
3985
        prebuilt->index = index;
 
3986
        /* row_merge_is_index_usable() was already checked above. */
 
3987
        prebuilt->index_usable = TRUE;
 
3988
        prebuilt->sql_stat_start = TRUE;
 
3989
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
 
3990
        prebuilt->n_template = 0;
 
3991
        prebuilt->need_to_access_clustered = FALSE;
 
3992
 
 
3993
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
3994
 
 
3995
        prebuilt->select_lock_type = LOCK_NONE;
4092
3996
        cnt = 1000;
4093
3997
 
4094
3998
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4207
4111
}
4208
4112
 
4209
4113
/*********************************************************************//**
 
4114
Checks a table for corruption.
 
4115
@return DB_ERROR or DB_SUCCESS */
 
4116
UNIV_INTERN
 
4117
ulint
 
4118
row_check_table_for_mysql(
 
4119
/*======================*/
 
4120
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
 
4121
                                        handle */
 
4122
{
 
4123
        dict_table_t*   table           = prebuilt->table;
 
4124
        dict_index_t*   index;
 
4125
        ulint           n_rows;
 
4126
        ulint           n_rows_in_table = ULINT_UNDEFINED;
 
4127
        ulint           ret             = DB_SUCCESS;
 
4128
        ulint           old_isolation_level;
 
4129
 
 
4130
        if (table->ibd_file_missing) {
 
4131
                ut_print_timestamp(stderr);
 
4132
                fprintf(stderr, "  InnoDB: Error:\n"
 
4133
                        "InnoDB: MySQL is trying to use a table handle"
 
4134
                        " but the .ibd file for\n"
 
4135
                        "InnoDB: table %s does not exist.\n"
 
4136
                        "InnoDB: Have you deleted the .ibd file"
 
4137
                        " from the database directory under\n"
 
4138
                        "InnoDB: the MySQL datadir, or have you"
 
4139
                        " used DISCARD TABLESPACE?\n"
 
4140
                        "InnoDB: Look from\n"
 
4141
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
 
4142
                        "InnoDB: how you can resolve the problem.\n",
 
4143
                        table->name);
 
4144
                return(DB_ERROR);
 
4145
        }
 
4146
 
 
4147
        prebuilt->trx->op_info = "checking table";
 
4148
 
 
4149
        old_isolation_level = prebuilt->trx->isolation_level;
 
4150
 
 
4151
        /* We must run the index record counts at an isolation level
 
4152
        >= READ COMMITTED, because a dirty read can see a wrong number
 
4153
        of records in some index; to play safe, we use always
 
4154
        REPEATABLE READ here */
 
4155
 
 
4156
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
 
4157
 
 
4158
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
 
4159
        mutex_enter(&kernel_mutex);
 
4160
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
 
4161
        mutex_exit(&kernel_mutex);
 
4162
 
 
4163
        index = dict_table_get_first_index(table);
 
4164
 
 
4165
        while (index != NULL) {
 
4166
                /* fputs("Validating index ", stderr);
 
4167
                ut_print_name(stderr, trx, FALSE, index->name);
 
4168
                putc('\n', stderr); */
 
4169
 
 
4170
                if (!btr_validate_index(index, prebuilt->trx)) {
 
4171
                        ret = DB_ERROR;
 
4172
                } else {
 
4173
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
 
4174
                                ret = DB_ERROR;
 
4175
                        }
 
4176
 
 
4177
                        if (trx_is_interrupted(prebuilt->trx)) {
 
4178
                                break;
 
4179
                        }
 
4180
 
 
4181
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
 
4182
                        index->name); */
 
4183
 
 
4184
                        if (index == dict_table_get_first_index(table)) {
 
4185
                                n_rows_in_table = n_rows;
 
4186
                        } else if (n_rows != n_rows_in_table) {
 
4187
 
 
4188
                                ret = DB_ERROR;
 
4189
 
 
4190
                                fputs("Error: ", stderr);
 
4191
                                dict_index_name_print(stderr,
 
4192
                                                      prebuilt->trx, index);
 
4193
                                fprintf(stderr,
 
4194
                                        " contains %lu entries,"
 
4195
                                        " should be %lu\n",
 
4196
                                        (ulong) n_rows,
 
4197
                                        (ulong) n_rows_in_table);
 
4198
                        }
 
4199
                }
 
4200
 
 
4201
                index = dict_table_get_next_index(index);
 
4202
        }
 
4203
 
 
4204
        /* Restore the original isolation level */
 
4205
        prebuilt->trx->isolation_level = old_isolation_level;
 
4206
 
 
4207
        /* We validate also the whole adaptive hash index for all tables
 
4208
        at every CHECK TABLE */
 
4209
 
 
4210
        if (!btr_search_validate()) {
 
4211
 
 
4212
                ret = DB_ERROR;
 
4213
        }
 
4214
 
 
4215
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
 
4216
        mutex_enter(&kernel_mutex);
 
4217
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
4218
        mutex_exit(&kernel_mutex);
 
4219
 
 
4220
        prebuilt->trx->op_info = "";
 
4221
 
 
4222
        return(ret);
 
4223
}
 
4224
 
 
4225
/*********************************************************************//**
4210
4226
Determines if a table is a magic monitor table.
4211
4227
@return TRUE if monitor table */
4212
4228
UNIV_INTERN