~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: patrick crews
  • Date: 2010-09-29 15:15:19 UTC
  • mfrom: (1099.4.188 drizzle)
  • Revision ID: gleebix@gmail.com-20100929151519-6mrmzd1ciw2p9nws
Tags: 2010.09.1802
Update translations

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) {
486
427
                                        row is used, as row may contain
487
428
                                        pointers to this record! */
488
429
{
489
 
        const mysql_row_templ_t*templ;
 
430
        mysql_row_templ_t*      templ;
490
431
        dfield_t*               dfield;
491
432
        ulint                   i;
492
433
 
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);
659
592
 
660
593
        heap = mem_heap_create(sizeof *prebuilt + 128);
661
594
 
662
 
        prebuilt = static_cast<row_prebuilt_t *>(mem_heap_zalloc(heap, sizeof *prebuilt));
 
595
        prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
663
596
 
664
597
        prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
665
598
        prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
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
/*========================*/
869
799
                prebuilt->ins_node = node;
870
800
 
871
801
                if (prebuilt->ins_upd_rec_buff == NULL) {
872
 
                        prebuilt->ins_upd_rec_buff = static_cast<byte *>(mem_heap_alloc(
873
 
                                prebuilt->heap, prebuilt->mysql_row_len));
 
802
                        prebuilt->ins_upd_rec_buff = mem_heap_alloc(
 
803
                                prebuilt->heap, prebuilt->mysql_row_len);
874
804
                }
875
805
 
876
806
                row = dtuple_create(prebuilt->heap,
880
810
 
881
811
                ins_node_set_new_row(node, row);
882
812
 
883
 
                prebuilt->ins_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
813
                prebuilt->ins_graph = que_node_get_parent(
884
814
                        pars_complete_graph_for_exec(node,
885
815
                                                     prebuilt->trx,
886
 
                                                     prebuilt->heap)));
 
816
                                                     prebuilt->heap));
887
817
                prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
888
818
        }
889
819
 
914
844
        if (counter > 2000000000
915
845
            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
916
846
 
917
 
                dict_update_statistics(table, FALSE /* update even if stats
918
 
                                                    are initialized */);
 
847
                dict_update_statistics(table);
919
848
        }
920
849
}
921
850
 
922
851
/*********************************************************************//**
923
 
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
924
 
function should be called at the the end of an SQL statement, by the
925
 
connection thread that owns the transaction (trx->mysql_thd). */
 
852
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
926
853
UNIV_INTERN
927
854
void
928
855
row_unlock_table_autoinc_for_mysql(
929
856
/*===============================*/
930
857
        trx_t*  trx)    /*!< in/out: transaction */
931
858
{
932
 
        if (lock_trx_holds_autoinc_locks(trx)) {
933
 
                mutex_enter(&kernel_mutex);
934
 
 
935
 
                lock_release_autoinc_locks(trx);
936
 
 
937
 
                mutex_exit(&kernel_mutex);
938
 
        }
 
859
        mutex_enter(&kernel_mutex);
 
860
 
 
861
        lock_release_autoinc_locks(trx);
 
862
 
 
863
        mutex_exit(&kernel_mutex);
939
864
}
940
865
 
941
866
/*********************************************************************//**
1066
991
        trx_start_if_not_started(trx);
1067
992
 
1068
993
        if (table) {
1069
 
                err = lock_table(0, table, static_cast<lock_mode>(mode), thr);
 
994
                err = lock_table(0, table, mode, thr);
1070
995
        } else {
1071
996
                err = lock_table(0, prebuilt->table,
1072
 
                                 static_cast<lock_mode>(prebuilt->select_lock_type), thr);
 
997
                                 prebuilt->select_lock_type, thr);
1073
998
        }
1074
999
 
1075
1000
        trx->error_state = err;
1244
1169
 
1245
1170
                node = sel_node_create(prebuilt->heap);
1246
1171
 
1247
 
                prebuilt->sel_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1172
                prebuilt->sel_graph = que_node_get_parent(
1248
1173
                        pars_complete_graph_for_exec(node,
1249
1174
                                                     prebuilt->trx,
1250
 
                                                     prebuilt->heap)));
 
1175
                                                     prebuilt->heap));
1251
1176
 
1252
1177
                prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1253
1178
        }
1315
1240
 
1316
1241
                prebuilt->upd_node = node;
1317
1242
 
1318
 
                prebuilt->upd_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1243
                prebuilt->upd_graph = que_node_get_parent(
1319
1244
                        pars_complete_graph_for_exec(node,
1320
1245
                                                     prebuilt->trx,
1321
 
                                                     prebuilt->heap)));
 
1246
                                                     prebuilt->heap));
1322
1247
                prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1323
1248
        }
1324
1249
 
1432
1357
run_again:
1433
1358
        thr->run_node = node;
1434
1359
        thr->prev_node = node;
1435
 
        thr->fk_cascade_depth = 0;
1436
1360
 
1437
1361
        row_upd_step(thr);
1438
1362
 
1439
 
        /* The recursive call for cascading update/delete happens
1440
 
        in above row_upd_step(), reset the counter once we come
1441
 
        out of the recursive call, so it does not accumulate for
1442
 
        different row deletes */
