~ubuntu-branches/ubuntu/lucid/mysql-dfsg-5.1/lucid-security

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/row/row0mysql.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 22:33:55 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20120222223355-or06x1euyk8n0ldi
Tags: 5.1.61-0ubuntu0.10.04.1
* SECURITY UPDATE: Update to 5.1.61 to fix multiple security issues
  (LP: #937869)
  - http://www.oracle.com/technetwork/topics/security/cpujan2012-366304.html
  - CVE-2011-2262
  - CVE-2012-0075
  - CVE-2012-0112
  - CVE-2012-0113
  - CVE-2012-0114
  - CVE-2012-0115
  - CVE-2012-0116
  - CVE-2012-0117
  - CVE-2012-0118
  - CVE-2012-0119
  - CVE-2012-0120
  - CVE-2012-0484
  - CVE-2012-0485
  - CVE-2012-0486
  - CVE-2012-0487
  - CVE-2012-0488
  - CVE-2012-0489
  - CVE-2012-0490
  - CVE-2012-0491
  - CVE-2012-0492
  - CVE-2012-0493
  - CVE-2012-0494
  - CVE-2012-0495
  - CVE-2012-0496
* Dropped patches unnecessary with 5.1.61:
  - debian/patches/90_mysql_safer_strmov.dpatch
  - debian/patches/51_ssl_test_certs.dpatch
  - debian/patches/52_CVE-2009-4030.dpatch
  - debian/patches/53_CVE-2009-4484.dpatch
  - debian/patches/54_CVE-2008-7247.dpatch
  - debian/patches/55_CVE-2010-1621.dpatch
  - debian/patches/56_CVE-2010-1850.dpatch
  - debian/patches/57_CVE-2010-1849.dpatch
  - debian/patches/58_CVE-2010-1848.dpatch
  - debian/patches/59_CVE-2010-1626.dpatch
  - debian/patches/60_CVE-2010-2008.dpatch
  - debian/patches/60_CVE-2010-3677.dpatch
  - debian/patches/60_CVE-2010-3678.dpatch
  - debian/patches/60_CVE-2010-3679.dpatch
  - debian/patches/60_CVE-2010-3680.dpatch
  - debian/patches/60_CVE-2010-3681.dpatch
  - debian/patches/60_CVE-2010-3682.dpatch
  - debian/patches/60_CVE-2010-3683.dpatch
  - debian/patches/60_CVE-2010-3833.dpatch
  - debian/patches/60_CVE-2010-3834.dpatch
  - debian/patches/60_CVE-2010-3835.dpatch
  - debian/patches/60_CVE-2010-3836.dpatch
  - debian/patches/60_CVE-2010-3837.dpatch
  - debian/patches/60_CVE-2010-3838.dpatch
  - debian/patches/60_CVE-2010-3839.dpatch
  - debian/patches/60_CVE-2010-3840.dpatch
  - debian/patches/61_disable_longfilename_test.dpatch
  - debian/patches/62_alter_table_fix.dpatch
  - debian/patches/63_cherrypick-upstream-49479.dpatch
  - debian/patches/10_readline_build_fix.dpatch
* debian/mysql-client-5.1.docs: removed EXCEPTIONS-CLIENT file
* debian/mysql-server-5.1.docs,debian/libmysqlclient16.docs,
  debian/libmysqlclient-dev.docs: removed, no longer necessary.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 2000, 2009, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 2000, 2011, Oracle and/or its affiliates. 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
444
444
                                        row is used, as row may contain
445
445
                                        pointers to this record! */
446
446
{
447
 
        mysql_row_templ_t*      templ;
 
447
        const mysql_row_templ_t*templ;
448
448
        dfield_t*               dfield;
449
449
        ulint                   i;
450
450
 
485
485
/****************************************************************//**
486
486
Handles user errors and lock waits detected by the database engine.
487
487
@return TRUE if it was a lock wait and we should continue running the
488
 
query thread */
 
488
query thread and in that case the thr is ALREADY in the running state. */
489
489
UNIV_INTERN
490
490
ibool
491
491
row_mysql_handle_errors(
522
522
        case DB_CANNOT_ADD_CONSTRAINT:
523
523
        case DB_TOO_MANY_CONCURRENT_TRXS:
524
524
        case DB_OUT_OF_FILE_SPACE:
 
525
        case DB_INTERRUPTED:
525
526
                if (savept) {
526
527
                        /* Roll back the latest, possibly incomplete
527
528
                        insertion or update */
572
573
                      "InnoDB: If the mysqld server crashes"
573
574
                      " after the startup or when\n"
574
575
                      "InnoDB: you dump the tables, look at\n"
575
 
                      "InnoDB: " REFMAN "forcing-recovery.html"
 
576
                      "InnoDB: " REFMAN "forcing-innodb-recovery.html"
576
577
                      " for help.\n", stderr);
577
578
                break;
 
579
        case DB_FOREIGN_EXCEED_MAX_CASCADE:
 
580
                fprintf(stderr, "InnoDB: Cannot delete/update rows with"
 
581
                        " cascading foreign key constraints that exceed max"
 
582
                        " depth of %lu\n"
 
583
                        "Please drop excessive foreign constraints"
 
584
                        " and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
 
585
                break;
578
586
        default:
579
587
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
580
588
                        (ulong) err);
624
632
 
625
633
        prebuilt->select_lock_type = LOCK_NONE;
626
634
        prebuilt->stored_select_lock_type = 99999999;
 
635
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
 
636
                         sizeof prebuilt->stored_select_lock_type);
627
637
 
628
638
        prebuilt->search_tuple = dtuple_create(
629
639
                heap, 2 * dict_table_get_n_cols(table));
861
871
        if (counter > 2000000000
862
872
            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
863
873
 
864
 
                dict_update_statistics(table);
 
874
                dict_update_statistics(table, FALSE /* update even if stats
 
875
                                                    are initialized */);
865
876
        }
866
877
}
867
878
 
1378
1389
run_again:
1379
1390
        thr->run_node = node;
1380
1391
        thr->prev_node = node;
 
1392
        thr->fk_cascade_depth = 0;
1381
1393
 
1382
1394
        row_upd_step(thr);
1383
1395
 
1384
1396
        err = trx->error_state;
1385
1397
 
 
1398
        /* Reset fk_cascade_depth back to 0 */
 
1399
        thr->fk_cascade_depth = 0;
 
1400
 
1386
1401
        if (err != DB_SUCCESS) {
1387
1402
                que_thr_stop_for_mysql(thr);
1388
1403
 
1419
1434
                srv_n_rows_updated++;
1420
1435
        }
1421
1436
 
1422
 
        row_update_statistics_if_needed(prebuilt->table);
 
1437
        /* We update table statistics only if it is a DELETE or UPDATE
 
1438
        that changes indexed columns, UPDATEs that change only non-indexed
 
1439
        columns would not affect statistics. */
 
1440
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
 
1441
                row_update_statistics_if_needed(prebuilt->table);
 
1442
        }
