~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-10 08:10:53 UTC
  • mto: (1819.7.44 update-innobase)
  • mto: This revision was merged to the branch mainline in revision 1926.
  • Revision ID: stewart@flamingspork.com-20101110081053-fz4depckopv167tg
add tset for bug673380: CREATE TABLE AS can create a table with a column type of NULL

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
468
468
/****************************************************************//**
469
469
Handles user errors and lock waits detected by the database engine.
470
470
@return TRUE if it was a lock wait and we should continue running the
471
 
query thread and in that case the thr is ALREADY in the running state. */
 
471
query thread */
472
472
UNIV_INTERN
473
473
ibool
474
474
row_mysql_handle_errors(
505
505
        case DB_CANNOT_ADD_CONSTRAINT:
506
506
        case DB_TOO_MANY_CONCURRENT_TRXS:
507
507
        case DB_OUT_OF_FILE_SPACE:
508
 
        case DB_INTERRUPTED:
509
508
                if (savept) {
510
509
                        /* Roll back the latest, possibly incomplete
511
510
                        insertion or update */
1442
1441
 
1443
1442
        if (UNIV_UNLIKELY
1444
1443
            (!srv_locks_unsafe_for_binlog
1445
 
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
 
1444
             && trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
1446
1445
 
1447
1446
                fprintf(stderr,
1448
1447
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1629
1628
}
1630
1629
 
1631
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
/*********************************************************************//**
1632
1662
Locks the data dictionary in shared mode from modifications, for performing
1633
1663
foreign key check, rollback, or other operation invisible to MySQL. */
1634
1664
UNIV_INTERN
2000
2030
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2001
2031
                                        table2 can be written also with the
2002
2032
                                        database name before it: test.table2 */
2003
 
        size_t          sql_length,     /*!< in: length of sql_string */
2004
2033
        const char*     name,           /*!< in: table full name in the
2005
2034
                                        normalized form
2006
2035
                                        database_name/table_name */
2022
2051
 
2023
2052
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2024
2053
 
2025
 
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
2026
 
                                              name, reject_fks);
 
2054
        err = dict_create_foreign_constraints(trx, sql_string, name,
 
2055
                                              reject_fks);
2027
2056
        if (err == DB_SUCCESS) {
2028
2057
                /* Check that also referencing constraints are ok */
2029
2058
                err = dict_load_foreigns(name, TRUE);
2367
2396
                goto funct_exit;
2368
2397
        }
2369
2398
 
2370
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2399
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2371
2400
 
2372
2401
        /* Remove all locks except the table-level S and X locks. */
2373
2402
        lock_remove_all_on_table(table, FALSE);
2729
2758
 
2730
2759
                        dict_index_t*   index;
2731
2760
 
2732
 
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2761
                        space = 0;
2733
2762
 
2734
 
                        if (space == ULINT_UNDEFINED
2735
 
                            || fil_create_new_single_table_tablespace(
2736
 
                                    space, table->name, FALSE, flags,
 
2763
                        if (fil_create_new_single_table_tablespace(
 
2764
                                    &space, table->name, FALSE, flags,
2737
2765
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2738
2766
                                ut_print_timestamp(stderr);
2739
2767
                                fprintf(stderr,
2838
2866
 
2839
2867
        mem_heap_free(heap);
2840
2868
 
2841
 
        dict_hdr_get_new_id(&new_id, NULL, NULL);
 
2869
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
2842
2870
 
2843
2871
        info = pars_info_create();
2844
2872
 
3204
3232
                           "END;\n"
3205
3233
                           , FALSE, trx);
3206
3234
 
3207
 
        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 {
3208
3244
                ibool           is_temp;
3209
3245
                const char*     name_or_path;
3210
3246
                mem_heap_t*     heap;
3211
3247
 
3212
 
        case DB_SUCCESS:
3213
 
 
3214
3248
                heap = mem_heap_create(200);
3215
3249
 
3216
3250
                /* Clone the name, in case it has been allocated
3276
3310
                }
3277
3311
 
3278
3312
                mem_heap_free(heap);
3279
 
                break;
3280
 
 
3281
 
        case DB_TOO_MANY_CONCURRENT_TRXS:
3282
 
                /* Cannot even find a free slot for the
3283
 
                the undo log. We can directly exit here
3284
 
                and return the DB_TOO_MANY_CONCURRENT_TRXS
3285
 
                error. */
3286
 
                break;
3287
 
 
3288
 
        case DB_OUT_OF_FILE_SPACE:
3289
 
                err = DB_MUST_GET_MORE_FILE_SPACE;
3290
 
 
3291
 
                row_mysql_handle_errors(&err, trx, NULL, NULL);
3292
 
 
3293
 
                /* Fall through to raise error */
3294
 
 
3295
 
        default:
3296
 
                /* No other possible error returns */
3297
 
                ut_error;
3298
3313
        }
3299
 
 
3300
3314
funct_exit:
3301
3315
 
3302
3316
        if (locked_dictionary) {
3312
3326
        return((int) err);
3313
3327
}
3314
3328
 
3315
 
/*********************************************************************//**
3316
 
Drop all temporary tables during crash recovery. */
3317
 
UNIV_INTERN
3318
 
void
3319
 
row_mysql_drop_temp_tables(void)
3320
 
/*============================*/
3321
 
{
3322
 
        trx_t*          trx;
3323
 
        btr_pcur_t      pcur;
3324
 
        mtr_t           mtr;
3325
 
        mem_heap_t*     heap;
3326
 
 
3327
 
        trx = trx_allocate_for_background();
3328
 
        trx->op_info = "dropping temporary tables";
3329
 
        row_mysql_lock_data_dictionary(trx);
3330
 
 
3331
 
        heap = mem_heap_create(200);
3332
 
 
3333
 
        mtr_start(&mtr);
3334
 
 
3335
 
        btr_pcur_open_at_index_side(
3336
 
                TRUE,
3337
 
                dict_table_get_first_index(dict_sys->sys_tables),
3338
 
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
3339
 
 
3340
 
        for (;;) {
3341
 
                const rec_t*    rec;
3342
 
                const byte*     field;
3343
 
                ulint           len;
3344
 
                const char*     table_name;
3345
 
                dict_table_t*   table;
3346
 
 
3347
 
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3348
 
 
3349
 
                if (!btr_pcur_is_on_user_rec(&pcur)) {
3350
 
                        break;
3351
 
                }
3352
 
 
3353
 
                rec = btr_pcur_get_rec(&pcur);
3354
 
                field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
3355
 
                if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
3356
 
                        continue;
3357
 
                }
3358
 
 
3359
 
                /* Because this is not a ROW_FORMAT=REDUNDANT table,
3360
 
                the is_temp flag is valid.  Examine it. */
3361
 
 
3362
 
                field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
3363
 
                if (len != 4
3364
 
                    || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
3365
 
                        continue;
3366
 
                }
3367
 
 
3368
 
                /* This is a temporary table. */
3369
 
                field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
3370
 
                if (len == UNIV_SQL_NULL || len == 0) {
3371
 
                        /* Corrupted SYS_TABLES.NAME */
3372
 
                        continue;
3373
 
                }
3374
 
 
3375
 
                table_name = mem_heap_strdupl(heap, (const char*) field, len);
3376
 
 
3377
 
                btr_pcur_store_position(&pcur, &mtr);
3378
 
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
3379
 
 
3380
 
                table = dict_load_table(table_name);
3381
 
 
3382
 
                if (table) {
3383
 
                        row_drop_table_for_mysql(table_name, trx, FALSE);
3384
 
                        trx_commit_for_mysql(trx);
3385
 
                }
3386
 
 
3387
 
                mtr_start(&mtr);
3388
 
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
3389
 
                                          &pcur, &mtr);
3390
 
        }
3391
 
 
3392
 
        btr_pcur_close(&pcur);
3393
 
        mtr_commit(&mtr);
3394
 
        mem_heap_free(heap);
3395
 
        row_mysql_unlock_data_dictionary(trx);
3396
 
        trx_free_for_background(trx);
3397
 
}
3398
 
 
3399
3329
/*******************************************************************//**
3400
3330
Drop all foreign keys in a database, see Bug#18942.
3401
3331
Called at the end of row_drop_database_for_mysql().
3945
3875
constraint is not broken, and calculates the number of index entries
3946
3876
in the read view of the current transaction.
3947
3877
@return TRUE if ok */
3948
 
UNIV_INTERN
 
3878
static
3949
3879
ibool
3950
 
row_check_index_for_mysql(
3951
 
/*======================*/
3952
 
        row_prebuilt_t*         prebuilt,       /*!< in: prebuilt struct
3953
 
                                                in MySQL handle */
3954
 
        const dict_index_t*     index,          /*!< in: index */
3955
 
        ulint*                  n_rows)         /*!< out: number of entries
3956
 
                                                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 */
3957
3886
{
3958
3887
        dtuple_t*       prev_entry      = NULL;
3959
3888
        ulint           matched_fields;
3974
3903
 
3975
3904
        *n_rows = 0;
3976
3905
 
 
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
 
3977
3914
        buf = mem_alloc(UNIV_PAGE_SIZE);
3978
3915
        heap = mem_heap_create(100);
3979
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;
3980
3931
        cnt = 1000;
3981
3932
 
3982
3933
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4095
4046
}
4096
4047
 
4097
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
/*********************************************************************//**
4098
4162
Determines if a table is a magic monitor table.
4099
4163
@return TRUE if monitor table */
4100
4164
UNIV_INTERN