1443
 
        thr->fk_cascade_depth = 0;
1444
 
 
1445
1363
        err = trx->error_state;
1446
1364
 
1447
 
        /* Reset fk_cascade_depth back to 0 */
1448
 
        thr->fk_cascade_depth = 0;
1449
 
 
1450
1365
        if (err != DB_SUCCESS) {
1451
1366
                que_thr_stop_for_mysql(thr);
1452
1367
 
1483
1398
                srv_n_rows_updated++;
1484
1399
        }
1485
1400
 
1486
 
        /* We update table statistics only if it is a DELETE or UPDATE
1487
 
        that changes indexed columns, UPDATEs that change only non-indexed
1488
 
        columns would not affect statistics. */
1489
 
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
1490
 
                row_update_statistics_if_needed(prebuilt->table);
1491
 
        }
 
1401
        row_update_statistics_if_needed(prebuilt->table);
1492
1402
 
1493
1403
        trx->op_info = "";
1494
1404
 
1496
1406
}
1497
1407
 
1498
1408
/*********************************************************************//**
1499
 
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
1500
 
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
1501
 
Before calling this function row_search_for_mysql() must have
1502
 
initialized prebuilt->new_rec_locks to store the information which new
1503
 
record locks really were set. This function removes a newly set
1504
 
clustered index record lock under prebuilt->pcur or
1505
 
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
1506
 
releases the latest clustered index record lock we set.
1507
 
@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 */
1508
1420
UNIV_INTERN
1509
1421
int
1510
1422
row_unlock_for_mysql(
1511
1423
/*=================*/
1512
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1424
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1513
1425
                                        handle */
1514
 
        ibool           has_latches_on_recs)/*!< in: TRUE if called so
1515
 
                                        that we have the latches on
1516
 
                                        the records under pcur and
1517
 
                                        clust_pcur, and we do not need
1518
 
                                        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. */
1519
1430
{
1520
1431
        btr_pcur_t*     pcur            = prebuilt->pcur;
1521
1432
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1526
1437
 
1527
1438
        if (UNIV_UNLIKELY
1528
1439
            (!srv_locks_unsafe_for_binlog
1529
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1440
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1530
1441
 
1531
1442
                fprintf(stderr,
1532
1443
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1598
1509
                        }
1599
1510
                }
1600
1511
 
1601
 
                if (rec_trx_id != trx->id) {
 
1512
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1602
1513
                        /* We did not update the record: unlock it */
1603
1514
 
1604
1515
                        rec = btr_pcur_get_rec(pcur);
1605
1516
                        index = btr_pcur_get_btr_cur(pcur)->index;
1606
1517
 
1607
1518
                        lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1608
 
                                        rec, static_cast<lock_mode>(prebuilt->select_lock_type));
 
1519
                                        rec, prebuilt->select_lock_type);
1609
1520
 
1610
1521
                        if (prebuilt->new_rec_locks >= 2) {
1611
1522
                                rec = btr_pcur_get_rec(clust_pcur);
1614
1525
                                lock_rec_unlock(trx,
1615
1526
                                                btr_pcur_get_block(clust_pcur),
1616
1527
                                                rec,
1617
 
                                                static_cast<lock_mode>(prebuilt->select_lock_type));
 
1528
                                                prebuilt->select_lock_type);
1618
1529
                        }
1619
1530
                }
1620
1531
no_unlock:
1642
1553
        trx_t*  trx;
1643
1554
 
