~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-09-28 07:45:44 UTC
  • mto: (1799.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1800.
  • Revision ID: mordred@inaugust.com-20100928074544-s3ujnv6s8wro74l2
Added BSD copying 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
 
249
249
}
250
250
 
251
251
/**************************************************************//**
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
252
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
296
253
The counterpart of this function is row_sel_field_store_in_mysql_format() in
297
254
row0sel.c.
383
340
                        /* Remove trailing spaces from old style VARCHAR
384
341
                        columns. */
385
342
 
386
 
                        /* Handle Unicode strings differently. */
 
343
                        /* Handle UCS2 strings differently. */
387
344
                        ulint   mbminlen        = dtype_get_mbminlen(dtype);
388
345
 
389
346
                        ptr = mysql_data;
390
347
 
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:
 
348
                        if (mbminlen == 2) {
408
349
                                /* space=0x0020 */
409
350
                                /* Trim "half-chars", just in case. */
410
351
                                col_len &= ~1;
413
354
                                       && ptr[col_len - 1] == 0x20) {
414
355
                                        col_len -= 2;
415
356
                                }
416
 
                                break;
417
 
                        case 1:
 
357
                        } else {
 
358
                                ut_a(mbminlen == 1);
418
359
                                /* space=0x20 */
419
360
                                while (col_len > 0
420
361
                                       && ptr[col_len - 1] == 0x20) {
527
468
/****************************************************************//**
528
469
Handles user errors and lock waits detected by the database engine.
529
470
@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. */
 
471
query thread */
531
472
UNIV_INTERN
532
473
ibool
533
474
row_mysql_handle_errors(
552
493
        switch (err) {
553
494
        case DB_LOCK_WAIT_TIMEOUT:
554
495
                if (row_rollback_on_timeout) {
555
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
496
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
556
497
                        break;
557
498
                }
558
499
                /* fall through */
564
505
        case DB_CANNOT_ADD_CONSTRAINT:
565
506
        case DB_TOO_MANY_CONCURRENT_TRXS:
566
507
        case DB_OUT_OF_FILE_SPACE:
567
 
        case DB_INTERRUPTED:
568
508
                if (savept) {
569
509
                        /* Roll back the latest, possibly incomplete
570
510
                        insertion or update */
571
511
 
572
 
                        trx_general_rollback_for_mysql(trx, savept);
 
512
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
573
513
                }
574
514
                /* MySQL will roll back the latest SQL statement */
575
515
                break;
591
531
                /* Roll back the whole transaction; this resolution was added
592
532
                to version 3.23.43 */
593
533
 
594
 
                trx_general_rollback_for_mysql(trx, NULL);
 
534
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
595
535
                break;
596
536
 
597
537
        case DB_MUST_GET_MORE_FILE_SPACE:
618
558
                      "InnoDB: " REFMAN "forcing-recovery.html"
619
559
                      " for help.\n", stderr);
620
560
                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
561
        default:
629
562
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
630
563
                        (ulong) err);
674
607
 
675
608
        prebuilt->select_lock_type = LOCK_NONE;
676
609
        prebuilt->stored_select_lock_type = 99999999;
677
 
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
678
 
                         sizeof prebuilt->stored_select_lock_type);
679
610
 
680
611
        prebuilt->search_tuple = dtuple_create(
681
612
                heap, 2 * dict_table_get_n_cols(table));
840
771
        }
841
772
}
842
773
 
843
 
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
844
 
 
845
774
/*********************************************************************//**
846
775
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
847
776
has not yet been built in the prebuilt struct, then this function first
848
777
builds it.
849
778
@return prebuilt dtuple; the column type information is also set in it */
 
779
static
850
780
dtuple_t*
851
781
row_get_prebuilt_insert_row(
852
782
/*========================*/
919
849
}
920
850
 
921
851
/*********************************************************************//**
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). */
 
852
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
925
853
UNIV_INTERN
926
854
void
927
855
row_unlock_table_autoinc_for_mysql(
928
856
/*===============================*/
929
857
        trx_t*  trx)    /*!< in/out: transaction */
