~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Moved sql_common.h and my_time.h to libdrizzle.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include "dict0boot.h"
26
26
#include "trx0roll.h"
27
27
#include "trx0purge.h"
28
 
#include "trx0rec.h"
29
 
#include "trx0undo.h"
30
28
#include "lock0lock.h"
31
29
#include "rem0cmp.h"
32
30
#include "log0log.h"
34
32
#include "fil0fil.h"
35
33
#include "ibuf0ibuf.h"
36
34
 
 
35
/* A dummy variable used to fool the compiler */
 
36
ibool   row_mysql_identically_false     = FALSE;
 
37
 
37
38
/* Provide optional 4.x backwards compatibility for 5.0 and above */
38
 
UNIV_INTERN ibool       row_rollback_on_timeout = FALSE;
 
39
ibool   row_rollback_on_timeout = FALSE;
39
40
 
40
41
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
41
42
that the table handler can drop the table in background when there are no
46
47
        UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
47
48
};
48
49
 
49
 
static UT_LIST_BASE_NODE_T(row_mysql_drop_t)    row_mysql_drop_list;
50
 
static ibool    row_mysql_drop_list_inited      = FALSE;
 
50
UT_LIST_BASE_NODE_T(row_mysql_drop_t)   row_mysql_drop_list;
 
51
ibool   row_mysql_drop_list_inited      = FALSE;
51
52
 
52
53
/* Magic table names for invoking various monitor threads */
53
54
static const char S_innodb_monitor[] = "innodb_monitor";
56
57
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
57
58
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
58
59
 
59
 
/* Evaluates to true if str1 equals str2_onstack, used for comparing
60
 
the above strings. */
61
 
#define STR_EQ(str1, str1_len, str2_onstack) \
62
 
        ((str1_len) == sizeof(str2_onstack) \
63
 
         && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
64
 
 
65
 
#ifndef UNIV_HOTBACKUP
66
60
/***********************************************************************
67
61
Determine if the given name is a name reserved for MySQL system tables. */
68
62
static
82
76
               || 0 == strcmp(name + 6, "user")
83
77
               || 0 == strcmp(name + 6, "db"));
84
78
}
85
 
#endif /* !UNIV_HOTBACKUP */
86
 
 
87
 
/*************************************************************************
88
 
If a table is not yet in the drop list, adds the table to the list of tables
89
 
which the master thread drops in background. We need this on Unix because in
90
 
ALTER TABLE MySQL may call drop table even if the table has running queries on
91
 
it. Also, if there are running foreign key checks on the table, we drop the
92
 
table lazily. */
93
 
static
94
 
ibool
95
 
row_add_table_to_background_drop_list(
96
 
/*==================================*/
97
 
                                /* out: TRUE if the table was not yet in the
98
 
                                drop list, and was added there */
99
 
        const char*     name);  /* in: table name */
100
79
 
101
80
/***********************************************************************
102
81
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
112
91
 
113
92
/***********************************************************************
114
93
Frees the blob heap in prebuilt when no longer needed. */
115
 
UNIV_INTERN
 
94
 