1644
1555
        trx = thr_get_trx(thr);
1645
 
 
1646
 
        /* Increment fk_cascade_depth to record the recursive call depth on
1647
 
        a single update/delete that affects multiple tables chained
1648
 
        together with foreign key relations. */
1649
 
        thr->fk_cascade_depth++;
1650
 
 
1651
 
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1652
 
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1653
 
        }
1654
1556
run_again:
1655
1557
        thr->run_node = node;
1656
1558
        thr->prev_node = node;
1657
1559
 
1658
1560
        row_upd_step(thr);
1659
1561
 
1660
 
        /* The recursive call for cascading update/delete happens
1661
 
        in above row_upd_step(), reset the counter once we come
1662
 
        out of the recursive call, so it does not accumulate for
1663
 
        different row deletes */
1664
 
        thr->fk_cascade_depth = 0;
1665
 
 
1666
1562
        err = trx->error_state;
1667
1563
 
1668
1564
        /* Note that the cascade node is a subnode of another InnoDB
1728
1624
}
1729
1625
 
1730
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
/*********************************************************************//**
1731
1658
Locks the data dictionary in shared mode from modifications, for performing
1732
1659
foreign key check, rollback, or other operation invisible to MySQL. */
1733
1660
UNIV_INTERN
1823
1750
        const char*     table_name;
1824
1751
        ulint           table_name_len;
1825
1752
        ulint           err;
 
1753
        ulint           i;
1826
1754
 
1827
1755
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1828
1756
#ifdef UNIV_SYNC_DEBUG
1837
1765
                      " by the user.\n"
1838
1766
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1839
1767
                      " is replaced with raw.\n", stderr);
 
1768
err_exit:
1840
1769
                dict_mem_table_free(table);
1841
1770
                trx_commit_for_mysql(trx);
1842
1771
 
1845
1774
 
1846
1775
        trx->op_info = "creating table";
1847
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
 
1848
1786
        trx_start_if_not_started(trx);
1849
1787
 
1850
1788
        /* The table name is prefixed with the database name and a '/'.
1912
1850
 
1913
1851
        thr = pars_complete_graph_for_exec(node, trx, heap);
1914
1852
 
1915
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
1853
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1916
1854
        que_run_threads(thr);
1917
1855
 
1918
1856
        err = trx->error_state;
1919
1857
 
 
1858
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 
1859
                trx->error_state = DB_SUCCESS;
 
1860
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
1861
        }
 
1862
 
1920
1863
        switch (err) {
1921
 
        case DB_SUCCESS:
1922
 
                break;
1923
1864
        case DB_OUT_OF_FILE_SPACE:
1924
 
                trx->error_state = DB_SUCCESS;
1925
 
                trx_general_rollback_for_mysql(trx, NULL);
1926
 
 
1927
1865
                ut_print_timestamp(stderr);
1928
1866
                fputs("  InnoDB: Warning: cannot create table ",
1929
1867
                      stderr);
1938
1876
                break;
1939
1877
 
1940
1878
        case DB_DUPLICATE_KEY:
1941
 
        default:
 
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
 
1945
 
                trx->error_state = DB_SUCCESS;
1946
 
                trx_general_rollback_for_mysql(trx, NULL);
1947
 
                dict_mem_table_free(table);
1948
1907
                break;
1949
1908
        }
1950
1909
 
2053
2012
 
2054
2013
        thr = pars_complete_graph_for_exec(node, trx, heap);
2055
2014
 
2056
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
2015
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2057
2016
        que_run_threads(thr);
2058
2017
 
2059
2018
        err = trx->error_state;
2066
2025
 
2067
2026
                trx->error_state = DB_SUCCESS;
2068
2027
 
2069
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2028
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2070
2029
 
2071
2030
                row_drop_table_for_mysql(table_name, trx, FALSE);
2072
2031
 
2087
2046
the foreign key constraints declared in the string. This function
2088
2047
should be called after the indexes for a table have been created.
2089
2048
Each foreign key constraint must be accompanied with indexes in
2090
 
both participating tables. The indexes are allowed to contain more
 
2049
bot participating tables. The indexes are allowed to contain more
2091
2050
fields than mentioned in the constraint. Check also that foreign key
2092
2051
constraints which reference this table are ok.
2093
2052
@return error code or DB_SUCCESS */
2101
2060
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2102
2061
                                        table2 can be written also with the