930
858
{
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
 
        }
 
859
        mutex_enter(&kernel_mutex);
 
860
 
 
861
        lock_release_autoinc_locks(trx);
 
862
 
 
863
        mutex_exit(&kernel_mutex);
938
864
}
939
865
 
940
866
/*********************************************************************//**
1431
1357
run_again:
1432
1358
        thr->run_node = node;
1433
1359
        thr->prev_node = node;
1434
 
        thr->fk_cascade_depth = 0;
1435
1360
 
1436
1361
        row_upd_step(thr);
1437
1362
 
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
1363
        err = trx->error_state;
1445
1364
 
1446
 
        /* Reset fk_cascade_depth back to 0 */
1447
 
        thr->fk_cascade_depth = 0;
1448
 
 
1449
1365
        if (err != DB_SUCCESS) {
1450
1366
                que_thr_stop_for_mysql(thr);
1451
1367
 
1482
1398
                srv_n_rows_updated++;
1483
1399
        }
1484
1400
 
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
 
        }
 
1401
        row_update_statistics_if_needed(prebuilt->table);
1491
1402
 
1492
1403
        trx->op_info = "";
1493
1404
 
1495
1406
}
1496
1407
 
1497
1408
/*********************************************************************//**
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 */
 
1409
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
 
1410
this session is using a READ COMMITTED isolation level. Before
 
1411
calling this function we must use trx_reset_new_rec_lock_info() and
 
1412
trx_register_new_rec_lock() to store the information which new record locks
 
1413
really were set. This function removes a newly set lock under prebuilt->pcur,
 
1414
and also under prebuilt->clust_pcur. Currently, this is only used and tested
 
1415
in the case of an UPDATE or a DELETE statement, where the row lock is of the
 
1416
LOCK_X type.
 
1417
Thus, this implements a 'mini-rollback' that releases the latest record
 
1418
locks we set.
 