1423
1443
 
1424
1444
        trx->op_info = "";
1425
1445
 
1427
1447
}
1428
1448
 
1429
1449
/*********************************************************************//**
1430
 
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
1431
 
this session is using a READ COMMITTED isolation level. Before
1432
 
calling this function we must use trx_reset_new_rec_lock_info() and
1433
 
trx_register_new_rec_lock() to store the information which new record locks
1434
 
really were set. This function removes a newly set lock under prebuilt->pcur,
1435
 
and also under prebuilt->clust_pcur. Currently, this is only used and tested
1436
 
in the case of an UPDATE or a DELETE statement, where the row lock is of the
1437
 
LOCK_X type.
1438
 
Thus, this implements a 'mini-rollback' that releases the latest record
1439
 
locks we set.
1440
 
@return error code or DB_SUCCESS */
 
1450
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
 
1451
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
 
1452
Before calling this function row_search_for_mysql() must have
 
1453
initialized prebuilt->new_rec_locks to store the information which new
 
1454
record locks really were set. This function removes a newly set
 
1455
clustered index record lock under prebuilt->pcur or
 
1456
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
 
1457
releases the latest clustered index record lock we set.
 
1458
@return error code or DB_SUCCESS */
1441
1459
UNIV_INTERN
1442
1460
int
1443
1461
row_unlock_for_mysql(
1444
1462
/*=================*/
1445
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
 
1463
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
1446
1464
                                        handle */
1447
 
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
1448
 
                                        the latches on the records under pcur
1449
 
                                        and clust_pcur, and we do not need to
1450
 
                                        reposition the cursors. */
 
1465
        ibool           has_latches_on_recs)/*!< in: TRUE if called so
 
1466
                                        that we have the latches on
 
1467
                                        the records under pcur and
 
1468
                                        clust_pcur, and we do not need
 
1469
                                        to reposition the cursors. */