116
95
void
117
96
row_mysql_prebuilt_free_blob_heap(
118
97
/*==============================*/
126
105
/***********************************************************************
127
106
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
128
107
format. */
129
 
UNIV_INTERN
 
108
 
130
109
byte*
131
110
row_mysql_store_true_var_len(
132
111
/*=========================*/
155
134
/***********************************************************************
156
135
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
157
136
returns a pointer to the data. */
158
 
UNIV_INTERN
159
 
const byte*
 
137
 
 
138
byte*
160
139
row_mysql_read_true_varchar(
161
140
/*========================*/
162
 
                                /* out: pointer to the data, we skip
163
 
                                the 1 or 2 bytes at the start that are
164
 
                                used to store the len */
165
 
        ulint*          len,    /* out: variable-length field length */
166
 
        const byte*     field,  /* in: field in the MySQL format */
167
 
        ulint           lenlen) /* in: storage length of len: either 1
168
 
                                or 2 bytes */
 
141
                        /* out: pointer to the data, we skip the 1 or 2 bytes
 
142
                        at the start that are used to store the len */
 
143
        ulint*  len,    /* out: variable-length field length */
 
144
        byte*   field,  /* in: field in the MySQL format */
 
145
        ulint   lenlen) /* in: storage length of len: either 1 or 2 bytes */
169
146
{
170
147
        if (lenlen == 2) {
171
148
                *len = mach_read_from_2_little_endian(field);
182
159
 
183
160
/***********************************************************************
184
161
Stores a reference to a BLOB in the MySQL format. */
185
 
UNIV_INTERN
 
162
 
186
163
void
187
164
row_mysql_store_blob_ref(
188
165
/*=====================*/
189
 
        byte*           dest,   /* in: where to store */
190
 
        ulint           col_len,/* in: dest buffer size: determines into
 
166
        byte*   dest,           /* in: where to store */
 
167
        ulint   col_len,        /* in: dest buffer size: determines into
191
168
                                how many bytes the BLOB length is stored,
192
169
                                the space for the length may vary from 1
193
170
                                to 4 bytes */
194
 
        const void*     data,   /* in: BLOB data; if the value to store
 
171
        byte*   data,           /* in: BLOB data; if the value to store
195
172
                                is SQL NULL this should be NULL pointer */
196
 
        ulint           len)    /* in: BLOB length; if the value to store
 
173
        ulint   len)            /* in: BLOB length; if the value to store
197
174
                                is SQL NULL this should be 0; remember
198
175
                                also to set the NULL bit in the MySQL record
199
176
                                header! */
214
191
 
215
192
        mach_write_to_n_little_endian(dest, col_len - 8, len);
216
193
 
217
 
        memcpy(dest + col_len - 8, &data, sizeof data);
 
194
        ut_memcpy(dest + col_len - 8, &data, sizeof(byte*));
218
195
}
219
196
 
220
197
/***********************************************************************
221
198
Reads a reference to a BLOB in the MySQL format. */
222
 
UNIV_INTERN
223
 
const byte*
 
199
 
 
200
byte*
224
201
row_mysql_read_blob_ref(
225
202
/*====================*/
226
 
                                        /* out: pointer to BLOB data */
227
 
        ulint*          len,            /* out: BLOB length */
228
 
        const byte*     ref,            /* in: BLOB reference in the
229
 
                                        MySQL format */
230
 
        ulint           col_len)        /* in: BLOB reference length
231
 
                                        (not BLOB length) */
 
203
                                /* out: pointer to BLOB data */
 
204
        ulint*  len,            /* out: BLOB length */
 
205
        byte*   ref,            /* in: BLOB reference in the MySQL format */
 
206
        ulint   col_len)        /* in: BLOB reference length (not BLOB
 
207
                                length) */
232
208
{
233
209
        byte*   data;
234
210
 
235
211
        *len = mach_read_from_n_little_endian(ref, col_len - 8);
236
212
 
237
 
        memcpy(&data, ref + col_len - 8, sizeof data);
 
213
        ut_memcpy(&data, ref + col_len - 8, sizeof(byte*));
238
214
 
239
215
        return(data);
240
216
}
243
219
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
244
220
The counterpart of this function is row_sel_field_store_in_mysql_format() in
245
221
row0sel.c. */
246
 
UNIV_INTERN
 
222
 
247
223
byte*
248
224
row_mysql_store_col_in_innobase_format(
249
225
/*===================================*/
262
238
                                        format differs in a row and in a
263
239
                                        key value: in a key value the length
264
240
                                        is always stored in 2 bytes! */
265
 
        const byte*     mysql_data,     /* in: MySQL column value, not
 
241
        byte*           mysql_data,     /* in: MySQL column value, not
266
242
                                        SQL NULL; NOTE that dfield may also
267
243
                                        get a pointer to mysql_data,
268
244
                                        therefore do not discard this as long
275
251
                                        VARCHAR then this is irrelevant */
276
252
        ulint           comp)           /* in: nonzero=compact format */
277
253
{
278
 
        const byte*     ptr     = mysql_data;
279
 
        const dtype_t*  dtype;
 
254
        byte*           ptr     = mysql_data;
 
255
        dtype_t*        dtype;
280
256
        ulint           type;
281
257
        ulint           lenlen;
282
258
 
289
265
                sign bit negated if the data is a signed integer. In MySQL,
290
266
                integers are stored in a little-endian format. */
291
267
 
292
 
                byte*   p = buf + col_len;
 
268
                ptr = buf + col_len;
293
269
 
294
270
                for (;;) {
295
 
                        p--;
296
 
                        *p = *mysql_data;
297
 
                        if (p == buf) {
 
271
                        ptr--;
 
272
                        *ptr = *mysql_data;
 
273
                        if (ptr == buf) {
298
274
                                break;
299
275
                        }
300
276
                        mysql_data++;
302
278
 
303
279
                if (!(dtype->prtype & DATA_UNSIGNED)) {
304
280
 
305
 
                        *buf ^= 128;
 
281
                        *ptr = (byte) (*ptr ^ 128);
306
282
                }
307
283
 
308
 
                ptr = buf;
309
284
                buf += col_len;
310
285
        } else if ((type == DATA_VARCHAR
311
286
                    || type == DATA_VARMYSQL
439
414
 
440
415
                                /* It is SQL NULL */
441
416
 
442
 
                                dfield_set_null(dfield);
 
417
                                dfield_set_data(dfield, NULL, UNIV_SQL_NULL);
443
418
 
444
419
                                goto next_column;
445
420
                        }
459
434
 
460
435
/********************************************************************
461
436
Handles user errors and lock waits detected by the database engine. */
462
 
UNIV_INTERN
 
437
 
463
438
ibool
464
439
row_mysql_handle_errors(
465
440
/*====================*/
483
458
 
484
459
        trx->error_state = DB_SUCCESS;
485
460
 
486
 
        switch (err) {
487
 
        case DB_LOCK_WAIT_TIMEOUT:
488
 
                if (row_rollback_on_timeout) {
489
 
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
490
 
                        break;
491
 
                }
492
 
                /* fall through */
493
 
        case DB_DUPLICATE_KEY:
494
 
        case DB_FOREIGN_DUPLICATE_KEY:
495
 
        case DB_TOO_BIG_RECORD:
496
 
        case DB_ROW_IS_REFERENCED:
497
 
        case DB_NO_REFERENCED_ROW:
498
 
        case DB_CANNOT_ADD_CONSTRAINT:
499
 
        case DB_TOO_MANY_CONCURRENT_TRXS:
500
 
        case DB_OUT_OF_FILE_SPACE:
501
 
                if (savept) {
502
 
                        /* Roll back the latest, possibly incomplete
503
 
                        insertion or update */
504
 
 
505
 
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
506
 
                }
507
 
                /* MySQL will roll back the latest SQL statement */
508
 
                break;
509
 
        case DB_LOCK_WAIT:
 
461
        if ((err == DB_DUPLICATE_KEY)
 
462
            || (err == DB_FOREIGN_DUPLICATE_KEY)) {
 
463
                if (savept) {
 
464
                        /* Roll back the latest, possibly incomplete
 
465
                        insertion or update */
 
466
 
 
467
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
 
468
                }
 
469
        } else if (err == DB_TOO_BIG_RECORD) {
 
470
                if (savept) {
 
471
                        /* Roll back the latest, possibly incomplete
 
472
                        insertion or update */
 
473
 
 
474
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
 
475
                }
 
476
                /* MySQL will roll back the latest SQL statement */
 
477
        } else if (err == DB_ROW_IS_REFERENCED
 
478
                   || err == DB_NO_REFERENCED_ROW
 
479
                   || err == DB_CANNOT_ADD_CONSTRAINT
 
480
                   || err == DB_TOO_MANY_CONCURRENT_TRXS) {
 
481
                if (savept) {
 
482
                        /* Roll back the latest, possibly incomplete
 
483
                        insertion or update */
 
484
 
 
485
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
 
486
                }
 
487
                /* MySQL will roll back the latest SQL statement */
 
488
        } else if (err == DB_LOCK_WAIT) {
 
489
 
510
490
                srv_suspend_mysql_thread(thr);
511
491
 
512
492
                if (trx->error_state != DB_SUCCESS) {
519
499
 
520
500
                return(TRUE);
521
501
 
522
 
        case DB_DEADLOCK:
523
 
        case DB_LOCK_TABLE_FULL:
 
502
        } else if (err == DB_DEADLOCK
 
503
                   || err == DB_LOCK_TABLE_FULL
 
504
                   || (err == DB_LOCK_WAIT_TIMEOUT
 
505
                       && row_rollback_on_timeout)) {
524
506
                /* Roll back the whole transaction; this resolution was added
525
507
                to version 3.23.43 */
526
508
 
527
509
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
528
 
                break;
529
 
 
530
 
        case DB_MUST_GET_MORE_FILE_SPACE:
 
510
 
 
511
        } else if (err == DB_OUT_OF_FILE_SPACE
 
512
                   || err == DB_LOCK_WAIT_TIMEOUT) {
 
513
 
 
514
                ut_ad(!(err == DB_LOCK_WAIT_TIMEOUT
 
515
                        && row_rollback_on_timeout));
 
516
 
 
517
                if (savept) {
 
518
                        /* Roll back the latest, possibly incomplete
 
519
                        insertion or update */
 
520
 
 
521
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
 
522
                }
 
523
                /* MySQL will roll back the latest SQL statement */
 
524
 
 
525
        } else if (err == DB_MUST_GET_MORE_FILE_SPACE) {
 
526
 
531
527
                fputs("InnoDB: The database cannot continue"
532
528
                      " operation because of\n"
533
529
                      "InnoDB: lack of space. You must add"
535
531
                      "InnoDB: my.cnf and restart the database.\n", stderr);
536
532
 
537
533
                exit(1);
 
534
        } else if (err == DB_CORRUPTION) {
538
535
 
539
 
        case DB_CORRUPTION:
540
536
                fputs("InnoDB: We detected index corruption"
541
537
                      " in an InnoDB type table.\n"
542
538
                      "InnoDB: You have to dump + drop + reimport"
551
547
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
552
548
                      "forcing-recovery.html"
553
549
                      " for help.\n", stderr);
554
 
                break;
555
 
        default:
 
550
 
 
551
        } else {
556
552
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
557
553
                        (ulong) err);
558
554
                ut_error;
578
574
 
579
575
/************************************************************************
580
576
Create a prebuilt struct for a MySQL table handle. */
581
 
UNIV_INTERN
 
577
 
582
578
row_prebuilt_t*
583
579
row_create_prebuilt(
584
580
/*================*/
590
586
        dict_index_t*   clust_index;
591
587
        dtuple_t*       ref;
592
588
        ulint           ref_len;
593
 
 
594
 
        heap = mem_heap_create(sizeof *prebuilt + 128);
595
 
 
596
 
        prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
 
589
        ulint           i;
 
590
 
 
591
        heap = mem_heap_create(128);
 
592
 
 
593
        prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
597
594
 
598
595
        prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
599
596
        prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
600
597
 
601
598
        prebuilt->table = table;
602
599
 
 
600
        prebuilt->trx = NULL;
 
601
 
603
602
        prebuilt->sql_stat_start = TRUE;
 
603
 
 
604
        prebuilt->mysql_has_locked = FALSE;
 
605
 
 
606
        prebuilt->index = NULL;
 
607
 
 
608
        prebuilt->used_in_HANDLER = FALSE;
 
609
 
 
610
        prebuilt->n_template = 0;
 
611
        prebuilt->mysql_template = NULL;
 
612
 
604
613
        prebuilt->heap = heap;
 
614
        prebuilt->ins_node = NULL;
 
615
 
 
616
        prebuilt->ins_upd_rec_buff = NULL;
 
617
 
 
618
        prebuilt->upd_node = NULL;
 
619
        prebuilt->ins_graph = NULL;
 
620
        prebuilt->upd_graph = NULL;
605
621
 
606
622
        prebuilt->pcur = btr_pcur_create_for_mysql();
607
623
        prebuilt->clust_pcur = btr_pcur_create_for_mysql();
609
625
        prebuilt->select_lock_type = LOCK_NONE;
610
626
        prebuilt->stored_select_lock_type = 99999999;
611
627
 
 
628
        prebuilt->row_read_type = ROW_READ_WITH_LOCKS;
 
629
 
 
630
        prebuilt->sel_graph = NULL;
 
631
 
612
632
        prebuilt->search_tuple = dtuple_create(
613
633
                heap, 2 * dict_table_get_n_cols(table));
614
634
 
625
645
 
626
646
        prebuilt->clust_ref = ref;
627
647
 
 
648
        for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
 
649
                prebuilt->fetch_cache[i] = NULL;
 
650
        }
 
651
 
 
652
        prebuilt->n_fetch_cached = 0;
 
653
 
 
654
        prebuilt->blob_heap = NULL;
 
655
 
 
656
        prebuilt->old_vers_heap = NULL;
 
657
 
 
658
        prebuilt->last_value = 0;
 
659
 
628
660
        return(prebuilt);
629
661
}
630
662
 
631
663
/************************************************************************
632
664
Free a prebuilt struct for a MySQL table handle. */
633
 
UNIV_INTERN
 
665
 
634
666
void
635
667
row_prebuilt_free(
636
668
/*==============*/
637
 
        row_prebuilt_t* prebuilt,       /* in, own: prebuilt struct */
638
 
        ibool           dict_locked)    /* in: TRUE=data dictionary locked */
 
669
        row_prebuilt_t* prebuilt)       /* in, own: prebuilt struct */
639
670
{
640
671
        ulint   i;
641
672
 
642
 
        if (UNIV_UNLIKELY
643
 
            (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED
644
 
             || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED)) {
645
 
 
 
673
        if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED
 
674
            || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) {
646
675
                fprintf(stderr,
647
676
                        "InnoDB: Error: trying to free a corrupt\n"
648
677
                        "InnoDB: table handle. Magic n %lu,"
649
 
                        " magic n2 %lu, table name ",
 
678
                        " magic n2 %lu, table name",
650
679
                        (ulong) prebuilt->magic_n,
651
680
                        (ulong) prebuilt->magic_n2);
652
681
                ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
708
737
                }
709
738
        }
710
739
 
711
 
        dict_table_decrement_handle_count(prebuilt->table, dict_locked);
 
740
        dict_table_decrement_handle_count(prebuilt->table);
712
741
 
713
742
        mem_heap_free(prebuilt->heap);
714
743
}
716
745
/*************************************************************************
717
746
Updates the transaction pointers in query graphs stored in the prebuilt
718
747
struct. */
719
 
UNIV_INTERN
 
748
 
720
749
void
721
750
row_update_prebuilt_trx(
722
751
/*====================*/
739
768
        if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
740
769
                fprintf(stderr,
741
770
                        "InnoDB: Error: trying to use a corrupt\n"
742
 
                        "InnoDB: table handle. Magic n %lu, table name ",
 
771
                        "InnoDB: table handle. Magic n %lu, table name",
743
772
                        (ulong) prebuilt->magic_n);
744
 
                ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
 
773
                ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
745
774
                putc('\n', stderr);
746
775
 
747
776
                mem_analyze_corruption(prebuilt);
780
809
        ins_node_t*     node;
781
810
        dtuple_t*       row;
782
811
        dict_table_t*   table   = prebuilt->table;
 
812
        ulint           i;
783
813
 
784
814
        ut_ad(prebuilt && table && prebuilt->trx);
785
815
 
802
832
 
803
833
                dict_table_copy_types(row, table);
804
834
 
 
835
                /* We init the value of every field to the SQL NULL to avoid
 
836
                a debug assertion from failing */
 
837
 
 
838
                for (i = 0; i < dtuple_get_n_fields(row); i++) {
 
839
 
 
840
                        dtuple_get_nth_field(row, i)->len = UNIV_SQL_NULL;
 
841
                }
 
842
 
805
843
                ins_node_set_new_row(node, row);
806
844
 
807
845
                prebuilt->ins_graph = que_node_get_parent(
836
874
        a counter table which is very small and updated very often. */
837
875
 
838
876
        if (counter > 2000000000
839
 
            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
 
877
            || ((ib_longlong)counter > 16 + table->stat_n_rows / 16)) {
840
878
 
841
879
                dict_update_statistics(table);
842
880
        }
844
882
 
845
883
/*************************************************************************
846
884
Unlocks an AUTO_INC type lock possibly reserved by trx. */
847
 
UNIV_INTERN
 
885
 
848
886
void
849
887
row_unlock_table_autoinc_for_mysql(
850
888
/*===============================*/
864
902
table. The lock is reserved only for the duration of an SQL statement.
865
903
It is not compatible with another AUTO_INC or exclusive lock on the
866
904
table. */
867
 
UNIV_INTERN
 
905
 
868
906
int
869
907
row_lock_table_autoinc_for_mysql(
870
908
/*=============================*/
936
974
 
937
975
/*************************************************************************
938
976
Sets a table lock on the table mentioned in prebuilt. */
939
 
UNIV_INTERN
 
977
 
940
978
int
941
979
row_lock_table_for_mysql(
942
980
/*=====================*/
1013
1051
 
1014
1052
/*************************************************************************
1015
1053
Does an insert for MySQL. */
1016
 
UNIV_INTERN
 
1054
 
1017
1055
int
1018
1056
row_insert_for_mysql(
1019
1057
/*=================*/
1050
1088
                return(DB_ERROR);
1051
1089
        }
1052
1090
 
1053
 
        if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
 
1091
        if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
1054
1092
                fprintf(stderr,
1055
1093
                        "InnoDB: Error: trying to free a corrupt\n"
1056
 
                        "InnoDB: table handle. Magic n %lu, table name ",
 
1094
                        "InnoDB: table handle. Magic n %lu, table name",
1057
1095
                        (ulong) prebuilt->magic_n);
1058
 
                ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
 
1096
                ut_print_name(stderr, prebuilt->trx, TRUE,
 
1097
                              prebuilt->table->name);
1059
1098
                putc('\n', stderr);
1060
1099
 
1061
1100
                mem_analyze_corruption(prebuilt);
1063
1102
                ut_error;
1064
1103
        }
1065
1104
 
1066
 
        if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
 
1105
        if (srv_created_new_raw || srv_force_recovery) {
1067
1106
                fputs("InnoDB: A new raw disk partition was initialized or\n"
1068
1107
                      "InnoDB: innodb_force_recovery is on: we do not allow\n"
1069
1108
                      "InnoDB: database modifications by the user. Shut down\n"
1146
1185
 
1147
1186
/*************************************************************************
1148
1187
Builds a dummy query graph used in selects. */
1149
 
UNIV_INTERN
 
1188
 
1150
1189
void
1151
1190
row_prebuild_sel_graph(
1152
1191
/*===================*/
1173
1212
/*************************************************************************
1174
1213
Creates an query graph node of 'update' type to be used in the MySQL
1175
1214
interface. */
1176
 
UNIV_INTERN
 
1215
 
1177
1216
upd_node_t*
1178
1217
row_create_update_node_for_mysql(
1179
1218
/*=============================*/
1211
1250
Gets pointer to a prebuilt update vector used in updates. If the update
1212
1251
graph has not yet been built in the prebuilt struct, then this function
1213
1252
first builds it. */
1214
 
UNIV_INTERN
 
1253
 
1215
1254
upd_t*
1216
1255
row_get_prebuilt_update_vector(
1217
1256
/*===========================*/
1245
1284
 
1246
1285
/*************************************************************************
1247
1286
Does an update or delete of a row for MySQL. */
1248
 
UNIV_INTERN
 
1287
 
1249
1288
int
1250
1289
row_update_for_mysql(
1251
1290
/*=================*/
1287
1326
                return(DB_ERROR);
1288
1327
        }
1289
1328
 
1290
 
        if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
 
1329
        if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
1291
1330
                fprintf(stderr,
1292
1331
                        "InnoDB: Error: trying to free a corrupt\n"
1293
 
                        "InnoDB: table handle. Magic n %lu, table name ",
 
1332
                        "InnoDB: table handle. Magic n %lu, table name",
1294
1333
                        (ulong) prebuilt->magic_n);
1295
 
                ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
 
1334
                ut_print_name(stderr, prebuilt->trx, TRUE,
 
1335
                              prebuilt->table->name);
1296
1336
                putc('\n', stderr);
1297
1337
 
1298
1338
                mem_analyze_corruption(prebuilt);
1300
1340
                ut_error;
1301
1341
        }
1302
1342
 
1303
 
        if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
 
1343
        if (srv_created_new_raw || srv_force_recovery) {
1304
1344
                fputs("InnoDB: A new raw disk partition was initialized or\n"
1305
1345
                      "InnoDB: innodb_force_recovery is on: we do not allow\n"
1306
1346
                      "InnoDB: database modifications by the user. Shut down\n"
1410
1450
LOCK_X type.
1411
1451
Thus, this implements a 'mini-rollback' that releases the latest record
1412
1452
locks we set. */
1413
 
UNIV_INTERN
 
1453
 
1414
1454
int
1415
1455
row_unlock_for_mysql(
1416
1456
/*=================*/
1460
1500
 
1461
1501
                rec = btr_pcur_get_rec(pcur);
1462
1502
 
1463
 
                lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1464
 
                                rec, prebuilt->select_lock_type);
 
1503
                lock_rec_unlock(trx, rec, prebuilt->select_lock_type);
1465
1504
 
1466
1505
                mtr_commit(&mtr);
1467
1506
 
1470
1509
                reset locks on clust_pcur. The values in clust_pcur may be
1471
1510
                garbage! */
1472
1511
 
1473
 
                if (dict_index_is_clust(index)) {
 
1512
                if (index->type & DICT_CLUSTERED) {
1474
1513
 
1475
1514
                        goto func_exit;
1476
1515
                }
1491
1530
 
1492
1531
                rec = btr_pcur_get_rec(clust_pcur);
1493
1532
 
1494
 
                lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
1495
 
                                rec, prebuilt->select_lock_type);
 
1533
                lock_rec_unlock(trx, rec, prebuilt->select_lock_type);
1496
1534
 
1497
1535
                mtr_commit(&mtr);
1498
1536
        }
1505
1543
 
1506
1544
/**************************************************************************
1507
1545
Does a cascaded delete or set null in a foreign key operation. */
1508
 
UNIV_INTERN
 
1546
 
1509
1547
ulint
1510
1548
row_update_cascade_for_mysql(
1511
1549
/*=========================*/
1575
1613
/*************************************************************************
1576
1614
Checks if a table is such that we automatically created a clustered
1577
1615
index on it (on row id). */
1578
 
UNIV_INTERN
 
1616
 
1579
1617
ibool
1580
1618
row_table_got_default_clust_index(
1581
1619
/*==============================*/
1582
 
        const dict_table_t*     table)
 
1620
        dict_table_t*   table)
1583
1621
{
1584
1622
        const dict_index_t*     clust_index;
1585
1623
 
1591
1629
/*************************************************************************
1592
1630
Calculates the key number used inside MySQL for an Innobase index. We have
1593
1631
to take into account if we generated a default clustered index for the table */
1594
 
UNIV_INTERN
 
1632
 
1595
1633
ulint
1596
1634
row_get_mysql_key_number_for_index(
1597
1635
/*===============================*/
1598
 
        const dict_index_t*     index)
 
1636
        dict_index_t*   index)
1599
1637
{
1600
 
        const dict_index_t*     ind;
1601
 
        ulint                   i;
 
1638
        dict_index_t*   ind;
 
1639
        ulint           i;
1602
1640
 
1603
1641
        ut_a(index);
1604
1642
 
1621
1659
/*************************************************************************
1622
1660
Locks the data dictionary in shared mode from modifications, for performing
1623
1661
foreign key check, rollback, or other operation invisible to MySQL. */
1624
 
UNIV_INTERN
 
1662
 
1625
1663
void
1626
1664
row_mysql_freeze_data_dictionary(
1627
1665
/*=============================*/
1636
1674
 
1637
1675
/*************************************************************************
1638
1676
Unlocks the data dictionary shared lock. */
1639
 
UNIV_INTERN
 
1677
 
1640
1678
void
1641
1679
row_mysql_unfreeze_data_dictionary(
1642
1680
/*===============================*/
1652
1690
/*************************************************************************
1653
1691
Locks the data dictionary exclusively for performing a table create or other
1654
1692
data dictionary modification operation. */
1655
 
UNIV_INTERN
 
1693
 
1656
1694
void
1657
1695
row_mysql_lock_data_dictionary(
1658
1696
/*===========================*/
1672
1710
 
1673
1711
/*************************************************************************
1674
1712
Unlocks the data dictionary exclusive lock. */
1675
 
UNIV_INTERN
 
1713
 
1676
1714
void
1677
1715
row_mysql_unlock_data_dictionary(
1678
1716
/*=============================*/
1689
1727
        trx->dict_operation_lock_mode = 0;
1690
1728
}
1691
1729
 
1692
 
#ifndef UNIV_HOTBACKUP
1693
1730
/*************************************************************************
1694
 
Creates a table for MySQL. If the name of the table ends in
 
1731
Drops a table for MySQL. If the name of the table ends in
1695
1732
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1696
1733
"innodb_table_monitor", then this will also start the printing of monitor
1697
1734
output by the master thread. If the table name ends in "innodb_mem_validate",
1698
1735
InnoDB will try to invoke mem_validate(). */
1699
 
UNIV_INTERN
 
1736
 
1700
1737
int
1701
1738
row_create_table_for_mysql(
1702
1739
/*=======================*/
1725
1762
                      " by the user.\n"
1726
1763
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1727
1764
                      " is replaced with raw.\n", stderr);
1728
 
err_exit:
 
1765
 
1729
1766
                dict_mem_table_free(table);
1730
1767
                trx_commit_for_mysql(trx);
1731
1768
 
1742
1779
                        "InnoDB: MySQL system tables must be"
1743
1780
                        " of the MyISAM type!\n",
1744
1781
                        table->name);
1745
 
                goto err_exit;
 
1782
 
 
1783
                dict_mem_table_free(table);
 
1784
                trx_commit_for_mysql(trx);
 
1785
 
 
1786
                return(DB_ERROR);
1746
1787
        }
1747
1788
 
1748
1789
        /* Check that no reserved column names are used. */
1750
1791
                if (dict_col_name_is_reserved(
1751
1792
                            dict_table_get_col_name(table, i))) {
1752
1793
 
1753
 
                        goto err_exit;
 
1794
                        dict_mem_table_free(table);
 
1795
                        trx_commit_for_mysql(trx);
 
1796
 
 
1797
                        return(DB_ERROR);
1754
1798
                }
1755
1799
        }
1756
1800
 
1765
1809
        table_name++;
1766
1810
        table_name_len = strlen(table_name) + 1;
1767
1811
 
1768
 
        if (STR_EQ(table_name, table_name_len, S_innodb_monitor)) {
 
1812
        if (table_name_len == sizeof S_innodb_monitor
 
1813
            && !memcmp(table_name, S_innodb_monitor,
 
1814
                       sizeof S_innodb_monitor)) {
1769
1815
 
1770
1816
                /* Table equals "innodb_monitor":
1771
1817
                start monitor prints */
1776
1822
                of InnoDB monitor prints */
1777
1823
 
1778
1824
                os_event_set(srv_lock_timeout_thread_event);
1779
 
        } else if (STR_EQ(table_name, table_name_len,
1780
 
                          S_innodb_lock_monitor)) {
 
1825
        } else if (table_name_len == sizeof S_innodb_lock_monitor
 
1826
                   && !memcmp(table_name, S_innodb_lock_monitor,
 
1827
                              sizeof S_innodb_lock_monitor)) {
1781
1828
 
1782
1829
                srv_print_innodb_monitor = TRUE;
1783
1830
                srv_print_innodb_lock_monitor = TRUE;
1784
1831
                os_event_set(srv_lock_timeout_thread_event);
1785
 
        } else if (STR_EQ(table_name, table_name_len,
1786
 
                          S_innodb_tablespace_monitor)) {
 
1832
        } else if (table_name_len == sizeof S_innodb_tablespace_monitor
 
1833
                   && !memcmp(table_name, S_innodb_tablespace_monitor,
 
1834
                              sizeof S_innodb_tablespace_monitor)) {
1787
1835
 
1788
1836
                srv_print_innodb_tablespace_monitor = TRUE;
1789
1837
                os_event_set(srv_lock_timeout_thread_event);
1790
 
        } else if (STR_EQ(table_name, table_name_len,
1791
 
                          S_innodb_table_monitor)) {
 
1838
        } else if (table_name_len == sizeof S_innodb_table_monitor
 
1839
                   && !memcmp(table_name, S_innodb_table_monitor,
 
1840
                              sizeof S_innodb_table_monitor)) {
1792
1841
 
1793
1842
                srv_print_innodb_table_monitor = TRUE;
1794
1843
                os_event_set(srv_lock_timeout_thread_event);
1795
 
        } else if (STR_EQ(table_name, table_name_len,
1796
 
                          S_innodb_mem_validate)) {
 
1844
        } else if (table_name_len == sizeof S_innodb_mem_validate
 
1845
                   && !memcmp(table_name, S_innodb_mem_validate,
 
1846
                              sizeof S_innodb_mem_validate)) {
1797
1847
                /* We define here a debugging feature intended for
1798
1848
                developers */
1799
1849
 
1815
1865
 
1816
1866
        heap = mem_heap_create(512);
1817
1867
 
1818
 
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
 
1868
        trx->dict_operation = TRUE;
1819
1869
 
1820
1870
        node = tab_create_graph_create(table, heap);
1821
1871
 
1826
1876
 
1827
1877
        err = trx->error_state;
1828
1878
 
1829
 
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
 
1879
        if (err != DB_SUCCESS) {
 
1880
                /* We have special error handling here */
 
1881
 
1830
1882
                trx->error_state = DB_SUCCESS;
 
1883
 
1831
1884
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1832
 
        }
1833
 
 
1834
 
        switch (err) {
1835
 
        case DB_OUT_OF_FILE_SPACE:
1836
 
                ut_print_timestamp(stderr);
1837
 
                fputs("  InnoDB: Warning: cannot create table ",
1838
 
                      stderr);
1839
 
                ut_print_name(stderr, trx, TRUE, table->name);
1840
 
                fputs(" because tablespace full\n", stderr);
1841
 
 
1842
 
                if (dict_table_get_low(table->name)) {
1843
 
 
1844
 
                        row_drop_table_for_mysql(table->name, trx, FALSE);
 
1885
 
 
1886
                if (err == DB_OUT_OF_FILE_SPACE) {
 
1887
                        ut_print_timestamp(stderr);
 
1888
 
 
1889
                        fputs("  InnoDB: Warning: cannot create table ",
 
1890
                              stderr);
 
1891
                        ut_print_name(stderr, trx, TRUE, table->name);
 
1892
                        fputs(" because tablespace full\n", stderr);
 
1893
 
 
1894
                        if (dict_table_get_low(table->name)) {
 
1895
 
 
1896
                                row_drop_table_for_mysql(table->name, trx,
 
1897
                                                         FALSE);
 
1898
                        }
 
1899
 
 
1900
                } else if (err == DB_DUPLICATE_KEY) {
 
1901
                        ut_print_timestamp(stderr);
 
1902
 
 
1903
                        fputs("  InnoDB: Error: table ", stderr);
 
1904
                        ut_print_name(stderr, trx, TRUE, table->name);
 
1905
                        fputs(" already exists in InnoDB internal\n"
 
1906
                              "InnoDB: data dictionary. Have you deleted"
 
1907
                              " the .frm file\n"
 
1908
                              "InnoDB: and not used DROP TABLE?"
 
1909
                              " Have you used DROP DATABASE\n"
 
1910
                              "InnoDB: for InnoDB tables in"
 
1911
                              " MySQL version <= 3.23.43?\n"
 
1912
                              "InnoDB: See the Restrictions section"
 
1913
                              " of the InnoDB manual.\n"
 
1914
                              "InnoDB: You can drop the orphaned table"
 
1915
                              " inside InnoDB by\n"
 
1916
                              "InnoDB: creating an InnoDB table with"
 
1917
                              " the same name in another\n"
 
1918
                              "InnoDB: database and copying the .frm file"
 
1919
                              " to the current database.\n"
 
1920
                              "InnoDB: Then MySQL thinks the table exists,"
 
1921
                              " and DROP TABLE will\n"
 
1922
                              "InnoDB: succeed.\n"
 
1923
                              "InnoDB: You can look for further help from\n"
 
1924
                              "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
 
1925
                              "innodb-troubleshooting.html\n",
 
1926
                              stderr);
1845
1927
                }
1846
 
                break;
1847
 
 
1848
 
        case DB_DUPLICATE_KEY:
1849
 
                ut_print_timestamp(stderr);
1850
 
                fputs("  InnoDB: Error: table ", stderr);
1851
 
                ut_print_name(stderr, trx, TRUE, table->name);
1852
 
                fputs(" already exists in InnoDB internal\n"
1853
 
                      "InnoDB: data dictionary. Have you deleted"
1854
 
                      " the .frm file\n"
1855
 
                      "InnoDB: and not used DROP TABLE?"
1856
 
                      " Have you used DROP DATABASE\n"
1857
 
                      "InnoDB: for InnoDB tables in"
1858
 
                      " MySQL version <= 3.23.43?\n"
1859
 
                      "InnoDB: See the Restrictions section"
1860
 
                      " of the InnoDB manual.\n"
1861
 
                      "InnoDB: You can drop the orphaned table"
1862
 
                      " inside InnoDB by\n"
1863
 
                      "InnoDB: creating an InnoDB table with"
1864
 
                      " the same name in another\n"
1865
 
                      "InnoDB: database and copying the .frm file"
1866
 
                      " to the current database.\n"
1867
 
                      "InnoDB: Then MySQL thinks the table exists,"
1868
 
                      " and DROP TABLE will\n"
1869
 
                      "InnoDB: succeed.\n"
1870
 
                      "InnoDB: You can look for further help from\n"
1871
 
                      "InnoDB: "
1872
 
                      "http://dev.mysql.com/doc/refman/5.1/en/"
1873
 
                      "innodb-troubleshooting.html\n", stderr);
1874
1928
 
1875
1929
                /* We may also get err == DB_ERROR if the .ibd file for the
1876
1930
                table already exists */
1877
1931
 
1878
 
                break;
 
1932
                trx->error_state = DB_SUCCESS;
1879
1933
        }
1880
1934
 
1881
1935
        que_graph_free((que_t*) que_node_get_parent(thr));
1889
1943
Does an index creation operation for MySQL. TODO: currently failure
1890
1944
to create an index results in dropping the whole table! This is no problem
1891
1945
currently as all indexes must be created at the same time as the table. */
1892
 
UNIV_INTERN
 
1946
 
1893
1947
int
1894
1948
row_create_index_for_mysql(
1895
1949
/*=======================*/
1907
1961
        mem_heap_t*     heap;
1908
1962
        que_thr_t*      thr;
1909
1963
        ulint           err;
1910
 
        ulint           i;
 
1964
        ulint           i, j;
1911
1965
        ulint           len;
1912
 
        char*           table_name;
1913
1966
 
1914
1967
#ifdef UNIV_SYNC_DEBUG
1915
1968
        ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
1919
1972
 
1920
1973
        trx->op_info = "creating index";
1921
1974
 
1922
 
        /* Copy the table name because we may want to drop the
1923
 
        table later, after the index object is freed (inside
1924
 
        que_run_threads()) and thus index->table_name is not available. */
1925
 
        table_name = mem_strdup(index->table_name);
1926
 
 
1927
1975
        trx_start_if_not_started(trx);
1928
1976
 
1929
1977
        /* Check that the same column does not appear twice in the index.
1931
1979
        safer not to allow them. */
1932
1980
 
1933
1981
        for (i = 0; i < dict_index_get_n_fields(index); i++) {
1934
 
                ulint           j;
1935
 
 
1936
1982
                for (j = 0; j < i; j++) {
1937
1983
                        if (0 == ut_strcmp(
1938
1984
                                    dict_index_get_nth_field(index, j)->name,
1939
1985
                                    dict_index_get_nth_field(index, i)->name)) {
 
1986
 
1940
1987
                                ut_print_timestamp(stderr);
1941
1988
 
1942
1989
                                fputs("  InnoDB: Error: column ", stderr);
1973
2020
 
1974
2021
        heap = mem_heap_create(512);
1975
2022
 
1976
 
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
 
2023
        trx->dict_operation = TRUE;
1977
2024
 
1978
2025
        /* Note that the space id where we store the index is inherited from
1979
2026
        the table in dict_build_index_def_step() in dict0crea.c. */
1997
2044
 
1998
2045
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1999
2046
 
2000
 
                row_drop_table_for_mysql(table_name, trx, FALSE);
 
2047
                row_drop_table_for_mysql(index->table_name, trx, FALSE);
2001
2048
 
2002
2049
                trx->error_state = DB_SUCCESS;
2003
2050
        }
2004
2051
 
2005
2052
        trx->op_info = "";
2006
2053
 
2007
 
        mem_free(table_name);
2008
 
 
2009
2054
        return((int) err);
2010
2055
}
2011
2056
 
2017
2062
bot participating tables. The indexes are allowed to contain more
2018
2063
fields than mentioned in the constraint. Check also that foreign key
2019
2064
constraints which reference this table are ok. */
2020
 
UNIV_INTERN
 
2065
 
2021
2066
int
2022
2067
row_table_add_foreign_constraints(
2023
2068
/*==============================*/
2047
2092
 
2048
2093
        trx_start_if_not_started(trx);
2049
2094
 
2050
 
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
 
2095
        trx->dict_operation = TRUE;
2051
2096
 
2052
2097
        err = dict_create_foreign_constraints(trx, sql_string, name,
2053
2098
                                              reject_fks);
2054
 
#ifndef UNIV_HOTBACKUP
 
2099
 
2055
2100
        if (err == DB_SUCCESS) {
2056
2101
                /* Check that also referencing constraints are ok */
2057
2102
                err = dict_load_foreigns(name, TRUE);
2058
2103
        }
2059
 
#endif /* !UNIV_HOTBACKUP */
 
2104
 
2060
2105
        if (err != DB_SUCCESS) {
2061
2106
                /* We have special error handling here */
2062
2107
 
2122
2167
The master thread in srv0srv.c calls this regularly to drop tables which
2123
2168
we must drop in background after queries to them have ended. Such lazy
2124
2169
dropping of tables is needed in ALTER TABLE on Unix. */
2125
 
UNIV_INTERN
 
2170
 
2126
2171
ulint
2127
2172
row_drop_tables_for_mysql_in_background(void)
2128
2173
/*=========================================*/
2181
2226
        UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
2182
2227
 
2183
2228
        ut_print_timestamp(stderr);
2184
 
        fputs("  InnoDB: Dropped table ", stderr);
2185
 
        ut_print_name(stderr, NULL, TRUE, drop->table_name);
2186
 
        fputs(" in background drop queue.\n", stderr);
 
2229
        fprintf(stderr,
 
2230
                "  InnoDB: Dropped table %s in background drop queue.\n",
 
2231
                drop->table_name);
2187
2232
 
2188
2233
        mem_free(drop->table_name);
2189
2234
 
2197
2242
/*************************************************************************
2198
2243
Get the background drop list length. NOTE: the caller must own the kernel
2199
2244
mutex! */
2200
 
UNIV_INTERN
 
2245
 
2201
2246
ulint
2202
2247
row_get_background_drop_list_len_low(void)
2203
2248
/*======================================*/
2226
2271
/*==================================*/
2227
2272
                                /* out: TRUE if the table was not yet in the
2228
2273
                                drop list, and was added there */
2229
 
        const char*     name)   /* in: table name */
 
2274
        dict_table_t*   table)  /* in: table */
2230
2275
{
2231
2276
        row_mysql_drop_t*       drop;
2232
2277
 
2242
2287
        drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
2243
2288
 
2244
2289
        while (drop != NULL) {
2245
 
                if (strcmp(drop->table_name, name) == 0) {
 
2290
                if (strcmp(drop->table_name, table->name) == 0) {
2246
2291
                        /* Already in the list */
2247
2292
 
2248
2293
                        mutex_exit(&kernel_mutex);
2255
2300
 
2256
2301
        drop = mem_alloc(sizeof(row_mysql_drop_t));
2257
2302
 
2258
 
        drop->table_name = mem_strdup(name);
 
2303
        drop->table_name = mem_strdup(table->name);
2259
2304
 
2260
2305
        UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
2261
2306
 
2268
2313
        return(TRUE);
2269
2314
}
2270
2315
 
 
2316
#ifndef UNIV_HOTBACKUP
2271
2317
/*************************************************************************
2272
2318
Discards the tablespace of a table which stored in an .ibd file. Discarding
2273
2319
means that this function deletes the .ibd file and assigns a new table id for
2274
2320
the table. Also the flag table->ibd_file_missing is set TRUE. */
2275
 
UNIV_INTERN
 
2321
 
2276
2322
int
2277
2323
row_discard_tablespace_for_mysql(
2278
2324
/*=============================*/
2385
2431
                ut_print_timestamp(ef);
2386
2432
 
2387
2433
                fputs("  Cannot DISCARD table ", ef);
2388
 
                ut_print_name(stderr, trx, TRUE, name);
 
2434
                ut_print_name(ef, trx, TRUE, name);
2389
2435
                fputs("\n"
2390
2436
                      "because it is referenced by ", ef);
2391
 
                ut_print_name(stderr, trx, TRUE, foreign->foreign_table_name);
 
2437
                ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
2392
2438
                putc('\n', ef);
2393
2439
                mutex_exit(&dict_foreign_err_mutex);
2394
2440
 
2463
2509
/*********************************************************************
2464
2510
Imports a tablespace. The space id in the .ibd file must match the space id
2465
2511
of the table in the data dictionary. */
2466
 
UNIV_INTERN
 
2512
 
2467
2513
int
2468
2514
row_import_tablespace_for_mysql(
2469
2515
/*============================*/
2473
2519
{
2474
2520
        dict_table_t*   table;
2475
2521
        ibool           success;
2476
 
        ib_uint64_t     current_lsn;
 
2522
        dulint          current_lsn;
2477
2523
        ulint           err             = DB_SUCCESS;
2478
2524
 
2479
2525
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2566
2612
 
2567
2613
        ibuf_delete_for_discarded_space(table->space);
2568
2614
 
2569
 
        success = fil_open_single_table_tablespace(
2570
 
                TRUE, table->space,
2571
 
                table->flags == DICT_TF_COMPACT ? 0 : table->flags,
2572
 
                table->name);
 
2615
        success = fil_open_single_table_tablespace(TRUE, table->space,
 
2616
                                                   table->name);
2573
2617
        if (success) {
2574
2618
                table->ibd_file_missing = FALSE;
2575
2619
                table->tablespace_discarded = FALSE;
2600
2644
 
2601
2645
/*************************************************************************
2602
2646
Truncates a table for MySQL. */
2603
 
UNIV_INTERN
 
2647
 
2604
2648
int
2605
2649
row_truncate_table_for_mysql(
2606
2650
/*=========================*/
2618
2662
        btr_pcur_t      pcur;
2619
2663
        mtr_t           mtr;
2620
2664
        dulint          new_id;
2621
 
        ulint           recreate_space = 0;
2622
2665
        pars_info_t*    info = NULL;
2623
2666
 
2624
2667
        /* How do we prevent crashes caused by ongoing operations on
2643
2686
        reallocated, the allocator will remove the ibuf entries for
2644
2687
        it.
2645
2688
 
2646
 
        When we truncate *.ibd files by recreating them (analogous to
2647
 
        DISCARD TABLESPACE), we remove all entries for the table in the
2648
 
        insert buffer tree.  This is not strictly necessary, because
2649
 
        in 6) we will assign a new tablespace identifier, but we can
2650
 
        free up some space in the system tablespace.
 
2689
        TODO: when we truncate *.ibd files (analogous to DISCARD
 
2690
        TABLESPACE), we will have to remove we remove all entries for
 
2691
        the table in the insert buffer tree!
2651
2692
 
2652
2693
        4) Linear readahead and random readahead: we use the same
2653
 
        method as in 3) to discard ongoing operations. (This is only
2654
 
        relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
 
2694
        method as in 3) to discard ongoing operations. (This will only
 
2695
        be relevant for TRUNCATE TABLE by DISCARD TABLESPACE.)
2655
2696
 
2656
2697
        5) FOREIGN KEY operations: if
2657
2698
        table->n_foreign_key_checks_running > 0, we do not allow the
2658
 
        TRUNCATE. We also reserve the data dictionary latch.
2659
 
 
2660
 
        6) Crash recovery: To prevent the application of pre-truncation
2661
 
        redo log records on the truncated tablespace, we will assign
2662
 
        a new tablespace identifier to the truncated tablespace. */
 
2699
        TRUNCATE. We also reserve the data dictionary latch. */
2663
2700
 
2664
2701
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
2665
2702
        ut_ad(table);
2748
2785
 
2749
2786
        trx->table_id = table->id;
2750
2787
 
2751
 
        if (table->space && !table->dir_path_of_temp_table) {
2752
 
                /* Discard and create the single-table tablespace. */
2753
 
                ulint   space   = table->space;
2754
 
                ulint   flags   = fil_space_get_flags(space);
2755
 
 
2756
 
                if (flags != ULINT_UNDEFINED
2757
 
                    && fil_discard_tablespace(space)) {
2758
 
 
2759
 
                        dict_index_t*   index;
2760
 
 
2761
 
                        space = 0;
2762
 
 
2763
 
                        if (fil_create_new_single_table_tablespace(
2764
 
                                    &space, table->name, FALSE, flags,
2765
 
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2766
 
                                ut_print_timestamp(stderr);
2767
 
                                fprintf(stderr,
2768
 
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2769
 
                                        " create a new tablespace\n",
2770
 
                                        table->name);
2771
 
                                table->ibd_file_missing = 1;
2772
 
                                err = DB_ERROR;
2773
 
                                goto funct_exit;
2774
 
                        }
2775
 
 
2776
 
                        recreate_space = space;
2777
 
 
2778
 
                        /* Replace the space_id in the data dictionary cache.
2779
 
                        The persisent data dictionary (SYS_TABLES.SPACE
2780
 
                        and SYS_INDEXES.SPACE) are updated later in this
2781
 
                        function. */
2782
 
                        table->space = space;
2783
 
                        index = dict_table_get_first_index(table);
2784
 
                        do {
2785
 
                                index->space = space;
2786
 
                                index = dict_table_get_next_index(index);
2787
 
                        } while (index);
2788
 
 
2789
 
                        mtr_start(&mtr);
2790
 
                        fsp_header_init(space,
2791
 
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2792
 
                        mtr_commit(&mtr);
2793
 
                }
2794
 
        }
2795
 
 
2796
2788
        /* scan SYS_INDEXES for all indexes of the table */
2797
2789
        heap = mem_heap_create(800);
2798
2790
 
2815
2807
                ulint           len;
2816
2808
                ulint           root_page_no;
2817
2809
 
2818
 
                if (!btr_pcur_is_on_user_rec(&pcur)) {
 
2810
                if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) {
2819
2811
                        /* The end of SYS_INDEXES has been reached. */
2820
2812
                        break;
2821
2813
                }
2837
2829
 
2838
2830
                /* This call may commit and restart mtr
2839
2831
                and reposition pcur. */
2840
 
                root_page_no = dict_truncate_index_tree(table, recreate_space,
2841
 
                                                        &pcur, &mtr);
 
2832
                root_page_no = dict_truncate_index_tree(table, &pcur, &mtr);
2842
2833
 
2843
2834
                rec = btr_pcur_get_rec(&pcur);
2844
2835
 
2870
2861
 
2871
2862
        info = pars_info_create();
2872
2863
 
2873
 
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2874
2864
        pars_info_add_dulint_literal(info, "old_id", table->id);
2875
2865
        pars_info_add_dulint_literal(info, "new_id", new_id);
2876
2866
 
2877
2867
        err = que_eval_sql(info,
2878
2868
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2879
2869
                           "BEGIN\n"
2880
 
                           "UPDATE SYS_TABLES"
2881
 
                           " SET ID = :new_id, SPACE = :space\n"
 
2870
                           "UPDATE SYS_TABLES SET ID = :new_id\n"
2882
2871
                           " WHERE ID = :old_id;\n"
2883
2872
                           "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
2884
2873
                           " WHERE TABLE_ID = :old_id;\n"
2885
 
                           "UPDATE SYS_INDEXES"
2886
 
                           " SET TABLE_ID = :new_id, SPACE = :space\n"
 
2874
                           "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n"
2887
2875
                           " WHERE TABLE_ID = :old_id;\n"
2888
2876
                           "COMMIT WORK;\n"
2889
2877
                           "END;\n"
2924
2912
 
2925
2913
        return((int) err);
2926
2914
}
 
2915
#endif /* !UNIV_HOTBACKUP */
2927
2916
 
2928
2917
/*************************************************************************
2929
2918
Drops a table for MySQL. If the name of the dropped table ends in
2930
2919
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
2931
2920
"innodb_table_monitor", then this will also stop the printing of monitor
2932
2921
output by the master thread. */
2933
 
UNIV_INTERN
 
2922
 
2934
2923
int
2935
2924
row_drop_table_for_mysql(
2936
2925
/*=====================*/
2939
2928
        trx_t*          trx,    /* in: transaction handle */
2940
2929
        ibool           drop_db)/* in: TRUE=dropping whole database */
2941
2930
{
2942
 
        ulint           err;
2943
 
 
2944
 
        err = row_drop_table_for_mysql_no_commit(name, trx, drop_db);
2945
 
        trx_commit_for_mysql(trx);
2946
 
 
2947
 
        return(err);
2948
 
}
2949
 
 
2950
 
/*************************************************************************
2951
 
Drops a table for MySQL but does not commit the transaction.  If the
2952
 
name of the dropped table ends in one of "innodb_monitor",
2953
 
"innodb_lock_monitor", "innodb_tablespace_monitor",
2954
 
"innodb_table_monitor", then this will also stop the printing of
2955
 
monitor output by the master thread. */
2956
 
UNIV_INTERN
2957
 
int
2958
 
row_drop_table_for_mysql_no_commit(
2959
 
/*===============================*/
2960
 
                                /* out: error code or DB_SUCCESS */
2961
 
        const char*     name,   /* in: table name */
2962
 
        trx_t*          trx,    /* in: transaction handle */
2963
 
        ibool           drop_db)/* in: TRUE=dropping whole database */
2964
 
{
2965
2931
        dict_foreign_t* foreign;
2966
2932
        dict_table_t*   table;
2967
2933
        ulint           space_id;
3103
3069
        if (table->n_mysql_handles_opened > 0) {
3104
3070
                ibool   added;
3105
3071
 
3106
 
                added = row_add_table_to_background_drop_list(table->name);
 
3072
                added = row_add_table_to_background_drop_list(table);
3107
3073
 
3108
3074
                if (added) {
3109
3075
                        ut_print_timestamp(stderr);
3119
3085
 
3120
3086
                        /* We return DB_SUCCESS to MySQL though the drop will
3121
3087
                        happen lazily later */
 
3088
 
3122
3089
                        err = DB_SUCCESS;
3123
3090
                } else {
3124
3091
                        /* The table is already in the background drop list */
3136
3103
 
3137
3104
        if (table->n_foreign_key_checks_running > 0) {
3138
3105
 
3139
 
                const char*     table_name = table->name;
3140
 
                ibool           added;
 
3106
                ibool   added;
3141
3107
 
3142
 
                added = row_add_table_to_background_drop_list(table_name);
 
3108
                added = row_add_table_to_background_drop_list(table);
3143
3109
 
3144
3110
                if (added) {
3145
3111
                        ut_print_timestamp(stderr);
3146
3112
                        fputs("  InnoDB: You are trying to drop table ",
3147
3113
                              stderr);
3148
 
                        ut_print_name(stderr, trx, TRUE, table_name);
 
3114
                        ut_print_name(stderr, trx, TRUE, table->name);
3149
3115
                        fputs("\n"
3150
3116
                              "InnoDB: though there is a"
3151
3117
                              " foreign key check running on it.\n"
3169
3135
 
3170
3136
        lock_reset_all_on_table(table);
3171
3137
 
3172
 
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
 
3138
        trx->dict_operation = TRUE;
3173
3139
        trx->table_id = table->id;
3174
3140
 
3175
3141
        /* We use the private SQL parser of Innobase to generate the
3194
3160
                           "WHERE NAME = :table_name\n"
3195
3161
                           "LOCK IN SHARE MODE;\n"
3196
3162
                           "IF (SQL % NOTFOUND) THEN\n"
 
3163
                           "       COMMIT WORK;\n"
3197
3164
                           "       RETURN;\n"
3198
3165
                           "END IF;\n"
3199
3166
                           "found := 1;\n"
3246
3213
                           "WHERE TABLE_ID = table_id;\n"
3247
3214
                           "DELETE FROM SYS_TABLES\n"
3248
3215
                           "WHERE ID = table_id;\n"
 
3216
                           "COMMIT WORK;\n"
3249
3217
                           "END;\n"
3250
3218
                           , FALSE, trx);
3251
3219
 
3329
3297
        }
3330
3298
funct_exit:
3331
3299
 
 
3300
        trx_commit_for_mysql(trx);
 
3301
 
3332
3302
        if (locked_dictionary) {
3333
3303
                row_mysql_unlock_data_dictionary(trx);
3334
3304
        }
3342
3312
        return((int) err);
3343
3313
}
3344
3314
 
3345
 
/***********************************************************************
3346
 
Drop all foreign keys in a database, see Bug#18942.
3347
 
Called at the end of row_drop_database_for_mysql(). */
3348
 
static
3349
 
ulint
3350
 
drop_all_foreign_keys_in_db(
3351
 
/*========================*/
3352
 
                                /* out: error code or DB_SUCCESS */
3353
 
        const char*     name,   /* in: database name which ends to '/' */
3354
 
        trx_t*          trx)    /* in: transaction handle */
3355
 
{
3356
 
        pars_info_t*    pinfo;
3357
 
        ulint           err;
3358
 
 
3359
 
        ut_a(name[strlen(name) - 1] == '/');
3360
 
 
3361
 
        pinfo = pars_info_create();
3362
 
 
3363
 
        pars_info_add_str_literal(pinfo, "dbname", name);
3364
 
 
3365
 
/* true if for_name is not prefixed with dbname */
3366
 
#define TABLE_NOT_IN_THIS_DB \
3367
 
"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3368
 
 
3369
 
        err = que_eval_sql(pinfo,
3370
 
                           "PROCEDURE DROP_ALL_FOREIGN_KEYS_PROC () IS\n"
3371
 
                           "foreign_id CHAR;\n"
3372
 
                           "for_name CHAR;\n"
3373
 
                           "found INT;\n"
3374
 
                           "DECLARE CURSOR cur IS\n"
3375
 
                           "SELECT ID, FOR_NAME FROM SYS_FOREIGN\n"
3376
 
                           "WHERE FOR_NAME >= :dbname\n"
3377
 
                           "LOCK IN SHARE MODE\n"
3378
 
                           "ORDER BY FOR_NAME;\n"
3379
 
                           "BEGIN\n"
3380
 
                           "found := 1;\n"
3381
 
                           "OPEN cur;\n"
3382
 
                           "WHILE found = 1 LOOP\n"
3383
 
                           "        FETCH cur INTO foreign_id, for_name;\n"
3384
 
                           "        IF (SQL % NOTFOUND) THEN\n"
3385
 
                           "                found := 0;\n"
3386
 
                           "        ELSIF (" TABLE_NOT_IN_THIS_DB ") THEN\n"
3387
 
                           "                found := 0;\n"
3388
 
                           "        ELSIF (1=1) THEN\n"
3389
 
                           "                DELETE FROM SYS_FOREIGN_COLS\n"
3390
 
                           "                WHERE ID = foreign_id;\n"
3391
 
                           "                DELETE FROM SYS_FOREIGN\n"
3392
 
                           "                WHERE ID = foreign_id;\n"
3393
 
                           "        END IF;\n"
3394
 
                           "END LOOP;\n"
3395
 
                           "CLOSE cur;\n"
3396
 
                           "COMMIT WORK;\n"
3397
 
                           "END;\n",
3398
 
                           FALSE, /* do not reserve dict mutex,
3399
 
                                  we are already holding it */
3400
 
                           trx);
3401
 
 
3402
 
        return(err);
3403
 
}
3404
 
 
3405
3315
/*************************************************************************
3406
3316
Drops a database for MySQL. */
3407
 
UNIV_INTERN
 
3317
 
3408
3318
int
3409
3319
row_drop_database_for_mysql(
3410
3320
/*========================*/
3472
3382
                }
3473
3383
        }
3474
3384
 
3475
 
        if (err == DB_SUCCESS) {
3476
 
                /* after dropping all tables try to drop all leftover
3477
 
                foreign keys in case orphaned ones exist */
3478
 
                err = (int) drop_all_foreign_keys_in_db(name, trx);
3479
 
 
3480
 
                if (err != DB_SUCCESS) {
3481
 
                        fputs("InnoDB: DROP DATABASE ", stderr);
3482
 
                        ut_print_name(stderr, trx, TRUE, name);
3483
 
                        fprintf(stderr, " failed with error %d while "
3484
 
                                "dropping all foreign keys", err);
3485
 
                }
3486
 
        }
3487
 
 
3488
3385
        trx_commit_for_mysql(trx);
3489
3386
 
3490
3387
        row_mysql_unlock_data_dictionary(trx);
3567
3464
 
3568
3465
/*************************************************************************
3569
3466
Renames a table for MySQL. */
3570
 
UNIV_INTERN
3571
 
ulint
 
3467
 
 
3468
int
3572
3469
row_rename_table_for_mysql(
3573
3470
/*=======================*/
3574
3471
                                        /* out: error code or DB_SUCCESS */
3575
3472
        const char*     old_name,       /* in: old table name */
3576
3473
        const char*     new_name,       /* in: new table name */
3577
 
        trx_t*          trx,            /* in: transaction handle */
3578
 
        ibool           commit)         /* in: if TRUE then commit trx */
 
3474
        trx_t*          trx)            /* in: transaction handle */
3579
3475
{
3580
3476
        dict_table_t*   table;
3581
 
        ulint           err                     = DB_ERROR;
 
3477
        ulint           err;
3582
3478
        mem_heap_t*     heap                    = NULL;
3583
3479
        const char**    constraints_to_drop     = NULL;
3584
3480
        ulint           n_constraints_to_drop   = 0;
3598
3494
                      "InnoDB: with raw, and innodb_force_... is removed.\n",
3599
3495
                      stderr);
3600
3496
 
3601
 
                goto funct_exit;
3602
 
        } else if (row_mysql_is_system_table(new_name)) {
 
3497
                trx_commit_for_mysql(trx);
 
3498
                return(DB_ERROR);
 
3499
        }
 
3500
 
 
3501
        if (row_mysql_is_system_table(new_name)) {
3603
3502
 
3604
3503
                fprintf(stderr,
3605
3504
                        "InnoDB: Error: trying to create a MySQL"
3608
3507
                        " of the MyISAM type!\n",
3609
3508
                        new_name);
3610
3509
 
3611
 
                goto funct_exit;
 
3510
                trx_commit_for_mysql(trx);
 
3511
                return(DB_ERROR);
3612
3512
        }
3613
3513
 
3614
3514
        trx->op_info = "renaming table";
3617
3517
        old_is_tmp = row_is_mysql_tmp_table_name(old_name);
3618
3518
        new_is_tmp = row_is_mysql_tmp_table_name(new_name);
3619
3519
 
 
3520
        /* Serialize data dictionary operations with dictionary mutex:
 
3521
        no deadlocks can occur then in these operations */
 
3522
 
 
3523
        row_mysql_lock_data_dictionary(trx);
 
3524
 
3620
3525
        table = dict_table_get_low(old_name);
3621
3526
 
3622
3527
        if (!table) {
3637
3542
                      "innodb-troubleshooting.html\n",
3638
3543
                      stderr);
3639
3544
                goto funct_exit;
3640
 
        } else if (table->ibd_file_missing) {
 
3545
        }
 
3546
 
 
3547
        if (table->ibd_file_missing) {
3641
3548
                err = DB_TABLE_NOT_FOUND;
3642
3549
                ut_print_timestamp(stderr);
3643
3550
 
3650
3557
                      "innodb-troubleshooting.html\n",
3651
3558
                      stderr);
3652
3559
                goto funct_exit;
3653
 
        } else if (new_is_tmp) {
 
3560
        }
 
3561
 
 
3562
        if (new_is_tmp) {
3654
3563
                /* MySQL is doing an ALTER TABLE command and it renames the
3655
3564
                original table to a temporary table name. We want to preserve
3656
3565
                the original foreign key constraint definitions despite the
3670
3579
        }
3671
3580
 
3672
3581
        /* We use the private SQL parser of Innobase to generate the query
3673
 
        graphs needed in updating the dictionary data from system tables. */
 
3582
        graphs needed in deleting the dictionary data from system tables in
 
3583
        Innobase. Deleting a row from SYS_INDEXES table also frees the file
 
3584
        segments of the B-tree associated with the index. */
3674
3585
 
3675
3586
        info = pars_info_create();
3676
3587
 
3688
3599
        if (err != DB_SUCCESS) {
3689
3600
 
3690
3601
                goto end;
3691
 
        } else if (!new_is_tmp) {
 
3602
        }
 
3603
 
 
3604
        if (!new_is_tmp) {
3692
3605
                /* Rename all constraints. */
3693
3606
 
3694
3607
                info = pars_info_create();
3826
3739
                /* The following call will also rename the .ibd data file if
3827
3740
                the table is stored in a single-table tablespace */
3828
3741
 
3829
 
                if (!dict_table_rename_in_cache(table, new_name,
3830
 
                                                !new_is_tmp)) {
 
3742
                ibool   success = dict_table_rename_in_cache(table, new_name,
 
3743
                                                             !new_is_tmp);
 
3744
 
 
3745
                if (!success) {
3831
3746
                        trx->error_state = DB_SUCCESS;
3832
3747
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
3833
3748
                        trx->error_state = DB_SUCCESS;
 
3749
                        ut_print_timestamp(stderr);
 
3750
                        fputs("  InnoDB: Error in table rename,"
 
3751
                              " cannot rename ", stderr);
 
3752
                        ut_print_name(stderr, trx, TRUE, old_name);
 
3753
                        fputs(" to ", stderr);
 
3754
                        ut_print_name(stderr, trx, TRUE, new_name);
 
3755
                        putc('\n', stderr);
 
3756
                        err = DB_ERROR;
 
3757
 
3834
3758
                        goto funct_exit;
3835
3759
                }
3836
3760
 
3838
3762
                an ALTER, not in a RENAME. */
3839
3763
 
3840
3764
                err = dict_load_foreigns(
3841
 
                        new_name, !old_is_tmp || trx->check_foreigns);
 
3765
                        new_name, old_is_tmp ? trx->check_foreigns : TRUE);
3842
3766
 
3843
3767
                if (err != DB_SUCCESS) {
3844
3768
                        ut_print_timestamp(stderr);
3875
3799
        }
3876
3800
 
3877
3801
funct_exit:
3878
 
 
3879
 
        if (commit) {
3880
 
                trx_commit_for_mysql(trx);
3881
 
        }
 
3802
        trx_commit_for_mysql(trx);
 
3803
        row_mysql_unlock_data_dictionary(trx);
3882
3804
 
3883
3805
        if (UNIV_LIKELY_NULL(heap)) {
3884
3806
                mem_heap_free(heap);
3886
3808
 
3887
3809
        trx->op_info = "";
3888
3810
 
3889
 
        return(err);
 
3811
        return((int) err);
3890
3812
}
3891
3813
 
3892
3814
/*************************************************************************
3915
3837
        ulint           i;
3916
3838
        ulint           cnt;
3917
3839
        mem_heap_t*     heap            = NULL;
3918
 
        ulint           n_ext;
3919
3840
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
3920
 
        ulint*          offsets;
3921
 
        rec_offs_init(offsets_);
 
3841
        ulint*          offsets         = offsets_;
 
3842
        *offsets_ = (sizeof offsets_) / sizeof *offsets_;
3922
3843
 
3923
3844
        *n_rows = 0;
3924
3845
 
3964
3885
 
3965
3886
        rec = buf + mach_read_from_4(buf);
3966
3887
 
3967
 
        offsets = rec_get_offsets(rec, index, offsets_,
3968
 
                                  ULINT_UNDEFINED, &heap);
3969
 
 
3970
3888
        if (prev_entry != NULL) {
3971
3889
                matched_fields = 0;
3972
3890
                matched_bytes = 0;
3973
3891
 
 
3892
                offsets = rec_get_offsets(rec, index, offsets,
 
3893
                                          ULINT_UNDEFINED, &heap);
3974
3894
                cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
3975
3895
                                                &matched_fields,
3976
3896
                                                &matched_bytes);
4003
3923
                        rec_print_new(stderr, rec, offsets);
4004
3924
                        putc('\n', stderr);
4005
3925
                        is_ok = FALSE;
4006
 
                } else if (dict_index_is_unique(index)
 
3926
                } else if ((index->type & DICT_UNIQUE)
4007
3927
                           && !contains_null
4008
3928
                           && matched_fields
4009
3929
                           >= dict_index_get_n_ordering_defined_by_user(
4014
3934
                }
4015
3935
        }
4016
3936
 
4017
 
        {
4018
 
                mem_heap_t*     tmp_heap = NULL;
4019
 
 
4020
 
                /* Empty the heap on each round.  But preserve offsets[]
4021
 
                for the row_rec_to_index_entry() call, by copying them
4022
 
                into a separate memory heap when needed. */
4023
 
                if (UNIV_UNLIKELY(offsets != offsets_)) {
4024
 
                        ulint   size = rec_offs_get_n_alloc(offsets)
4025
 
                                * sizeof *offsets;
4026
 
 
4027
 
                        tmp_heap = mem_heap_create(size);
4028
 
                        offsets = mem_heap_dup(tmp_heap, offsets, size);
4029
 
                }
4030
 
 
4031
 
                mem_heap_empty(heap);
4032
 
 
4033
 
                prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, rec,
4034
 
                                                    index, offsets,
4035
 
                                                    &n_ext, heap);
4036
 
 
4037
 
                if (UNIV_LIKELY_NULL(tmp_heap)) {
4038
 
                        mem_heap_free(tmp_heap);
4039
 
                }
4040
 
        }
 
3937
        mem_heap_empty(heap);
 
3938
        offsets = offsets_;
 
3939
 
 
3940
        prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
4041
3941
 
4042
3942
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
4043
3943
 
4046
3946
 
4047
3947
/*************************************************************************
4048
3948
Checks a table for corruption. */
4049
 
UNIV_INTERN
 
3949
 
4050
3950
ulint
4051
3951
row_check_table_for_mysql(
4052
3952
/*======================*/
4061
3961
        ulint           ret             = DB_SUCCESS;
4062
3962
        ulint           old_isolation_level;
4063
3963
 
4064
 
        if (table->ibd_file_missing) {
 
3964
        if (prebuilt->table->ibd_file_missing) {
4065
3965
                ut_print_timestamp(stderr);
4066
3966
                fprintf(stderr, "  InnoDB: Error:\n"
4067
3967
                        "InnoDB: MySQL is trying to use a table handle"
4075
3975
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
4076
3976
                        "innodb-troubleshooting.html\n"
4077
3977
                        "InnoDB: how you can resolve the problem.\n",
4078
 
                        table->name);
 
3978
                        prebuilt->table->name);
4079
3979
                return(DB_ERROR);
4080
3980
        }
4081
3981
 
4105
4005
                if (!btr_validate_index(index, prebuilt->trx)) {
4106
4006
                        ret = DB_ERROR;
4107
4007
                } else {
4108
 
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
 
4008
                        if (!row_scan_and_check_index(prebuilt,
 
4009
                                                      index, &n_rows)) {
4109
4010
                                ret = DB_ERROR;
4110
4011
                        }
4111
4012
 
4156
4057
 
4157
4058
        return(ret);
4158
4059
}
4159
 
#endif /* !UNIV_HOTBACKUP */
4160
 
 
4161
 
/*************************************************************************
4162
 
Determines if a table is a magic monitor table. */
4163
 
UNIV_INTERN
4164
 
ibool
4165
 
row_is_magic_monitor_table(
4166
 
/*=======================*/
4167
 
                                        /* out: TRUE if monitor table */
4168
 
        const char*     table_name)     /* in: name of the table, in the
4169
 
                                        form database/table_name */
4170
 
{
4171
 
        const char*     name; /* table_name without database/ */
4172
 
        ulint           len;
4173
 
 
4174
 
        name = strchr(table_name, '/');
4175
 
        ut_a(name != NULL);
4176
 
        name++;
4177
 
        len = strlen(name) + 1;
4178
 
 
4179
 
        if (STR_EQ(name, len, S_innodb_monitor)
4180
 
            || STR_EQ(name, len, S_innodb_lock_monitor)
4181
 
            || STR_EQ(name, len, S_innodb_tablespace_monitor)
4182
 
            || STR_EQ(name, len, S_innodb_table_monitor)
4183
 
            || STR_EQ(name, len, S_innodb_mem_validate)) {
4184
 
 
4185
 
                return(TRUE);
4186
 
        }
4187
 
 
4188
 
        return(FALSE);
4189
 
}