~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2008-10-28 08:36:02 UTC
  • mfrom: (520.4.13 merge-innodb-plugin)
  • Revision ID: brian@tangent.org-20081028083602-0p3zzlhlxr5q2sqo
Merging Monty's work

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