~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Stewart Smith
  • Date: 2010-11-03 03:28:23 UTC
  • mto: (1902.1.1 build) (1910.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: stewart@flamingspork.com-20101103032823-44k21f0njmk97omr
fix docs warning: Title underline (and overline) is too short in brief_history_of_drizzle.rst

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
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(
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 */
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
 
1066
995
        trx_start_if_not_started(trx);
1067
996
 
1068
997
        if (table) {
1069
 
                err = lock_table(0, table, static_cast<lock_mode>(mode), thr);
 
998
                err = lock_table(0, table, mode, thr);
1070
999
        } else {
1071
1000
                err = lock_table(0, prebuilt->table,
1072
 
                                 static_cast<lock_mode>(prebuilt->select_lock_type), thr);
 
1001
                                 prebuilt->select_lock_type, thr);
1073
1002
        }
1074
1003
 
1075
1004
        trx->error_state = err;
1244
1173
 
1245
1174
                node = sel_node_create(prebuilt->heap);
1246
1175
 
1247
 
                prebuilt->sel_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1176
                prebuilt->sel_graph = que_node_get_parent(
1248
1177
                        pars_complete_graph_for_exec(node,
1249
1178
                                                     prebuilt->trx,
1250
 
                                                     prebuilt->heap)));
 
1179
                                                     prebuilt->heap));
1251
1180
 
1252
1181
                prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1253
1182
        }
1315
1244
 
1316
1245
                prebuilt->upd_node = node;
1317
1246
 
1318
 
                prebuilt->upd_graph = static_cast<que_fork_t *>(que_node_get_parent(
 
1247
                prebuilt->upd_graph = que_node_get_parent(
1319
1248
                        pars_complete_graph_for_exec(node,
1320
1249
                                                     prebuilt->trx,
1321
 
                                                     prebuilt->heap)));
 
1250
                                                     prebuilt->heap));
1322
1251
                prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1323
1252
        }
1324
1253
 
1432
1361
run_again:
1433
1362
        thr->run_node = node;
1434
1363
        thr->prev_node = node;
1435
 
        thr->fk_cascade_depth = 0;
1436
1364
 
1437
1365
        row_upd_step(thr);
1438
1366
 
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
1367
        err = trx->error_state;
1446
1368
 
1447
 
        /* Reset fk_cascade_depth back to 0 */
1448
 
        thr->fk_cascade_depth = 0;
1449
 
 
1450
1369
        if (err != DB_SUCCESS) {
1451
1370
                que_thr_stop_for_mysql(thr);
1452
1371
 
1483
1402
                srv_n_rows_updated++;
1484
1403
        }
1485
1404
 
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
 
        }
 
1405
        row_update_statistics_if_needed(prebuilt->table);
1492
1406
 
1493
1407
        trx->op_info = "";
1494
1408
 
1496
1410
}
1497
1411
 
1498
1412
/*********************************************************************//**
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 */
 
1413
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
 
1414
this session is using a READ COMMITTED isolation level. Before
 
1415
calling this function we must use trx_reset_new_rec_lock_info() and
 
1416
trx_register_new_rec_lock() to store the information which new record locks
 
1417
really were set. This function removes a newly set lock under prebuilt->pcur,
 
1418
and also under prebuilt->clust_pcur. Currently, this is only used and tested
 
1419
in the case of an UPDATE or a DELETE statement, where the row lock is of the
 
1420
LOCK_X type.
 
1421
Thus, this implements a 'mini-rollback' that releases the latest record
 
1422
locks we set.
 
1423
@return error code or DB_SUCCESS */
1508
1424
UNIV_INTERN
1509
1425
int
1510
1426
row_unlock_for_mysql(
1511
1427
/*=================*/
1512
 
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
 
1428
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL
1513
1429
                                        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. */
 
1430
        ibool           has_latches_on_recs)/*!< TRUE if called so that we have
 
1431
                                        the latches on the records under pcur
 
1432
                                        and clust_pcur, and we do not need to
 
1433
                                        reposition the cursors. */