1419
@return error code or DB_SUCCESS */
1507
1420
UNIV_INTERN
1508
1421
int
1509
1422
row_unlock_for_mysql(
1510
1423
/*=================*/
1511
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1424
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1512
1425
                                        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. */
 
1426
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
 
1427
                                        the latches on the records under pcur
 
1428
                                        and clust_pcur, and we do not need to
 
1429
                                        reposition the cursors. */
1518
1430
{
1519
1431
        btr_pcur_t*     pcur            = prebuilt->pcur;
1520
1432
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1525
1437
 
1526
1438
        if (UNIV_UNLIKELY
1527
1439
            (!srv_locks_unsafe_for_binlog
1528
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1440
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1529
1441
 
1530
1442
                fprintf(stderr,
1531
1443
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1597
1509
                        }
1598
1510
                }
1599
1511
 
1600
 
                if (rec_trx_id != trx->id) {
 
1512
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1601
1513
                        /* We did not update the record: unlock it */
1602
1514
 
1603
1515
                        rec = btr_pcur_get_rec(pcur);
1641
1553
        trx_t*  trx;
1642
1554
 
1643
1555
        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
1556
run_again:
1654
1557
        thr->run_node = node;
1655
1558
        thr->prev_node = node;
1656
1559
 
1657
1560
        row_upd_step(thr);
1658
1561
 
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
1562
        err = trx->error_state;
1666
1563
 
1667
1564
        /* Note that the cascade node is a subnode of another InnoDB
1727
1624
}
1728
1625
 
1729
1626
/*********************************************************************//**
 
1627
Calculates the key number used inside MySQL for an Innobase index. We have
 
1628
to take into account if we generated a default clustered index for the table
 
1629
@return the key number used inside MySQL */
 
1630
UNIV_INTERN
 
1631
ulint
 
1632
row_get_mysql_key_number_for_index(
 
1633
/*===============================*/
 
1634
        const dict_index_t*     index)  /*!< in: index */
 
1635
{
 
1636
        const dict_index_t*     ind;
 
1637
        ulint                   i;
 
1638
 
 
1639
        ut_a(index);
 
1640
 
 
1641
        i = 0;
 
1642
        ind = dict_table_get_first_index(index->table);
 
1643
 
 
1644
        while (index != ind) {
 
1645
                ind = dict_table_get_next_index(ind);
 
1646
                i++;
 
1647
        }
 
1648
 
 
1649
        if (row_table_got_default_clust_index(index->table)) {
 
1650
                ut_a(i > 0);
 
1651
                i--;
 
1652
        }
 
1653
 
 
1654
        return(i);
 
1655
}
 
1656
 
 
1657
/*********************************************************************//**
1730
1658
Locks the data dictionary in shared mode from modifications, for performing
1731
1659
foreign key check, rollback, or other operation invisible to MySQL. */
1732
1660
UNIV_INTERN
1822
1750
        const char*     table_name;
1823
1751
        ulint           table_name_len;
1824
1752
        ulint           err;
 
1753
        ulint           i;
1825
1754
 
1826
1755
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1827
1756
#ifdef UNIV_SYNC_DEBUG
1836
1765
                      " by the user.\n"
1837
1766
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1838
1767
                      " is replaced with raw.\n", stderr);
 
1768
err_exit:
1839
1769
                dict_mem_table_free(table);
1840
1770
                trx_commit_for_mysql(trx);
1841
1771
 
1844
1774
 
1845
1775
        trx->op_info = "creating table";
1846
1776
 
 
1777
        /* Check that no reserved column names are used. */
 
1778
        for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
 
1779
                if (dict_col_name_is_reserved(
 
1780
                            dict_table_get_col_name(table, i))) {
 
1781
 
 
1782
                        goto err_exit;
 
1783
                }
 
1784
        }
 
1785
 
1847
1786
        trx_start_if_not_started(trx);
1848
1787
 
1849
1788
        /* The table name is prefixed with the database name and a '/'.
1918
1857
 
1919
1858
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1920
1859
                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. */
 
1860
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1924
1861
        }
1925
1862
 
1926
1863
        switch (err) {
1939
1876
                break;
1940
1877
 
1941
1878
        case DB_DUPLICATE_KEY:
 
1879
                ut_print_timestamp(stderr);
 
1880
                fputs("  InnoDB: Error: table ", stderr);
 
1881
                ut_print_name(stderr, trx, TRUE, table->name);
 
1882
                fputs(" already exists in InnoDB internal\n"
 
1883
                      "InnoDB: data dictionary. Have you deleted"
 
1884
                      " the .frm file\n"
 
1885
                      "InnoDB: and not used DROP TABLE?"
 
1886
                      " Have you used DROP DATABASE\n"
 
1887
                      "InnoDB: for InnoDB tables in"
 
1888
                      " MySQL version <= 3.23.43?\n"
 
1889
                      "InnoDB: See the Restrictions section"
 
1890
                      " of the InnoDB manual.\n"
 
1891
                      "InnoDB: You can drop the orphaned table"
 
1892
                      " inside InnoDB by\n"
 
1893
                      "InnoDB: creating an InnoDB table with"
 
1894
                      " the same name in another\n"
 
1895
                      "InnoDB: database and copying the .frm file"
 
1896
                      " to the current database.\n"
 
1897
                      "InnoDB: Then MySQL thinks the table exists,"
 
1898
                      " and DROP TABLE will\n"
 
1899
                      "InnoDB: succeed.\n"
 
1900
                      "InnoDB: You can look for further help from\n"
 
1901
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
1902
                      stderr);
 
1903
 
1942
1904
                /* We may also get err == DB_ERROR if the .ibd file for the
1943
1905
                table already exists */
1944
1906
 
2063
2025
 
2064
2026
                trx->error_state = DB_SUCCESS;
2065
2027
 
2066
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2028
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2067
2029
 
2068
2030
                row_drop_table_for_mysql(table_name, trx, FALSE);
2069
2031
 
2084
2046
the foreign key constraints declared in the string. This function
2085
2047
should be called after the indexes for a table have been created.
2086
2048
Each foreign key constraint must be accompanied with indexes in
2087
 
both participating tables. The indexes are allowed to contain more
 
2049
bot participating tables. The indexes are allowed to contain more
2088
2050
fields than mentioned in the constraint. Check also that foreign key
2089
2051
constraints which reference this table are ok.
2090
2052
@return error code or DB_SUCCESS */
2098
2060
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2099
2061
                                        table2 can be written also with the
2100
2062
                                        database name before it: test.table2 */
2101
 
        size_t          sql_length,     /*!< in: length of sql_string */
2102
2063
        const char*     name,           /*!< in: table full name in the
2103
2064
                                        normalized form
2104
2065
                                        database_name/table_name */
2120
2081
 
2121
2082
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2122
2083
 
2123
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2124
 
                                              name, reject_fks);
 
2084
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2085
                                              reject_fks);