1451
1470
{
1452
1471
        btr_pcur_t*     pcur            = prebuilt->pcur;
1453
1472
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1458
1477
 
1459
1478
        if (UNIV_UNLIKELY
1460
1479
            (!srv_locks_unsafe_for_binlog
1461
 
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
 
1480
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
1462
1481
 
1463
1482
                fprintf(stderr,
1464
1483
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1574
1593
        trx_t*  trx;
1575
1594
 
1576
1595
        trx = thr_get_trx(thr);
 
1596
 
 
1597
        /* Increment fk_cascade_depth to record the recursive call depth on
 
1598
        a single update/delete that affects multiple tables chained
 
1599
        together with foreign key relations. */
 
1600
        thr->fk_cascade_depth++;
 
1601
 
 
1602
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
 
1603
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
 
1604
        }
1577
1605
run_again:
1578
1606
        thr->run_node = node;
1579
1607
        thr->prev_node = node;
1580
1608
 
1581
1609
        row_upd_step(thr);
1582
1610
 
 
1611
        /* The recursive call for cascading update/delete happens
 
1612
        in above row_upd_step(), reset the counter once we come
 
1613
        out of the recursive call, so it does not accumulate for
 
1614
        different row deletes */
 
1615
        thr->fk_cascade_depth = 0;
 
1616
 
1583
1617
        err = trx->error_state;
1584
1618
 
1585
1619
        /* Note that the cascade node is a subnode of another InnoDB
1645
1679
}
1646
1680
 
1647
1681
/*********************************************************************//**
1648
 
Calculates the key number used inside MySQL for an Innobase index. We have
1649
 
to take into account if we generated a default clustered index for the table
1650
 
@return the key number used inside MySQL */
1651
 
UNIV_INTERN
1652
 
ulint
1653
 
row_get_mysql_key_number_for_index(
1654
 
/*===============================*/
1655
 
        const dict_index_t*     index)  /*!< in: index */
1656
 
{
1657
 
        const dict_index_t*     ind;
1658
 
        ulint                   i;
1659
 
 
1660
 
        ut_a(index);
1661
 
 
1662
 
        i = 0;
1663
 
        ind = dict_table_get_first_index(index->table);
1664
 
 
1665
 
        while (index != ind) {
1666
 
                ind = dict_table_get_next_index(ind);
1667
 
                i++;
1668
 
        }
1669
 
 
1670
 
        if (row_table_got_default_clust_index(index->table)) {
1671
 
                ut_a(i > 0);
1672
 
                i--;
1673
 
        }
1674
 
 
1675
 
        return(i);
1676
 
}
1677
 
 
1678
 
/*********************************************************************//**
1679
1682
Locks the data dictionary in shared mode from modifications, for performing
1680
1683
foreign key check, rollback, or other operation invisible to MySQL. */
1681
1684
UNIV_INTERN
1877
1880
 
1878
1881
        err = trx->error_state;
1879
1882
 
1880
 
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 
1883
        switch (err) {
 
1884
        case DB_SUCCESS:
 
1885
                break;
 
1886
        case DB_OUT_OF_FILE_SPACE:
1881
1887
                trx->error_state = DB_SUCCESS;
1882
1888
                trx_general_rollback_for_mysql(trx, NULL);
1883
 
        }
1884
1889
 
1885
 
        switch (err) {
1886
 
        case DB_OUT_OF_FILE_SPACE:
1887
1890
                ut_print_timestamp(stderr);
1888
1891
                fputs("  InnoDB: Warning: cannot create table ",
1889
1892
                      stderr);
1898
1901
                break;
1899
1902
 
1900
1903
        case DB_DUPLICATE_KEY:
1901
 
                ut_print_timestamp(stderr);
1902
 
                fputs("  InnoDB: Error: table ", stderr);
1903
 
                ut_print_name(stderr, trx, TRUE, table->name);
1904
 
                fputs(" already exists in InnoDB internal\n"
1905
 
                      "InnoDB: data dictionary. Have you deleted"
1906
 
                      " the .frm file\n"
1907
 
                      "InnoDB: and not used DROP TABLE?"
1908
 
                      " Have you used DROP DATABASE\n"
1909
 
                      "InnoDB: for InnoDB tables in"
1910
 
                      " MySQL version <= 3.23.43?\n"
1911
 
                      "InnoDB: See the Restrictions section"
1912
 
                      " of the InnoDB manual.\n"
1913
 
                      "InnoDB: You can drop the orphaned table"
1914
 
                      " inside InnoDB by\n"
1915
 
                      "InnoDB: creating an InnoDB table with"
1916
 
                      " the same name in another\n"
1917
 
                      "InnoDB: database and copying the .frm file"
1918
 
                      " to the current database.\n"
1919
 
                      "InnoDB: Then MySQL thinks the table exists,"
1920
 
                      " and DROP TABLE will\n"
1921
 
                      "InnoDB: succeed.\n"
1922
 
                      "InnoDB: You can look for further help from\n"
1923
 
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
1924
 
                      stderr);
1925
 
 
 
1904
        default:
1926
1905
                /* We may also get err == DB_ERROR if the .ibd file for the
1927
1906
                table already exists */
1928
1907
 
 
1908
                trx->error_state = DB_SUCCESS;
 
1909
                trx_general_rollback_for_mysql(trx, NULL);
 
1910
                dict_mem_table_free(table);
1929
1911
                break;
1930
1912
        }
1931
1913
 
2082
2064
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2083
2065
                                        table2 can be written also with the
2084
2066
                                        database name before it: test.table2 */
 
2067
        size_t          sql_length,     /*!< in: length of sql_string */
2085
2068
        const char*     name,           /*!< in: table full name in the
2086
2069
                                        normalized form
2087
2070
                                        database_name/table_name */
2103
2086
 
2104
2087
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2105
2088
 
2106
 
        err = dict_create_foreign_constraints(trx, sql_string, name,
2107
 
                                              reject_fks);
 
2089
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
 
2090
                                              name, reject_fks);
2108
2091
        if (err == DB_SUCCESS) {
2109
2092
                /* Check that also referencing constraints are ok */
2110
 
                err = dict_load_foreigns(name, TRUE);
 
2093
                err = dict_load_foreigns(name, FALSE, TRUE);
2111
2094
        }
2112
2095
 
2113
2096
        if (err != DB_SUCCESS) {
2448
2431
                goto funct_exit;
2449
2432
        }
2450
2433
 
2451
 
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
 
2434
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2452
2435
 
2453
2436
        /* Remove all locks except the table-level S and X locks. */
2454
2437
        lock_remove_all_on_table(table, FALSE);
2810
2793
 
2811
2794
                        dict_index_t*   index;
2812
2795
 
2813
 
                        space = 0;
2814
 
 
2815
 
                        if (fil_create_new_single_table_tablespace(
2816
 
                                    &space, table->name, FALSE, flags,
 
2796
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2797
 
 
2798
                        /* Lock all index trees for this table. We must
 
2799
                        do so after dict_hdr_get_new_id() to preserve
 
2800
                        the latch order */
 
2801
                        dict_table_x_lock_indexes(table);
 
2802
 
 
2803
                        if (space == ULINT_UNDEFINED
 
2804
                            || fil_create_new_single_table_tablespace(
 
2805
                                    space, table->name, FALSE, flags,
2817
2806
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
 
2807
                                dict_table_x_unlock_indexes(table);
2818
2808
                                ut_print_timestamp(stderr);
2819
2809
                                fprintf(stderr,
2820
2810
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2843
2833
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2844
2834
                        mtr_commit(&mtr);
2845
2835
                }
 
2836
        } else {
 
2837
                /* Lock all index trees for this table, as we will
 
2838
                truncate the table/index and possibly change their metadata.
 
2839
                All DML/DDL are blocked by table level lock, with
 
2840
                a few exceptions such as queries into information schema
 
2841
                about the table, MySQL could try to access index stats
 
2842
                for this kind of query, we need to use index locks to
 
2843
                sync up */
 
2844
                dict_table_x_lock_indexes(table);
2846
2845
        }
2847
2846
 
2848
2847
        /* scan SYS_INDEXES for all indexes of the table */
2918
2917
 
2919
2918
        mem_heap_free(heap);
2920
2919
 
2921
 
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
 
2920
        /* Done with index truncation, release index tree locks,
 
2921
        subsequent work relates to table level metadata change */
 
2922
        dict_table_x_unlock_indexes(table);
 
2923
 
 
2924
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2922
2925
 
2923
2926
        info = pars_info_create();
2924
2927
 
2962
2965
        dict_table_autoinc_lock(table);
2963
2966
        dict_table_autoinc_initialize(table, 1);
2964
2967
        dict_table_autoinc_unlock(table);
2965
 
        dict_update_statistics(table);
 
2968
        dict_update_statistics(table, FALSE /* update even if stats are
 
2969
                                            initialized */);
2966
2970
 
2967
2971
        trx_commit_for_mysql(trx);
2968
2972
 
3217
3221
                           "index_id CHAR;\n"
3218
3222
                           "foreign_id CHAR;\n"
3219
3223
                           "found INT;\n"
 
3224
 
 
3225
                           "DECLARE CURSOR cur_fk IS\n"
 
3226
                           "SELECT ID FROM SYS_FOREIGN\n"
 
3227
                           "WHERE FOR_NAME = :table_name\n"
 
3228
                           "AND TO_BINARY(FOR_NAME)\n"
 
3229
                           "  = TO_BINARY(:table_name)\n"
 
3230
                           "LOCK IN SHARE MODE;\n"
 
3231
 
 
3232
                           "DECLARE CURSOR cur_idx IS\n"
 
3233
                           "SELECT ID FROM SYS_INDEXES\n"
 
3234
                           "WHERE TABLE_ID = table_id\n"
 
3235
                           "LOCK IN SHARE MODE;\n"
 
3236
 
3220
3237
                           "BEGIN\n"
3221
3238
                           "SELECT ID INTO table_id\n"
3222
3239
                           "FROM SYS_TABLES\n"
3239
3256
                           "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n"
3240
3257
                           "       found := 0;\n"
3241
3258
                           "END IF;\n"
 
3259
                           "OPEN cur_fk;\n"
3242
3260
                           "WHILE found = 1 LOOP\n"
3243
 
                           "       SELECT ID INTO foreign_id\n"
3244
 
                           "       FROM SYS_FOREIGN\n"
3245
 
                           "       WHERE FOR_NAME = :table_name\n"
3246
 
                           "               AND TO_BINARY(FOR_NAME)\n"
3247
 
                           "                 = TO_BINARY(:table_name)\n"
3248
 
                           "               LOCK IN SHARE MODE;\n"
 
3261
                           "       FETCH cur_fk INTO foreign_id;\n"
3249
3262
                           "       IF (SQL % NOTFOUND) THEN\n"
3250
3263
                           "               found := 0;\n"
3251
3264
                           "       ELSE\n"
3255
3268
                           "               WHERE ID = foreign_id;\n"
3256
3269
                           "       END IF;\n"
3257
3270
                           "END LOOP;\n"
 
3271
                           "CLOSE cur_fk;\n"
3258
3272
                           "found := 1;\n"
 
3273
                           "OPEN cur_idx;\n"
3259
3274
                           "WHILE found = 1 LOOP\n"
3260
 
                           "       SELECT ID INTO index_id\n"
3261
 
                           "       FROM SYS_INDEXES\n"
3262
 
                           "       WHERE TABLE_ID = table_id\n"
3263
 
                           "       LOCK IN SHARE MODE;\n"
 
3275
                           "       FETCH cur_idx INTO index_id;\n"
3264
3276
                           "       IF (SQL % NOTFOUND) THEN\n"
3265
3277
                           "               found := 0;\n"
3266
3278
                           "       ELSE\n"
3271
3283
                           "               AND TABLE_ID = table_id;\n"
3272
3284
                           "       END IF;\n"
3273
3285
                           "END LOOP;\n"
 
3286
                           "CLOSE cur_idx;\n"
3274
3287
                           "DELETE FROM SYS_COLUMNS\n"
3275
3288
                           "WHERE TABLE_ID = table_id;\n"
3276
3289
                           "DELETE FROM SYS_TABLES\n"
3278
3291
                           "END;\n"
3279
3292
                           , FALSE, trx);
3280
3293
 
3281
 
        if (err != DB_SUCCESS) {
3282
 
                ut_a(err == DB_OUT_OF_FILE_SPACE);
3283
 
 
3284
 
                err = DB_MUST_GET_MORE_FILE_SPACE;
3285
 
 
3286
 
                row_mysql_handle_errors(&err, trx, NULL, NULL);
3287
 
 
3288
 
                ut_error;
3289
 
        } else {
3290
 
                ibool           is_path;
 
3294
        switch (err) {
 
3295
                ibool           is_temp;
3291
3296
                const char*     name_or_path;
3292
3297
                mem_heap_t*     heap;
3293
3298
 
 
3299
        case DB_SUCCESS:
 
3300
 
3294
3301
                heap = mem_heap_create(200);
3295
3302
 
3296
3303
                /* Clone the name, in case it has been allocated
3300
3307
                space_id = table->space;
3301
3308
 
3302
3309
                if (table->dir_path_of_temp_table != NULL) {
3303
 
                        is_path = TRUE;
3304
3310
                        name_or_path = mem_heap_strdup(
3305
3311
                                heap, table->dir_path_of_temp_table);
 
3312
                        is_temp = TRUE;
3306
3313
                } else {
3307
 
                        is_path = FALSE;
3308
3314
                        name_or_path = name;
 
3315
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
 
3316
                                & DICT_TF2_TEMPORARY;
3309
3317
                }
3310
3318
 
3311
3319
                dict_table_remove_from_cache(table);
3325
3333
                if (err == DB_SUCCESS && space_id > 0) {
3326
3334
                        if (!fil_space_for_table_exists_in_mem(space_id,
3327
3335
                                                               name_or_path,
3328
 
                                                               is_path,
3329
 
                                                               FALSE, TRUE)) {
 
3336
                                                               is_temp, FALSE,
 
3337
                                                               !is_temp)) {
3330
3338
                                err = DB_SUCCESS;
3331
3339
 
3332
3340
                                fprintf(stderr,
3355
3363
                }
3356
3364
 
3357
3365
                mem_heap_free(heap);
 
3366
                break;
 
3367
 
 
3368
        case DB_TOO_MANY_CONCURRENT_TRXS:
 
3369
                /* Cannot even find a free slot for the
 
3370
                the undo log. We can directly exit here
 
3371
                and return the DB_TOO_MANY_CONCURRENT_TRXS
 
3372
                error. */
 
3373
                break;
 
3374
 
 
3375
        case DB_OUT_OF_FILE_SPACE:
 
3376
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3377
 
 
3378
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3379
 
 
3380
                /* Fall through to raise error */
 
3381
 
 
3382
        default:
 
3383
                /* No other possible error returns */
 
3384
                ut_error;
3358
3385
        }
 
3386
 
3359
3387
funct_exit:
3360
3388
 
3361
3389
        if (locked_dictionary) {
3371
3399
        return((int) err);
3372
3400
}
3373
3401
 
 
3402
/*********************************************************************//**
 
3403
Drop all temporary tables during crash recovery. */
 
3404
UNIV_INTERN
 
3405
void
 
3406
row_mysql_drop_temp_tables(void)
 
3407
/*============================*/
 
3408
{
 
3409
        trx_t*          trx;
 
3410
        btr_pcur_t      pcur;
 
3411
        mtr_t           mtr;
 
3412
        mem_heap_t*     heap;
 
3413
 
 
3414
        trx = trx_allocate_for_background();
 
3415
        trx->op_info = "dropping temporary tables";
 
3416
        row_mysql_lock_data_dictionary(trx);
 
3417
 
 
3418
        heap = mem_heap_create(200);
 
3419
 
 
3420
        mtr_start(&mtr);
 
3421
 
 
3422
        btr_pcur_open_at_index_side(
 
3423
                TRUE,
 
3424
                dict_table_get_first_index(dict_sys->sys_tables),
 
3425
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
 
3426
 
 
3427
        for (;;) {
 
3428
                const rec_t*    rec;
 
3429
                const byte*     field;
 
3430
                ulint           len;
 
3431
                const char*     table_name;
 
3432
                dict_table_t*   table;
 
3433
 
 
3434
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
3435
 
 
3436
                if (!btr_pcur_is_on_user_rec(&pcur)) {
 
3437
                        break;
 
3438
                }
 
3439
 
 
3440
                rec = btr_pcur_get_rec(&pcur);
 
3441
                field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
 
3442
                if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
 
3443
                        continue;
 
3444
                }
 
3445
 
 
3446
                /* Because this is not a ROW_FORMAT=REDUNDANT table,
 
3447
                the is_temp flag is valid.  Examine it. */
 
3448
 
 
3449
                field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
 
3450
                if (len != 4
 
3451
                    || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
 
3452
                        continue;
 
3453
                }
 
3454
 
 
3455
                /* This is a temporary table. */
 
3456
                field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
 
3457
                if (len == UNIV_SQL_NULL || len == 0) {
 
3458
                        /* Corrupted SYS_TABLES.NAME */
 
3459
                        continue;
 
3460
                }
 
3461
 
 
3462
                table_name = mem_heap_strdupl(heap, (const char*) field, len);
 
3463
 
 
3464
                btr_pcur_store_position(&pcur, &mtr);
 
3465
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
 
3466
 
 
3467
                table = dict_load_table(table_name);
 
3468
 
 
3469
                if (table) {
 
3470
                        row_drop_table_for_mysql(table_name, trx, FALSE);
 
3471
                        trx_commit_for_mysql(trx);
 
3472
                }
 
3473
 
 
3474
                mtr_start(&mtr);
 
3475
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
3476
                                          &pcur, &mtr);
 
3477
        }
 
3478
 
 
3479
        btr_pcur_close(&pcur);
 
3480
        mtr_commit(&mtr);
 
3481
        mem_heap_free(heap);
 
3482
        row_mysql_unlock_data_dictionary(trx);
 
3483
        trx_free_for_background(trx);
 
3484
}
 
3485
 
3374
3486
/*******************************************************************//**
3375
3487
Drop all foreign keys in a database, see Bug#18942.
3376
3488
Called at the end of row_drop_database_for_mysql().
3859
3971
                        trx->error_state = DB_SUCCESS;
3860
3972
                        trx_general_rollback_for_mysql(trx, NULL);
3861
3973
                        trx->error_state = DB_SUCCESS;
 
3974
                        err = DB_ERROR;
3862
3975
                        goto funct_exit;
3863
3976
                }
3864
3977
 
3866
3979
                an ALTER, not in a RENAME. */
3867
3980
 
3868
3981
                err = dict_load_foreigns(
3869
 
                        new_name, !old_is_tmp || trx->check_foreigns);
 
3982
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
3870
3983
 
3871
3984
                if (err != DB_SUCCESS) {
3872
3985
                        ut_print_timestamp(stderr);
3922
4035
constraint is not broken, and calculates the number of index entries
3923
4036
in the read view of the current transaction.
3924
4037
@return TRUE if ok */
3925
 
static
 
4038
UNIV_INTERN
3926
4039
ibool
3927
 
row_scan_and_check_index(
3928
 
/*=====================*/
3929
 
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
3930
 
        dict_index_t*   index,          /*!< in: index */
3931
 
        ulint*          n_rows)         /*!< out: number of entries seen in the
3932
 
                                        current consistent read */
 
4040
row_check_index_for_mysql(
 
4041
/*======================*/
 
4042
        row_prebuilt_t*         prebuilt,       /*!< in: prebuilt struct
 
4043
                                                in MySQL handle */
 
4044
        const dict_index_t*     index,          /*!< in: index */
 
4045
        ulint*                  n_rows)         /*!< out: number of entries
 
4046
                                                seen in the consistent read */
3933
4047
{
3934
4048
        dtuple_t*       prev_entry      = NULL;
3935
4049
        ulint           matched_fields;
3950
4064
 
3951
4065
        *n_rows = 0;
3952
4066
 
3953
 
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
3954
 
                /* A newly created index may lack some delete-marked
3955
 
                records that may exist in the read view of
3956
 
                prebuilt->trx.  Thus, such indexes must not be
3957
 
                accessed by consistent read. */
3958
 
                return(is_ok);
3959
 
        }
3960
 
 
3961
4067
        buf = mem_alloc(UNIV_PAGE_SIZE);
3962
4068
        heap = mem_heap_create(100);
3963
4069
 
3964
 
        /* Make a dummy template in prebuilt, which we will use
3965
 
        in scanning the index entries */
3966
 
 
3967
 
        prebuilt->index = index;
3968
 
        /* row_merge_is_index_usable() was already checked above. */
3969
 
        prebuilt->index_usable = TRUE;
3970
 
        prebuilt->sql_stat_start = TRUE;
3971
 
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
3972
 
        prebuilt->n_template = 0;
3973
 
        prebuilt->need_to_access_clustered = FALSE;
3974
 
 
3975
 
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
3976
 
 
3977
 
        prebuilt->select_lock_type = LOCK_NONE;
3978
4070
        cnt = 1000;
3979
4071
 
3980
4072
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4093
4185
}
4094
4186
 
4095
4187
/*********************************************************************//**
4096
 
Checks a table for corruption.
4097
 
@return DB_ERROR or DB_SUCCESS */
4098
 
UNIV_INTERN
4099
 
ulint
4100
 
row_check_table_for_mysql(
4101
 
/*======================*/
4102
 
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
4103
 
                                        handle */
4104
 
{
4105
 
        dict_table_t*   table           = prebuilt->table;
4106
 
        dict_index_t*   index;
4107
 
        ulint           n_rows;
4108
 
        ulint           n_rows_in_table = ULINT_UNDEFINED;
4109
 
        ulint           ret             = DB_SUCCESS;
4110
 
        ulint           old_isolation_level;
4111
 
 
4112
 
        if (table->ibd_file_missing) {
4113
 
                ut_print_timestamp(stderr);
4114
 
                fprintf(stderr, "  InnoDB: Error:\n"
4115
 
                        "InnoDB: MySQL is trying to use a table handle"
4116
 
                        " but the .ibd file for\n"
4117
 
                        "InnoDB: table %s does not exist.\n"
4118
 
                        "InnoDB: Have you deleted the .ibd file"
4119
 
                        " from the database directory under\n"
4120
 
                        "InnoDB: the MySQL datadir, or have you"
4121
 
                        " used DISCARD TABLESPACE?\n"
4122
 
                        "InnoDB: Look from\n"
4123
 
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
4124
 
                        "InnoDB: how you can resolve the problem.\n",
4125
 
                        table->name);
4126
 
                return(DB_ERROR);
4127
 
        }
4128
 
 
4129
 
        prebuilt->trx->op_info = "checking table";
4130
 
 
4131
 
        old_isolation_level = prebuilt->trx->isolation_level;
4132
 
 
4133
 
        /* We must run the index record counts at an isolation level
4134
 
        >= READ COMMITTED, because a dirty read can see a wrong number
4135
 
        of records in some index; to play safe, we use always
4136
 
        REPEATABLE READ here */
4137
 
 
4138
 
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
4139
 
 
4140
 
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
4141
 
        mutex_enter(&kernel_mutex);
4142
 
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
4143
 
        mutex_exit(&kernel_mutex);
4144
 
 
4145
 
        index = dict_table_get_first_index(table);
4146
 
 
4147
 
        while (index != NULL) {
4148
 
                /* fputs("Validating index ", stderr);
4149
 
                ut_print_name(stderr, trx, FALSE, index->name);
4150
 
                putc('\n', stderr); */
4151
 
 
4152
 
                if (!btr_validate_index(index, prebuilt->trx)) {
4153
 
                        ret = DB_ERROR;
4154
 
                } else {
4155
 
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
4156
 
                                ret = DB_ERROR;
4157
 
                        }
4158
 
 
4159
 
                        if (trx_is_interrupted(prebuilt->trx)) {
4160
 
                                break;
4161
 
                        }
4162
 
 
4163
 
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
4164
 
                        index->name); */
4165
 
 
4166
 
                        if (index == dict_table_get_first_index(table)) {
4167
 
                                n_rows_in_table = n_rows;
4168
 
                        } else if (n_rows != n_rows_in_table) {
4169
 
 
4170
 
                                ret = DB_ERROR;
4171
 
 
4172
 
                                fputs("Error: ", stderr);
4173
 
                                dict_index_name_print(stderr,
4174
 
                                                      prebuilt->trx, index);
4175
 
                                fprintf(stderr,
4176
 
                                        " contains %lu entries,"
4177
 
                                        " should be %lu\n",
4178
 
                                        (ulong) n_rows,
4179
 
                                        (ulong) n_rows_in_table);
4180
 
                        }
4181
 
                }
4182
 
 
4183
 
                index = dict_table_get_next_index(index);
4184
 
        }
4185
 
 
4186
 
        /* Restore the original isolation level */
4187
 
        prebuilt->trx->isolation_level = old_isolation_level;
4188
 
 
4189
 
        /* We validate also the whole adaptive hash index for all tables
4190
 
        at every CHECK TABLE */
4191
 
 
4192
 
        if (!btr_search_validate()) {
4193
 
 
4194
 
                ret = DB_ERROR;
4195
 
        }
4196
 
 
4197
 
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
4198
 
        mutex_enter(&kernel_mutex);
4199
 
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
4200
 
        mutex_exit(&kernel_mutex);
4201
 
 
4202
 
        prebuilt->trx->op_info = "";
4203
 
 
4204
 
        return(ret);
4205
 
}
4206
 
 
4207
 
/*********************************************************************//**
4208
4188
Determines if a table is a magic monitor table.
4209
4189
@return TRUE if monitor table */
4210
4190
UNIV_INTERN