1519
1434
{
1520
1435
        btr_pcur_t*     pcur            = prebuilt->pcur;
1521
1436
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1526
1441
 
1527
1442
        if (UNIV_UNLIKELY
1528
1443
            (!srv_locks_unsafe_for_binlog
1529
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1444
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1530
1445
 
1531
1446
                fprintf(stderr,
1532
1447
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1598
1513
                        }
1599
1514
                }
1600
1515
 
1601
 
                if (rec_trx_id != trx->id) {
 
1516
                if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) {
1602
1517
                        /* We did not update the record: unlock it */
1603
1518
 
1604
1519
                        rec = btr_pcur_get_rec(pcur);
1605
1520
                        index = btr_pcur_get_btr_cur(pcur)->index;
1606
1521
 
1607
1522
                        lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1608
 
                                        rec, static_cast<lock_mode>(prebuilt->select_lock_type));
 
1523
                                        rec, prebuilt->select_lock_type);
1609
1524
 
1610
1525
                        if (prebuilt->new_rec_locks >= 2) {
1611
1526
                                rec = btr_pcur_get_rec(clust_pcur);
1614
1529
                                lock_rec_unlock(trx,
1615
1530
                                                btr_pcur_get_block(clust_pcur),
1616
1531
                                                rec,
1617
 
                                                static_cast<lock_mode>(prebuilt->select_lock_type));
 
1532
                                                prebuilt->select_lock_type);
1618
1533
                        }
1619
1534
                }
1620
1535
no_unlock:
1642
1557
        trx_t*  trx;
1643
1558
 
1644
1559
        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
1560
run_again:
1655
1561
        thr->run_node = node;
1656
1562
        thr->prev_node = node;
1657
1563
 
1658
1564
        row_upd_step(thr);
1659
1565
 
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
1566
        err = trx->error_state;
1667
1567
 
1668
1568
        /* Note that the cascade node is a subnode of another InnoDB
1728
1628
}
1729
1629
 
1730
1630
/*********************************************************************//**
 
1631
Calculates the key number used inside MySQL for an Innobase index. We have
 
1632
to take into account if we generated a default clustered index for the table
 
1633
@return the key number used inside MySQL */
 
1634
UNIV_INTERN
 
1635
ulint
 
1636
row_get_mysql_key_number_for_index(
 
1637
/*===============================*/
 
1638
        const dict_index_t*     index)  /*!< in: index */
 
1639
{
 
1640
        const dict_index_t*     ind;
 
1641
        ulint                   i;
 
1642
 
 
1643
        ut_a(index);
 
1644
 
 
1645
        i = 0;
 
1646
        ind = dict_table_get_first_index(index->table);
 
1647
 
 
1648
        while (index != ind) {
 
1649
                ind = dict_table_get_next_index(ind);
 
1650
                i++;
 
1651
        }
 
1652
 
 
1653
        if (row_table_got_default_clust_index(index->table)) {
 
1654
                ut_a(i > 0);
 
1655
                i--;
 
1656
        }
 
1657
 
 
1658
        return(i);
 
1659
}
 
1660
 
 
1661
/*********************************************************************//**
1731
1662
Locks the data dictionary in shared mode from modifications, for performing
1732
1663
foreign key check, rollback, or other operation invisible to MySQL. */
1733
1664
UNIV_INTERN
1912
1843
 
1913
1844
        thr = pars_complete_graph_for_exec(node, trx, heap);
1914
1845
 
1915
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
1846
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
1916
1847
        que_run_threads(thr);
1917
1848
 
1918
1849
        err = trx->error_state;
1919
1850
 
 
1851
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 
1852
                trx->error_state = DB_SUCCESS;
 
1853
                trx_general_rollback_for_mysql(trx, NULL);
 
1854
                /* TO DO: free table?  The code below will dereference
 
1855
                table->name, though. */
 
1856
        }
 
1857
 