2125
2086
        if (err == DB_SUCCESS) {
2126
2087
                /* Check that also referencing constraints are ok */
2127
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2088
                err = dict_load_foreigns(name, TRUE);
2128
2089
        }
2129
2090
 
2130
2091
        if (err != DB_SUCCESS) {
2132
2093
 
2133
2094
                trx->error_state = DB_SUCCESS;
2134
2095
 
2135
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2096
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2136
2097
 
2137
2098
                row_drop_table_for_mysql(name, trx, FALSE);
2138
2099
 
2351
2312
        trx_t*          trx)    /*!< in: transaction handle */
2352
2313
{
2353
2314
        dict_foreign_t* foreign;
2354
 
        table_id_t      new_id;
 
2315
        dulint          new_id;
2355
2316
        dict_table_t*   table;
2356
2317
        ibool           success;
2357
2318
        ulint           err;
2465
2426
                goto funct_exit;
2466
2427
        }
2467
2428
 
2468
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2429
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2469
2430
 
2470
2431
        /* Remove all locks except the table-level S and X locks. */
2471
2432
        lock_remove_all_on_table(table, FALSE);
2473
2434
        info = pars_info_create();
2474
2435
 
2475
2436
        pars_info_add_str_literal(info, "table_name", name);
2476
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2437
        pars_info_add_dulint_literal(info, "new_id", new_id);
2477
2438
 