2103
2062
                                        database name before it: test.table2 */
2104
 
        size_t          sql_length,     /*!< in: length of sql_string */
2105
2063
        const char*     name,           /*!< in: table full name in the
2106
2064
                                        normalized form
2107
2065
                                        database_name/table_name */
2123
2081
 
2124
2082
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2125
2083
 
2126
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2127
 
                                              name, reject_fks);
 
2084
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2085
                                              reject_fks);
2128
2086
        if (err == DB_SUCCESS) {
2129
2087
                /* Check that also referencing constraints are ok */
2130
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2088
                err = dict_load_foreigns(name, TRUE);
2131
2089
        }
2132
2090
 
2133
2091
        if (err != DB_SUCCESS) {
2135
2093
 
2136
2094
                trx->error_state = DB_SUCCESS;
2137
2095
 
2138
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2096
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2139
2097
 
2140
2098
                row_drop_table_for_mysql(name, trx, FALSE);
2141
2099
 
2326
2284
                drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2327
2285
        }
2328
2286
 
2329
 
        drop = static_cast<row_mysql_drop_t *>(mem_alloc(sizeof(row_mysql_drop_t)));
 
2287
        drop = mem_alloc(sizeof(row_mysql_drop_t));
2330
2288
 
2331
2289
        drop->table_name = mem_strdup(name);
2332
2290
 
2354
2312
        trx_t*          trx)    /*!< in: transaction handle */
2355
2313
{
2356
2314
        dict_foreign_t* foreign;
2357
 
        table_id_t      new_id;
 
2315
        dulint          new_id;
2358
2316
        dict_table_t*   table;
2359
2317
        ibool           success;
2360
2318
        ulint           err;
2468
2426
                goto funct_exit;
2469
2427
        }
2470
2428
 
2471
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2429
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2472
2430
 
2473
2431
        /* Remove all locks except the table-level S and X locks. */
2474
2432
        lock_remove_all_on_table(table, FALSE);
2476
2434
        info = pars_info_create();
2477
2435
 
2478
2436
        pars_info_add_str_literal(info, "table_name", name);
2479
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2437
        pars_info_add_dulint_literal(info, "new_id", new_id);
2480
2438
 