1920
1858
        switch (err) {
1921
 
        case DB_SUCCESS:
1922
 
                break;
1923
1859
        case DB_OUT_OF_FILE_SPACE:
1924
 
                trx->error_state = DB_SUCCESS;
1925
 
                trx_general_rollback_for_mysql(trx, NULL);
1926
 
 
1927
1860
                ut_print_timestamp(stderr);
1928
1861
                fputs("  InnoDB: Warning: cannot create table ",
1929
1862
                      stderr);
1938
1871
                break;
1939
1872
 
1940
1873
        case DB_DUPLICATE_KEY:
1941
 
        default:
1942
1874
                /* We may also get err == DB_ERROR if the .ibd file for the
1943
1875
                table already exists */
1944
1876
 
1945
 
                trx->error_state = DB_SUCCESS;
1946
 
                trx_general_rollback_for_mysql(trx, NULL);
1947
 
                dict_mem_table_free(table);
1948
1877
                break;
1949
1878
        }
1950
1879
 
2053
1982
 
2054
1983
        thr = pars_complete_graph_for_exec(node, trx, heap);
2055
1984
 
2056
 
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
 
1985
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
2057
1986
        que_run_threads(thr);
2058
1987
 
2059
1988
        err = trx->error_state;
2101
2030
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2102
2031
                                        table2 can be written also with the
2103
2032
                                        database name before it: test.table2 */
2104
 
        size_t          sql_length,     /*!< in: length of sql_string */
2105
2033
        const char*     name,           /*!< in: table full name in the
2106
2034
                                        normalized form
2107
2035
                                        database_name/table_name */
2123
2051
 
2124
2052
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2125
2053
 
2126
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2127
 
                                              name, reject_fks);
 
2054
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2055
                                              reject_fks);
2128
2056
        if (err == DB_SUCCESS) {
2129
2057
                /* Check that also referencing constraints are ok */
2130
 
                err = dict_load_foreigns(name, FALSE, TRUE);
 
2058
                err = dict_load_foreigns(name, TRUE);
2131
2059
        }
2132
2060
 
2133
2061
        if (err != DB_SUCCESS) {
2326
2254
                drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2327
2255
        }
2328
2256
 
2329
 
        drop = static_cast<row_mysql_drop_t *>(mem_alloc(sizeof(row_mysql_drop_t)));
 
2257
        drop = mem_alloc(sizeof(row_mysql_drop_t));
2330
2258
 
2331
2259
        drop->table_name = mem_strdup(name);
2332
2260
 
2354
2282
        trx_t*          trx)    /*!< in: transaction handle */
2355
2283
{
2356
2284
        dict_foreign_t* foreign;
2357
 
        table_id_t      new_id;
 
2285
        dulint          new_id;
2358
2286
        dict_table_t*   table;
2359
2287
        ibool           success;
2360
2288
        ulint           err;
2468
2396
                goto funct_exit;
2469
2397
        }
2470
2398
 
2471
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2399
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2472
2400
 
2473
2401
        /* Remove all locks except the table-level S and X locks. */
2474
2402
        lock_remove_all_on_table(table, FALSE);
2476
2404
        info = pars_info_create();
2477
2405
 
2478
2406
        pars_info_add_str_literal(info, "table_name", name);
2479
 
        pars_info_add_ull_literal(info, "new_id", new_id);
 
2407
        pars_info_add_dulint_literal(info, "new_id", new_id);
2480
2408
 