2478
2439
        err = que_eval_sql(info,
2479
2440
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2499
2460
 
2500
2461
        if (err != DB_SUCCESS) {
2501
2462
                trx->error_state = DB_SUCCESS;
2502
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2463
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2503
2464
                trx->error_state = DB_SUCCESS;
2504
2465
        } else {
2505
2466
                dict_table_change_id_in_cache(table, new_id);
2508
2469
 
2509
2470
                if (!success) {
2510
2471
                        trx->error_state = DB_SUCCESS;
2511
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
2472
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
2512
2473
                        trx->error_state = DB_SUCCESS;
2513
2474
 
2514
2475
                        err = DB_ERROR;
2687
2648
        dict_index_t*   sys_index;
2688
2649
        btr_pcur_t      pcur;
2689
2650
        mtr_t           mtr;
2690
 
        table_id_t      new_id;
 
2651
        dulint          new_id;
2691
2652
        ulint           recreate_space = 0;
2692
2653
        pars_info_t*    info = NULL;
2693
2654
 
2817
2778
 
2818
2779
        trx->table_id = table->id;
2819
2780
 
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
2781
        if (table->space && !table->dir_path_of_temp_table) {
2830
2782
                /* Discard and create the single-table tablespace. */
2831
2783
                ulint   space   = table->space;
2836
2788
 
2837
2789
                        dict_index_t*   index;
2838
2790
 
2839
 
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2791
                        space = 0;
2840
2792
 
2841
 
                        if (space == ULINT_UNDEFINED
2842
 
                            || fil_create_new_single_table_tablespace(
2843
 
                                    space, table->name, FALSE, flags,
 
2793
                        if (fil_create_new_single_table_tablespace(
 
2794
                                    &space, table->name, FALSE, flags,
2844
2795
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2845
 
                                dict_table_x_unlock_indexes(table);
2846
2796
                                ut_print_timestamp(stderr);
2847
2797
                                fprintf(stderr,
2848
2798
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2946
2896
 
2947
2897
        mem_heap_free(heap);
2948
2898
 
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);
 
2899
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2954
2900
 
2955
2901
        info = pars_info_create();
2956
2902
 
2957
2903
        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);
 
2904
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2905
        pars_info_add_dulint_literal(info, "new_id", new_id);
2960
2906
 
2961
2907
        err = que_eval_sql(info,
2962
2908
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2975
2921
 
2976
2922
        if (err != DB_SUCCESS) {
2977
2923
                trx->error_state = DB_SUCCESS;
2978
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2924
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2979
2925
                trx->error_state = DB_SUCCESS;
2980
2926
                ut_print_timestamp(stderr);
2981
2927
                fputs("  InnoDB: Unable to assign a new identifier to table ",
3316
3262
                           "END;\n"
3317
3263
                           , FALSE, trx);
3318
3264
 
3319
 
        switch (err) {
3320
 
                ibool           is_temp;
 
3265
        if (err != DB_SUCCESS) {
 
3266
                ut_a(err == DB_OUT_OF_FILE_SPACE);
 
3267
 
 
3268
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3269
 
 
3270
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3271
 
 
3272
                ut_error;
 
3273
        } else {
 
3274
                ibool           is_path;
3321
3275
                const char*     name_or_path;
3322
3276
                mem_heap_t*     heap;
3323
3277
 
3324
 
        case DB_SUCCESS:
3325
 
 
3326
3278
                heap = mem_heap_create(200);
3327
3279
 
3328
3280
                /* Clone the name, in case it has been allocated
3332
3284
                space_id = table->space;
3333
3285
 
3334
3286
                if (table->dir_path_of_temp_table != NULL) {
 
3287
                        is_path = TRUE;
3335
3288
                        name_or_path = mem_heap_strdup(
3336
3289
                                heap, table->dir_path_of_temp_table);
3337
 
                        is_temp = TRUE;
3338
3290
                } else {
 
3291
                        is_path = FALSE;
3339
3292
                        name_or_path = name;
3340
 
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
3341
 
                                & DICT_TF2_TEMPORARY;
3342
3293
                }
3343
3294
 
3344
3295
                dict_table_remove_from_cache(table);
3345
3296
 
3346
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3297
                if (dict_load_table(name) != NULL) {
3347
3298
                        ut_print_timestamp(stderr);
3348
3299
                        fputs("  InnoDB: Error: not able to remove table ",
3349
3300
                              stderr);
3358
3309
                if (err == DB_SUCCESS && space_id > 0) {
3359
3310
                        if (!fil_space_for_table_exists_in_mem(space_id,
3360
3311
                                                               name_or_path,
3361
 
                                                               is_temp, FALSE,
3362
 
                                                               !is_temp)) {
 
3312
                                                               is_path,
 
3313
                                                               FALSE, TRUE)) {
3363
3314
                                err = DB_SUCCESS;
3364
3315
 
3365
3316
                                fprintf(stderr,
3388
3339
                }
3389
3340
 
3390
3341
                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
3342
        }
3411
 
 
3412
3343
funct_exit:
3413
3344
 
3414
3345
        if (locked_dictionary) {
3424
3355
        return((int) err);
3425
3356
}
3426
3357
 
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
3358
/*******************************************************************//**
3512
3359
Drop all foreign keys in a database, see Bug#18942.
3513
3360
Called at the end of row_drop_database_for_mysql().
3983
3830
                              "InnoDB: succeed.\n", stderr);
3984
3831
                }
3985
3832
                trx->error_state = DB_SUCCESS;
3986
 
                trx_general_rollback_for_mysql(trx, NULL);
 
3833
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
3987
3834
                trx->error_state = DB_SUCCESS;
3988
3835
        } else {
3989
3836
                /* The following call will also rename the .ibd data file if
3992
3839
                if (!dict_table_rename_in_cache(table, new_name,
3993
3840
                                                !new_is_tmp)) {
3994
3841
                        trx->error_state = DB_SUCCESS;
3995
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3842
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
3996
3843
                        trx->error_state = DB_SUCCESS;
3997
3844
                        goto funct_exit;
3998
3845
                }
4001
3848
                an ALTER, not in a RENAME. */
4002
3849
 
4003
3850
                err = dict_load_foreigns(
4004
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3851
                        new_name, !old_is_tmp || trx->check_foreigns);
4005
3852
 
4006
3853
                if (err != DB_SUCCESS) {
4007
3854
                        ut_print_timestamp(stderr);
4032
3879
                        ut_a(dict_table_rename_in_cache(table,
4033
3880
                                                        old_name, FALSE));
4034
3881
                        trx->error_state = DB_SUCCESS;
4035
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3882
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
4036
3883
                        trx->error_state = DB_SUCCESS;
4037
3884
                }
4038
3885
        }
4057
3904
constraint is not broken, and calculates the number of index entries
4058
3905
in the read view of the current transaction.
4059
3906
@return TRUE if ok */
4060
 
UNIV_INTERN
 
3907
static
4061
3908
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 */
 
3909
row_scan_and_check_index(
 
3910
/*=====================*/
 
3911
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
 
3912
        dict_index_t*   index,          /*!< in: index */
 
3913
        ulint*          n_rows)         /*!< out: number of entries seen in the
 
3914
                                        current consistent read */
4069
3915
{
4070
3916
        dtuple_t*       prev_entry      = NULL;
4071
3917
        ulint           matched_fields;
4086
3932
 
4087
3933
        *n_rows = 0;
4088
3934
 
 
3935
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
3936
                /* A newly created index may lack some delete-marked
 
3937
                records that may exist in the read view of
 
3938
                prebuilt->trx.  Thus, such indexes must not be
 
3939
                accessed by consistent read. */
 
3940
                return(is_ok);
 
3941
        }
 
3942
 
4089
3943
        buf = mem_alloc(UNIV_PAGE_SIZE);
4090
3944
        heap = mem_heap_create(100);
4091
3945
 
 
3946
        /* Make a dummy template in prebuilt, which we will use
 
3947
        in scanning the index entries */
 
3948
 
 
3949
        prebuilt->index = index;
 
3950
        /* row_merge_is_index_usable() was already checked above. */
 
3951
        prebuilt->index_usable = TRUE;
 
3952
        prebuilt->sql_stat_start = TRUE;
 
3953
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
 
3954
        prebuilt->n_template = 0;
 
3955
        prebuilt->need_to_access_clustered = FALSE;
 
3956
 
 
3957
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
3958
 
 
3959
        prebuilt->select_lock_type = LOCK_NONE;
4092
3960
        cnt = 1000;
4093
3961
 
4094
3962
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4207
4075
}
4208
4076
 
4209
4077
/*********************************************************************//**
 
4078
Checks a table for corruption.
 
4079
@return DB_ERROR or DB_SUCCESS */
 
4080
UNIV_INTERN
 
4081
ulint
 
4082
row_check_table_for_mysql(
 
4083
/*======================*/
 
4084
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
 
4085
                                        handle */
 
4086
{
 
4087
        dict_table_t*   table           = prebuilt->table;
 
4088
        dict_index_t*   index;
 
4089
        ulint           n_rows;
 
4090
        ulint           n_rows_in_table = ULINT_UNDEFINED;
 
4091
        ulint           ret             = DB_SUCCESS;
 
4092
        ulint           old_isolation_level;
 
4093
 
 
4094
        if (table->ibd_file_missing) {
 
4095
                ut_print_timestamp(stderr);
 
4096
                fprintf(stderr, "  InnoDB: Error:\n"
 
4097
                        "InnoDB: MySQL is trying to use a table handle"
 
4098
                        " but the .ibd file for\n"
 
4099
                        "InnoDB: table %s does not exist.\n"
 
4100
                        "InnoDB: Have you deleted the .ibd file"
 
4101
                        " from the database directory under\n"
 
4102
                        "InnoDB: the MySQL datadir, or have you"
 
4103
                        " used DISCARD TABLESPACE?\n"
 
4104
                        "InnoDB: Look from\n"
 
4105
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
 
4106
                        "InnoDB: how you can resolve the problem.\n",
 
4107
                        table->name);
 
4108
                return(DB_ERROR);
 
4109
        }
 
4110
 
 
4111
        prebuilt->trx->op_info = "checking table";
 
4112
 
 
4113
        old_isolation_level = prebuilt->trx->isolation_level;
 
4114
 
 
4115
        /* We must run the index record counts at an isolation level
 
4116
        >= READ COMMITTED, because a dirty read can see a wrong number
 
4117
        of records in some index; to play safe, we use always
 
4118
        REPEATABLE READ here */
 
4119
 
 
4120
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
 
4121
 
 
4122
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
 
4123
        mutex_enter(&kernel_mutex);
 
4124
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
 
4125
        mutex_exit(&kernel_mutex);
 
4126
 
 
4127
        index = dict_table_get_first_index(table);
 
4128
 
 
4129
        while (index != NULL) {
 
4130
                /* fputs("Validating index ", stderr);
 
4131
                ut_print_name(stderr, trx, FALSE, index->name);
 
4132
                putc('\n', stderr); */
 
4133
 
 
4134
                if (!btr_validate_index(index, prebuilt->trx)) {
 
4135
                        ret = DB_ERROR;
 
4136
                } else {
 
4137
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
 
4138
                                ret = DB_ERROR;
 
4139
                        }
 
4140
 
 
4141
                        if (trx_is_interrupted(prebuilt->trx)) {
 
4142
                                break;
 
4143
                        }
 
4144
 
 
4145
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
 
4146
                        index->name); */
 
4147
 
 
4148
                        if (index == dict_table_get_first_index(table)) {
 
4149
                                n_rows_in_table = n_rows;
 
4150
                        } else if (n_rows != n_rows_in_table) {
 
4151
 
 
4152
                                ret = DB_ERROR;
 
4153
 
 
4154
                                fputs("Error: ", stderr);
 
4155
                                dict_index_name_print(stderr,
 
4156
                                                      prebuilt->trx, index);
 
4157
                                fprintf(stderr,
 
4158
                                        " contains %lu entries,"
 
4159
                                        " should be %lu\n",
 
4160
                                        (ulong) n_rows,
 
4161
                                        (ulong) n_rows_in_table);
 
4162
                        }
 
4163
                }
 
4164
 
 
4165
                index = dict_table_get_next_index(index);
 
4166
        }
 
4167
 
 
4168
        /* Restore the original isolation level */
 
4169
        prebuilt->trx->isolation_level = old_isolation_level;
 
4170
 
 
4171
        /* We validate also the whole adaptive hash index for all tables
 
4172
        at every CHECK TABLE */
 
4173
 
 
4174
        if (!btr_search_validate()) {
 
4175
 
 
4176
                ret = DB_ERROR;
 
4177
        }
 
4178
 
 
4179
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
 
4180
        mutex_enter(&kernel_mutex);
 
4181
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
4182
        mutex_exit(&kernel_mutex);
 
4183
 
 
4184
        prebuilt->trx->op_info = "";
 
4185
 
 
4186
        return(ret);
 
4187
}
 
4188
 
 
4189
/*********************************************************************//**
4210
4190
Determines if a table is a magic monitor table.
4211
4191
@return TRUE if monitor table */
4212
4192
UNIV_INTERN