2481
2439
        err = que_eval_sql(info,
2482
2440
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2502
2460
 
2503
2461
        if (err != DB_SUCCESS) {
2504
2462
                trx->error_state = DB_SUCCESS;
2505
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2463
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2506
2464
                trx->error_state = DB_SUCCESS;
2507
2465
        } else {
2508
2466
                dict_table_change_id_in_cache(table, new_id);
2511
2469
 
2512
2470
                if (!success) {
2513
2471
                        trx->error_state = DB_SUCCESS;
2514
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
2472
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
2515
2473
                        trx->error_state = DB_SUCCESS;
2516
2474
 
2517
2475
                        err = DB_ERROR;
2690
2648
        dict_index_t*   sys_index;
2691
2649
        btr_pcur_t      pcur;
2692
2650
        mtr_t           mtr;
2693
 
        table_id_t      new_id;
 
2651
        dulint          new_id;
2694
2652
        ulint           recreate_space = 0;
2695
2653
        pars_info_t*    info = NULL;
2696
2654
 
2830
2788
 
2831
2789
                        dict_index_t*   index;
2832
2790
 
2833
 
                        dict_hdr_get_new_id(NULL, NULL, &space);
2834
 
 
2835
 
                        /* Lock all index trees for this table. We must
2836
 
                        do so after dict_hdr_get_new_id() to preserve
2837
 
                        the latch order */
2838
 
                        dict_table_x_lock_indexes(table);
2839
 
 
2840
 
                        if (space == ULINT_UNDEFINED
2841
 
                            || fil_create_new_single_table_tablespace(
2842
 
                                    space, table->name, FALSE, flags,
 
2791
                        space = 0;
 
2792
 
 
2793
                        if (fil_create_new_single_table_tablespace(
 
2794
                                    &space, table->name, FALSE, flags,
2843
2795
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2844
 
                                dict_table_x_unlock_indexes(table);
2845
2796
                                ut_print_timestamp(stderr);
2846
2797
                                fprintf(stderr,
2847
2798
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2870
2821
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2871
2822
                        mtr_commit(&mtr);
2872
2823
                }
2873
 
        } else {
2874
 
                /* Lock all index trees for this table, as we will
2875
 
                truncate the table/index and possibly change their metadata.
2876
 
                All DML/DDL are blocked by table level lock, with
2877
 
                a few exceptions such as queries into information schema
2878
 
                about the table, MySQL could try to access index stats
2879
 
                for this kind of query, we need to use index locks to
2880
 
                sync up */
2881
 
                dict_table_x_lock_indexes(table);
2882
2824
        }
2883
2825
 
2884
2826
        /* scan SYS_INDEXES for all indexes of the table */
2887
2829
        tuple = dtuple_create(heap, 1);
2888
2830
        dfield = dtuple_get_nth_field(tuple, 0);
2889
2831
 
2890
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 8));
 
2832
        buf = mem_heap_alloc(heap, 8);
2891
2833
        mach_write_to_8(buf, table->id);
2892
2834
 
2893
2835
        dfield_set_data(dfield, buf, 8);
2954
2896
 
2955
2897
        mem_heap_free(heap);
2956
2898
 
2957
 
        /* Done with index truncation, release index tree locks,
2958
 
        subsequent work relates to table level metadata change */
2959
 
        dict_table_x_unlock_indexes(table);
2960
 
 
2961
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2899
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2962
2900
 
2963
2901
        info = pars_info_create();
2964
2902
 
2965
2903
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2966
 
        pars_info_add_ull_literal(info, "old_id", table->id);
2967
 
        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);
2968
2906
 
2969
2907
        err = que_eval_sql(info,
2970
2908
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2983
2921
 
2984
2922
        if (err != DB_SUCCESS) {
2985
2923
                trx->error_state = DB_SUCCESS;
2986
 
                trx_general_rollback_for_mysql(trx, NULL);
 
2924
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
2987
2925
                trx->error_state = DB_SUCCESS;
2988
2926
                ut_print_timestamp(stderr);
2989
2927
                fputs("  InnoDB: Unable to assign a new identifier to table ",
3004
2942
        dict_table_autoinc_lock(table);
3005
2943
        dict_table_autoinc_initialize(table, 1);
3006
2944
        dict_table_autoinc_unlock(table);
3007
 
        dict_update_statistics(table, FALSE /* update even if stats are
3008
 
                                            initialized */);
 
2945
        dict_update_statistics(table);
3009
2946
 
3010
2947
        trx_commit_for_mysql(trx);
3011
2948
 
3213
3150
 
3214
3151
        if (table->n_foreign_key_checks_running > 0) {
3215
3152
 
3216
 
                const char*     i_table_name = table->name;
 
3153
                const char*     table_name = table->name;
3217
3154
                ibool           added;
3218
3155
 
3219
 
                added = row_add_table_to_background_drop_list(i_table_name);
 
3156
                added = row_add_table_to_background_drop_list(table_name);
3220
3157
 
3221
3158
                if (added) {
3222
3159
                        ut_print_timestamp(stderr);
3223
3160
                        fputs("  InnoDB: You are trying to drop table ",
3224
3161
                              stderr);
3225
 
                        ut_print_name(stderr, trx, TRUE, i_table_name);
 
3162
                        ut_print_name(stderr, trx, TRUE, table_name);
3226
3163
                        fputs("\n"
3227
3164
                              "InnoDB: though there is a"
3228
3165
                              " foreign key check running on it.\n"
3325
3262
                           "END;\n"
3326
3263
                           , FALSE, trx);
3327
3264
 
3328
 
        switch (err) {
3329
 
                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;
3330
3275
                const char*     name_or_path;
3331
3276
                mem_heap_t*     heap;
3332
3277
 
3333
 
        case DB_SUCCESS:
3334
 
 
3335
3278
                heap = mem_heap_create(200);
3336
3279
 
3337
3280
                /* Clone the name, in case it has been allocated
3341
3284
                space_id = table->space;
3342
3285
 
3343
3286
                if (table->dir_path_of_temp_table != NULL) {
 
3287
                        is_path = TRUE;
3344
3288
                        name_or_path = mem_heap_strdup(
3345
3289
                                heap, table->dir_path_of_temp_table);
3346
 
                        is_temp = TRUE;
3347
3290
                } else {
 
3291
                        is_path = FALSE;
3348
3292
                        name_or_path = name;
3349
 
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
3350
 
                                & DICT_TF2_TEMPORARY;
3351
3293
                }
3352
3294
 
3353
3295
                dict_table_remove_from_cache(table);
3354
3296
 
3355
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3297
                if (dict_load_table(name) != NULL) {
3356
3298
                        ut_print_timestamp(stderr);
3357
3299
                        fputs("  InnoDB: Error: not able to remove table ",
3358
3300
                              stderr);
3367
3309
                if (err == DB_SUCCESS && space_id > 0) {
3368
3310
                        if (!fil_space_for_table_exists_in_mem(space_id,
3369
3311
                                                               name_or_path,
3370
 
                                                               is_temp, FALSE,
3371
 
                                                               !is_temp)) {
 
3312
                                                               is_path,
 
3313
                                                               FALSE, TRUE)) {
3372
3314
                                err = DB_SUCCESS;
3373
3315
 
3374
3316
                                fprintf(stderr,
3397
3339
                }
3398
3340
 
3399
3341
                mem_heap_free(heap);
3400
 
                break;
3401
 
 
3402
 
        case DB_TOO_MANY_CONCURRENT_TRXS:
3403
 
                /* Cannot even find a free slot for the
3404
 
                the undo log. We can directly exit here
3405
 
                and return the DB_TOO_MANY_CONCURRENT_TRXS
3406
 
                error. */
3407
 
                break;
3408
 
 
3409
 
        case DB_OUT_OF_FILE_SPACE:
3410
 
                err = DB_MUST_GET_MORE_FILE_SPACE;
3411
 
 
3412
 
                row_mysql_handle_errors(&err, trx, NULL, NULL);
3413
 
 
3414
 
                /* Fall through to raise error */
3415
 
 
3416
 
        default:
3417
 
                /* No other possible error returns */
3418
 
                ut_error;
3419
3342
        }
3420
 
 
3421
3343
funct_exit:
3422
3344
 
3423
3345
        if (locked_dictionary) {
3433
3355
        return((int) err);
3434
3356
}
3435
3357
 
3436
 
/*********************************************************************//**
3437
 
Drop all temporary tables during crash recovery. */
3438
 
UNIV_INTERN
3439
 
void
3440
 
row_mysql_drop_temp_tables(void)
3441
 
/*============================*/
3442
 
{
3443
 
        trx_t*          trx;
3444
 
        btr_pcur_t      pcur;
3445
 
        mtr_t           mtr;
3446
 
        mem_heap_t*     heap;
3447
 
 
3448
 
        trx = trx_allocate_for_background();
3449
 
        trx->op_info = "dropping temporary tables";
3450
 
        row_mysql_lock_data_dictionary(trx);
3451
 
 
3452
 
        heap = mem_heap_create(200);
3453
 
 
3454
 
        mtr_start(&mtr);
3455
 
 
3456
 
        btr_pcur_open_at_index_side(
3457
 
                TRUE,
3458
 
                dict_table_get_first_index(dict_sys->sys_tables),
3459
 
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
3460
 
 
3461
 
        for (;;) {
3462
 
                const rec_t*    rec;
3463
 
                const byte*     field;
3464
 
                ulint           len;
3465
 
                const char*     table_name;
3466
 
                dict_table_t*   table;
3467
 
 
3468
 
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3469
 
 
3470
 
                if (!btr_pcur_is_on_user_rec(&pcur)) {
3471
 
                        break;
3472
 
                }
3473
 
 
3474
 
                rec = btr_pcur_get_rec(&pcur);
3475
 
                field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
3476
 
                if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
3477
 
                        continue;
3478
 
                }
3479
 
 
3480
 
                /* Because this is not a ROW_FORMAT=REDUNDANT table,
3481
 
                the is_temp flag is valid.  Examine it. */
3482
 
 
3483
 
                field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
3484
 
                if (len != 4
3485
 
                    || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
3486
 
                        continue;
3487
 
                }
3488
 
 
3489
 
                /* This is a temporary table. */
3490
 
                field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
3491
 
                if (len == UNIV_SQL_NULL || len == 0) {
3492
 
                        /* Corrupted SYS_TABLES.NAME */
3493
 
                        continue;
3494
 
                }
3495
 
 
3496
 
                table_name = mem_heap_strdupl(heap, (const char*) field, len);
3497
 
 
3498
 
                btr_pcur_store_position(&pcur, &mtr);
3499
 
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
3500
 
 
3501
 
                table = dict_load_table(table_name, TRUE);
3502
 
 
3503
 
                if (table) {
3504
 
                        row_drop_table_for_mysql(table_name, trx, FALSE);
3505
 
                        trx_commit_for_mysql(trx);
3506
 
                }
3507
 
 
3508
 
                mtr_start(&mtr);
3509
 
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
3510
 
                                          &pcur, &mtr);
3511
 
        }
3512
 
 
3513
 
        btr_pcur_close(&pcur);
3514
 
        mtr_commit(&mtr);
3515
 
        mem_heap_free(heap);
3516
 
        row_mysql_unlock_data_dictionary(trx);
3517
 
        trx_free_for_background(trx);
3518
 
}
3519
 
 
3520
3358
/*******************************************************************//**
3521
3359
Drop all foreign keys in a database, see Bug#18942.
3522
3360
Called at the end of row_drop_database_for_mysql().
3992
3830
                              "InnoDB: succeed.\n", stderr);
3993
3831
                }
3994
3832
                trx->error_state = DB_SUCCESS;
3995
 
                trx_general_rollback_for_mysql(trx, NULL);
 
3833
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
3996
3834
                trx->error_state = DB_SUCCESS;
3997
3835
        } else {
3998
3836
                /* The following call will also rename the .ibd data file if
4001
3839
                if (!dict_table_rename_in_cache(table, new_name,
4002
3840
                                                !new_is_tmp)) {
4003
3841
                        trx->error_state = DB_SUCCESS;
4004
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3842
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
4005
3843
                        trx->error_state = DB_SUCCESS;
4006
3844
                        goto funct_exit;
4007
3845
                }
4010
3848
                an ALTER, not in a RENAME. */
4011
3849
 
4012
3850
                err = dict_load_foreigns(
4013
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3851
                        new_name, !old_is_tmp || trx->check_foreigns);
4014
3852
 
4015
3853
                if (err != DB_SUCCESS) {
4016
3854
                        ut_print_timestamp(stderr);
4041
3879
                        ut_a(dict_table_rename_in_cache(table,
4042
3880
                                                        old_name, FALSE));
4043
3881
                        trx->error_state = DB_SUCCESS;
4044
 
                        trx_general_rollback_for_mysql(trx, NULL);
 
3882
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
4045
3883
                        trx->error_state = DB_SUCCESS;
4046
3884
                }
4047
3885
        }
4066
3904
constraint is not broken, and calculates the number of index entries
4067
3905
in the read view of the current transaction.
4068
3906
@return TRUE if ok */
4069
 
UNIV_INTERN
 
3907
static
4070
3908
ibool
4071
 
row_check_index_for_mysql(
4072
 
/*======================*/
4073
 
        row_prebuilt_t*         prebuilt,       /*!< in: prebuilt struct
4074
 
                                                in MySQL handle */
4075
 
        const dict_index_t*     index,          /*!< in: index */
4076
 
        ulint*                  n_rows)         /*!< out: number of entries
4077
 
                                                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 */
4078
3915
{
4079
3916
        dtuple_t*       prev_entry      = NULL;
4080
3917
        ulint           matched_fields;
4095
3932
 
4096
3933
        *n_rows = 0;
4097
3934
 
4098
 
        buf = static_cast<byte *>(mem_alloc(UNIV_PAGE_SIZE));
 
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
 
 
3943
        buf = mem_alloc(UNIV_PAGE_SIZE);
4099
3944
        heap = mem_heap_create(100);
4100
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;
4101
3960
        cnt = 1000;
4102
3961
 
4103
3962
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4196
4055
                                * sizeof *offsets;
4197
4056
 
4198
4057
                        tmp_heap = mem_heap_create(size);
4199
 
                        offsets = static_cast<ulint *>(mem_heap_dup(tmp_heap, offsets, size));
 
4058
                        offsets = mem_heap_dup(tmp_heap, offsets, size);
4200
4059
                }
4201
4060
 
4202
4061
                mem_heap_empty(heap);
4216
4075
}
4217
4076
 
4218
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
/*********************************************************************//**
4219
4190
Determines if a table is a magic monitor table.
4220
4191
@return TRUE if monitor table */
4221
4192
UNIV_INTERN