2481
2409
        err = que_eval_sql(info,
2482
2410
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2690
2618
        dict_index_t*   sys_index;
2691
2619
        btr_pcur_t      pcur;
2692
2620
        mtr_t           mtr;
2693
 
        table_id_t      new_id;
 
2621
        dulint          new_id;
2694
2622
        ulint           recreate_space = 0;
2695
2623
        pars_info_t*    info = NULL;
2696
2624
 
2830
2758
 
2831
2759
                        dict_index_t*   index;
2832
2760
 
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,
 
2761
                        space = 0;
 
2762
 
 
2763
                        if (fil_create_new_single_table_tablespace(
 
2764
                                    &space, table->name, FALSE, flags,
2843
2765
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2844
 
                                dict_table_x_unlock_indexes(table);
2845
2766
                                ut_print_timestamp(stderr);
2846
2767
                                fprintf(stderr,
2847
2768
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2870
2791
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2871
2792
                        mtr_commit(&mtr);
2872
2793
                }
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
2794
        }
2883
2795
 
2884
2796
        /* scan SYS_INDEXES for all indexes of the table */
2887
2799
        tuple = dtuple_create(heap, 1);
2888
2800
        dfield = dtuple_get_nth_field(tuple, 0);
2889
2801
 
2890
 
        buf = static_cast<byte *>(mem_heap_alloc(heap, 8));
 
2802
        buf = mem_heap_alloc(heap, 8);
2891
2803
        mach_write_to_8(buf, table->id);
2892
2804
 
2893
2805
        dfield_set_data(dfield, buf, 8);
2954
2866
 
2955
2867
        mem_heap_free(heap);
2956
2868
 
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);
 
2869
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2962
2870
 
2963
2871
        info = pars_info_create();
2964
2872
 
2965
2873
        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);
 
2874
        pars_info_add_dulint_literal(info, "old_id", table->id);
 
2875
        pars_info_add_dulint_literal(info, "new_id", new_id);
2968
2876
 
2969
2877
        err = que_eval_sql(info,
2970
2878
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
3004
2912
        dict_table_autoinc_lock(table);
3005
2913
        dict_table_autoinc_initialize(table, 1);
3006
2914
        dict_table_autoinc_unlock(table);
3007
 
        dict_update_statistics(table, FALSE /* update even if stats are
3008
 
                                            initialized */);
 
2915
        dict_update_statistics(table);
3009
2916
 
3010
2917
        trx_commit_for_mysql(trx);
3011
2918
 
3213
3120
 
3214
3121
        if (table->n_foreign_key_checks_running > 0) {
3215
3122
 
3216
 
                const char*     i_table_name = table->name;
 
3123
                const char*     table_name = table->name;
3217
3124
                ibool           added;
3218
3125
 
3219
 
                added = row_add_table_to_background_drop_list(i_table_name);
 
3126
                added = row_add_table_to_background_drop_list(table_name);
3220
3127
 
3221
3128
                if (added) {
3222
3129
                        ut_print_timestamp(stderr);
3223
3130
                        fputs("  InnoDB: You are trying to drop table ",
3224
3131
                              stderr);
3225
 
                        ut_print_name(stderr, trx, TRUE, i_table_name);
 
3132
                        ut_print_name(stderr, trx, TRUE, table_name);
3226
3133
                        fputs("\n"
3227
3134
                              "InnoDB: though there is a"
3228
3135
                              " foreign key check running on it.\n"
3325
3232
                           "END;\n"
3326
3233
                           , FALSE, trx);
3327
3234
 
3328
 
        switch (err) {
 
3235
        if (err != DB_SUCCESS) {
 
3236
                ut_a(err == DB_OUT_OF_FILE_SPACE);
 
3237
 
 
3238
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3239
 
 
3240
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3241
 
 
3242
                ut_error;
 
3243
        } else {
3329
3244
                ibool           is_temp;
3330
3245
                const char*     name_or_path;
3331
3246
                mem_heap_t*     heap;
3332
3247
 
3333
 
        case DB_SUCCESS:
3334
 
 
3335
3248
                heap = mem_heap_create(200);
3336
3249
 
3337
3250
                /* Clone the name, in case it has been allocated
3352
3265
 
3353
3266
                dict_table_remove_from_cache(table);
3354
3267
 
3355
 
                if (dict_load_table(name, TRUE) != NULL) {
 
3268
                if (dict_load_table(name) != NULL) {
3356
3269
                        ut_print_timestamp(stderr);
3357
3270
                        fputs("  InnoDB: Error: not able to remove table ",
3358
3271
                              stderr);
3397
3310
                }
3398
3311
 
3399
3312
                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
3313
        }
3420
 
 
3421
3314
funct_exit:
3422
3315
 
3423
3316
        if (locked_dictionary) {
3433
3326
        return((int) err);
3434
3327
}
3435
3328
 
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
3329
/*******************************************************************//**
3521
3330
Drop all foreign keys in a database, see Bug#18942.
3522
3331
Called at the end of row_drop_database_for_mysql().
4010
3819
                an ALTER, not in a RENAME. */
4011
3820
 
4012
3821
                err = dict_load_foreigns(
4013
 
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
 
3822
                        new_name, !old_is_tmp || trx->check_foreigns);
4014
3823
 
4015
3824
                if (err != DB_SUCCESS) {
4016
3825
                        ut_print_timestamp(stderr);
4066
3875
constraint is not broken, and calculates the number of index entries
4067
3876
in the read view of the current transaction.
4068
3877
@return TRUE if ok */
4069
 
UNIV_INTERN
 
3878
static
4070
3879
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 */
 
3880
row_scan_and_check_index(
 
3881
/*=====================*/
 
3882
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in MySQL */
 
3883
        dict_index_t*   index,          /*!< in: index */
 
3884
        ulint*          n_rows)         /*!< out: number of entries seen in the
 
3885
                                        current consistent read */
4078
3886
{
4079
3887
        dtuple_t*       prev_entry      = NULL;
4080
3888
        ulint           matched_fields;
4095
3903
 
4096
3904
        *n_rows = 0;
4097
3905
 
4098
 
        buf = static_cast<byte *>(mem_alloc(UNIV_PAGE_SIZE));
 
3906
        if (!row_merge_is_index_usable(prebuilt->trx, index)) {
 
3907
                /* A newly created index may lack some delete-marked
 
3908
                records that may exist in the read view of
 
3909
                prebuilt->trx.  Thus, such indexes must not be
 
3910
                accessed by consistent read. */
 
3911
                return(is_ok);
 
3912
        }
 
3913
 
 
3914
        buf = mem_alloc(UNIV_PAGE_SIZE);
4099
3915
        heap = mem_heap_create(100);
4100
3916
 
 
3917
        /* Make a dummy template in prebuilt, which we will use
 
3918
        in scanning the index entries */
 
3919
 
 
3920
        prebuilt->index = index;
 
3921
        /* row_merge_is_index_usable() was already checked above. */
 
3922
        prebuilt->index_usable = TRUE;
 
3923
        prebuilt->sql_stat_start = TRUE;
 
3924
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
 
3925
        prebuilt->n_template = 0;
 
3926
        prebuilt->need_to_access_clustered = FALSE;
 
3927
 
 
3928
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
 
3929
 
 
3930
        prebuilt->select_lock_type = LOCK_NONE;
4101
3931
        cnt = 1000;
4102
3932
 
4103
3933
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4196
4026
                                * sizeof *offsets;
4197
4027
 
4198
4028
                        tmp_heap = mem_heap_create(size);
4199
 
                        offsets = static_cast<ulint *>(mem_heap_dup(tmp_heap, offsets, size));
 
4029
                        offsets = mem_heap_dup(tmp_heap, offsets, size);
4200
4030
                }
4201
4031
 
4202
4032
                mem_heap_empty(heap);
4216
4046
}
4217
4047
 
4218
4048
/*********************************************************************//**
 
4049
Checks a table for corruption.
 
4050
@return DB_ERROR or DB_SUCCESS */
 
4051
UNIV_INTERN
 
4052
ulint
 
4053
row_check_table_for_mysql(
 
4054
/*======================*/
 
4055
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
 
4056
                                        handle */
 
4057
{
 
4058
        dict_table_t*   table           = prebuilt->table;
 
4059
        dict_index_t*   index;
 
4060
        ulint           n_rows;
 
4061
        ulint           n_rows_in_table = ULINT_UNDEFINED;
 
4062
        ulint           ret             = DB_SUCCESS;
 
4063
        ulint           old_isolation_level;
 
4064
 
 
4065
        if (table->ibd_file_missing) {
 
4066
                ut_print_timestamp(stderr);
 
4067
                fprintf(stderr, "  InnoDB: Error:\n"
 
4068
                        "InnoDB: MySQL is trying to use a table handle"
 
4069
                        " but the .ibd file for\n"
 
4070
                        "InnoDB: table %s does not exist.\n"
 
4071
                        "InnoDB: Have you deleted the .ibd file"
 
4072
                        " from the database directory under\n"
 
4073
                        "InnoDB: the MySQL datadir, or have you"
 
4074
                        " used DISCARD TABLESPACE?\n"
 
4075
                        "InnoDB: Look from\n"
 
4076
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
 
4077
                        "InnoDB: how you can resolve the problem.\n",
 
4078
                        table->name);
 
4079
                return(DB_ERROR);
 
4080
        }
 
4081
 
 
4082
        prebuilt->trx->op_info = "checking table";
 
4083
 
 
4084
        old_isolation_level = prebuilt->trx->isolation_level;
 
4085
 
 
4086
        /* We must run the index record counts at an isolation level
 
4087
        >= READ COMMITTED, because a dirty read can see a wrong number
 
4088
        of records in some index; to play safe, we use always
 
4089
        REPEATABLE READ here */
 
4090
 
 
4091
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
 
4092
 
 
4093
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
 
4094
        mutex_enter(&kernel_mutex);
 
4095
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
 
4096
        mutex_exit(&kernel_mutex);
 
4097
 
 
4098
        index = dict_table_get_first_index(table);
 
4099
 
 
4100
        while (index != NULL) {
 
4101
                /* fputs("Validating index ", stderr);
 
4102
                ut_print_name(stderr, trx, FALSE, index->name);
 
4103
                putc('\n', stderr); */
 
4104
 
 
4105
                if (!btr_validate_index(index, prebuilt->trx)) {
 
4106
                        ret = DB_ERROR;
 
4107
                } else {
 
4108
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
 
4109
                                ret = DB_ERROR;
 
4110
                        }
 
4111
 
 
4112
                        if (trx_is_interrupted(prebuilt->trx)) {
 
4113
                                ret = DB_INTERRUPTED;
 
4114
                                break;
 
4115
                        }
 
4116
 
 
4117
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
 
4118
                        index->name); */
 
4119
 
 
4120
                        if (index == dict_table_get_first_index(table)) {
 
4121
                                n_rows_in_table = n_rows;
 
4122
                        } else if (n_rows != n_rows_in_table) {
 
4123
 
 
4124
                                ret = DB_ERROR;
 
4125
 
 
4126
                                fputs("Error: ", stderr);
 
4127
                                dict_index_name_print(stderr,
 
4128
                                                      prebuilt->trx, index);
 
4129
                                fprintf(stderr,
 
4130
                                        " contains %lu entries,"
 
4131
                                        " should be %lu\n",
 
4132
                                        (ulong) n_rows,
 
4133
                                        (ulong) n_rows_in_table);
 
4134
                        }
 
4135
                }
 
4136
 
 
4137
                index = dict_table_get_next_index(index);
 
4138
        }
 
4139
 
 
4140
        /* Restore the original isolation level */
 
4141
        prebuilt->trx->isolation_level = old_isolation_level;
 
4142
 
 
4143
        /* We validate also the whole adaptive hash index for all tables
 
4144
        at every CHECK TABLE */
 
4145
 
 
4146
        if (!btr_search_validate()) {
 
4147
 
 
4148
                ret = DB_ERROR;
 
4149
        }
 
4150
 
 
4151
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
 
4152
        mutex_enter(&kernel_mutex);
 
4153
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
 
4154
        mutex_exit(&kernel_mutex);
 
4155
 
 
4156
        prebuilt->trx->op_info = "";
 
4157
 
 
4158
        return(ret);
 
4159
}
 
4160
 
 
4161
/*********************************************************************//**
4219
4162
Determines if a table is a magic monitor table.
4220
4163
@return TRUE if monitor table */
4221
4164
UNIV_INTERN