~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (C) 2000, 2010, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
15
St, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/**************************************************//**
 
20
@file row/row0mysql.c
2
21
Interface between Innobase row operations and MySQL.
3
22
Contains also create table and other data dictionary operations.
4
23
 
5
 
(c) 2000 Innobase Oy
6
 
 
7
24
Created 9/17/2000 Heikki Tuuri
8
25
*******************************************************/
9
26
 
14
31
#endif
15
32
 
16
33
#include "row0ins.h"
 
34
#include "row0merge.h"
17
35
#include "row0sel.h"
18
36
#include "row0upd.h"
19
37
#include "row0row.h"
34
52
#include "fil0fil.h"
35
53
#include "ibuf0ibuf.h"
36
54
 
37
 
/* Provide optional 4.x backwards compatibility for 5.0 and above */
 
55
#include <errno.h>
 
56
 
 
57
/** Provide optional 4.x backwards compatibility for 5.0 and above */
38
58
UNIV_INTERN ibool       row_rollback_on_timeout = FALSE;
39
59
 
40
 
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
41
 
that the table handler can drop the table in background when there are no
42
 
queries to it any more. Protected by the kernel mutex. */
 
60
/** Chain node of the list of tables to drop in the background. */
43
61
typedef struct row_mysql_drop_struct    row_mysql_drop_t;
 
62
 
 
63
/** Chain node of the list of tables to drop in the background. */
44
64
struct row_mysql_drop_struct{
45
 
        char*                           table_name;
46
 
        UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
 
65
        char*                           table_name;     /*!< table name */
 
66
        UT_LIST_NODE_T(row_mysql_drop_t)row_mysql_drop_list;
 
67
                                                        /*!< list chain node */
47
68
};
48
69
 
 
70
/** @brief List of tables we should drop in background.
 
71
 
 
72
ALTER TABLE in MySQL requires that the table handler can drop the
 
73
table in background when there are no queries to it any
 
74
more.  Protected by kernel_mutex. */
49
75
static UT_LIST_BASE_NODE_T(row_mysql_drop_t)    row_mysql_drop_list;
 
76
/** Flag: has row_mysql_drop_list been initialized? */
50
77
static ibool    row_mysql_drop_list_inited      = FALSE;
51
78
 
52
 
/* Magic table names for invoking various monitor threads */
 
79
/** Magic table names for invoking various monitor threads */
 
80
/* @{ */
53
81
static const char S_innodb_monitor[] = "innodb_monitor";
54
82
static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";
55
83
static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";
56
84
static const char S_innodb_table_monitor[] = "innodb_table_monitor";
57
85
static const char S_innodb_mem_validate[] = "innodb_mem_validate";
 
86
/* @} */
58
87
 
59
 
/* Evaluates to true if str1 equals str2_onstack, used for comparing
60
 
the above strings. */
 
88
/** Evaluates to true if str1 equals str2_onstack, used for comparing
 
89
the magic table names.
 
90
@param str1             in: string to compare
 
91
@param str1_len         in: length of str1, in bytes, including terminating NUL
 
92
@param str2_onstack     in: char[] array containing a NUL terminated string
 
93
@return                 TRUE if str1 equals str2_onstack */
61
94
#define STR_EQ(str1, str1_len, str2_onstack) \
62
95
        ((str1_len) == sizeof(str2_onstack) \
63
96
         && memcmp(str1, str2_onstack, sizeof(str2_onstack)) == 0)
64
97
 
65
 
#ifndef UNIV_HOTBACKUP
66
 
/***********************************************************************
67
 
Determine if the given name is a name reserved for MySQL system tables. */
68
 
static
69
 
ibool
70
 
row_mysql_is_system_table(
71
 
/*======================*/
72
 
                                 /* out: TRUE if name is a MySQL
73
 
                                 system table name */
74
 
        const char*     name)
75
 
{
76
 
        if (strncmp(name, "mysql/", 6) != 0) {
77
 
 
78
 
                return(FALSE);
79
 
        }
80
 
 
81
 
        return(0 == strcmp(name + 6, "host")
82
 
               || 0 == strcmp(name + 6, "user")
83
 
               || 0 == strcmp(name + 6, "db"));
84
 
}
85
 
#endif /* !UNIV_HOTBACKUP */
86
 
 
87
 
/*************************************************************************
 
98
/*********************************************************************//**
88
99
If a table is not yet in the drop list, adds the table to the list of tables
89
100
which the master thread drops in background. We need this on Unix because in
90
101
ALTER TABLE MySQL may call drop table even if the table has running queries on
91
102
it. Also, if there are running foreign key checks on the table, we drop the
92
 
table lazily. */
 
103
table lazily.
 
104
@return TRUE if the table was not yet in the drop list, and was added there */
93
105
static
94
106
ibool
95
107
row_add_table_to_background_drop_list(
96
108
/*==================================*/
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 */
 
109
        const char*     name);  /*!< in: table name */
100
110
 
101
 
/***********************************************************************
 
111
/*******************************************************************//**
102
112
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
103
113
static
104
114
void
110
120
        }
111
121
}
112
122
 
113
 
/***********************************************************************
 
123
/*******************************************************************//**
114
124
Frees the blob heap in prebuilt when no longer needed. */
115
125
UNIV_INTERN
116
126
void
117
127
row_mysql_prebuilt_free_blob_heap(
118
128
/*==============================*/
119
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct of a
 
129
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct of a
120
130
                                        ha_innobase:: table handle */
121
131
{
122
132
        mem_heap_free(prebuilt->blob_heap);
123
133
        prebuilt->blob_heap = NULL;
124
134
}
125
135
 
126
 
/***********************************************************************
 
136
/*******************************************************************//**
127
137
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
128
 
format. */
 
138
format.
 
139
@return pointer to the data, we skip the 1 or 2 bytes at the start
 
140
that are used to store the len */
129
141
UNIV_INTERN
130
142
byte*
131
143
row_mysql_store_true_var_len(
132
144
/*=========================*/
133
 
                        /* out: pointer to the data, we skip the 1 or 2 bytes
134
 
                        at the start that are used to store the len */
135
 
        byte*   dest,   /* in: where to store */
136
 
        ulint   len,    /* in: length, must fit in two bytes */
137
 
        ulint   lenlen) /* in: storage length of len: either 1 or 2 bytes */
 
145
        byte*   dest,   /*!< in: where to store */
 
146
        ulint   len,    /*!< in: length, must fit in two bytes */
 
147
        ulint   lenlen) /*!< in: storage length of len: either 1 or 2 bytes */
138
148
{
139
149
        if (lenlen == 2) {
140
150
                ut_a(len < 256 * 256);
152
162
        return(dest + 1);
153
163
}
154
164
 
155
 
/***********************************************************************
 
165
/*******************************************************************//**
156
166
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
157
 
returns a pointer to the data. */
 
167
returns a pointer to the data.
 
168
@return pointer to the data, we skip the 1 or 2 bytes at the start
 
169
that are used to store the len */
158
170
UNIV_INTERN
159
171
const byte*
160
172
row_mysql_read_true_varchar(
161
173
/*========================*/
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
 
174
        ulint*          len,    /*!< out: variable-length field length */
 
175
        const byte*     field,  /*!< in: field in the MySQL format */
 
176
        ulint           lenlen) /*!< in: storage length of len: either 1
168
177
                                or 2 bytes */
169
178
{
170
179
        if (lenlen == 2) {
180
189
        return(field + 1);
181
190
}
182
191
 
183
 
/***********************************************************************
 
192
/*******************************************************************//**
184
193
Stores a reference to a BLOB in the MySQL format. */
185
194
UNIV_INTERN
186
195
void
187
196
row_mysql_store_blob_ref(
188
197
/*=====================*/
189
 
        byte*           dest,   /* in: where to store */
190
 
        ulint           col_len,/* in: dest buffer size: determines into
 
198
        byte*           dest,   /*!< in: where to store */
 
199
        ulint           col_len,/*!< in: dest buffer size: determines into
191
200
                                how many bytes the BLOB length is stored,
192
201
                                the space for the length may vary from 1
193
202
                                to 4 bytes */
194
 
        const void*     data,   /* in: BLOB data; if the value to store
 
203
        const void*     data,   /*!< in: BLOB data; if the value to store
195
204
                                is SQL NULL this should be NULL pointer */
196
 
        ulint           len)    /* in: BLOB length; if the value to store
 
205
        ulint           len)    /*!< in: BLOB length; if the value to store
197
206
                                is SQL NULL this should be 0; remember
198
207
                                also to set the NULL bit in the MySQL record
199
208
                                header! */
217
226
        memcpy(dest + col_len - 8, &data, sizeof data);
218
227
}
219
228
 
220
 
/***********************************************************************
221
 
Reads a reference to a BLOB in the MySQL format. */
 
229
/*******************************************************************//**
 
230
Reads a reference to a BLOB in the MySQL format.
 
231
@return pointer to BLOB data */
222
232
UNIV_INTERN
223
233
const byte*
224
234
row_mysql_read_blob_ref(
225
235
/*====================*/
226
 
                                        /* out: pointer to BLOB data */
227
 
        ulint*          len,            /* out: BLOB length */
228
 
        const byte*     ref,            /* in: BLOB reference in the
 
236
        ulint*          len,            /*!< out: BLOB length */
 
237
        const byte*     ref,            /*!< in: BLOB reference in the
229
238
                                        MySQL format */
230
 
        ulint           col_len)        /* in: BLOB reference length
 
239
        ulint           col_len)        /*!< in: BLOB reference length
231
240
                                        (not BLOB length) */
232
241
{
233
242
        byte*   data;
239
248
        return(data);
240
249
}
241
250
 
242
 
/******************************************************************
 
251
/**************************************************************//**
 
252
Pad a column with spaces. */
 
253
UNIV_INTERN
 
254
void
 
255
row_mysql_pad_col(
 
256
/*==============*/
 
257
        ulint   mbminlen,       /*!< in: minimum size of a character,
 
258
                                in bytes */
 
259
        byte*   pad,            /*!< out: padded buffer */
 
260
        ulint   len)            /*!< in: number of bytes to pad */
 
261
{
 
262
        const byte*     pad_end;
 
263
 
 
264
        switch (UNIV_EXPECT(mbminlen, 1)) {
 
265
        default:
 
266
                ut_error;
 
267
        case 1:
 
268
                /* space=0x20 */
 
269
                memset(pad, 0x20, len);
 
270
                break;
 
271
        case 2:
 
272
                /* space=0x0020 */
 
273
                pad_end = pad + len;
 
274
                ut_a(!(len % 2));
 
275
                do {
 
276
                        *pad++ = 0x00;
 
277
                        *pad++ = 0x20;
 
278
                } while (pad < pad_end);
 
279
                break;
 
280
        case 4:
 
281
                /* space=0x00000020 */
 
282
                pad_end = pad + len;
 
283
                ut_a(!(len % 4));
 
284
                do {
 
285
                        *pad++ = 0x00;
 
286
                        *pad++ = 0x00;
 
287
                        *pad++ = 0x00;
 
288
                        *pad++ = 0x20;
 
289
                } while (pad < pad_end);
 
290
                break;
 
291
        }
 
292
}
 
293
 
 
294
/**************************************************************//**
243
295
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
244
296
The counterpart of this function is row_sel_field_store_in_mysql_format() in
245
 
row0sel.c. */
 
297
row0sel.c.
 
298
@return up to which byte we used buf in the conversion */
246
299
UNIV_INTERN
247
300
byte*
248
301
row_mysql_store_col_in_innobase_format(
249
302
/*===================================*/
250
 
                                        /* out: up to which byte we used
251
 
                                        buf in the conversion */
252
 
        dfield_t*       dfield,         /* in/out: dfield where dtype
 
303
        dfield_t*       dfield,         /*!< in/out: dfield where dtype
253
304
                                        information must be already set when
254
305
                                        this function is called! */
255
 
        byte*           buf,            /* in/out: buffer for a converted
 
306
        byte*           buf,            /*!< in/out: buffer for a converted
256
307
                                        integer value; this must be at least
257
308
                                        col_len long then! */
258
 
        ibool           row_format_col, /* TRUE if the mysql_data is from
 
309
        ibool           row_format_col, /*!< TRUE if the mysql_data is from
259
310
                                        a MySQL row, FALSE if from a MySQL
260
311
                                        key value;
261
312
                                        in MySQL, a true VARCHAR storage
262
313
                                        format differs in a row and in a
263
314
                                        key value: in a key value the length
264
315
                                        is always stored in 2 bytes! */
265
 
        const byte*     mysql_data,     /* in: MySQL column value, not
 
316
        const byte*     mysql_data,     /*!< in: MySQL column value, not
266
317
                                        SQL NULL; NOTE that dfield may also
267
318
                                        get a pointer to mysql_data,
268
319
                                        therefore do not discard this as long
269
320
                                        as dfield is used! */
270
 
        ulint           col_len,        /* in: MySQL column length; NOTE that
 
321
        ulint           col_len,        /*!< in: MySQL column length; NOTE that
271
322
                                        this is the storage length of the
272
323
                                        column in the MySQL format row, not
273
324
                                        necessarily the length of the actual
274
325
                                        payload data; if the column is a true
275
326
                                        VARCHAR then this is irrelevant */
276
 
        ulint           comp)           /* in: nonzero=compact format */
 
327
        ulint           comp)           /*!< in: nonzero=compact format */
277
328
{
278
329
        const byte*     ptr     = mysql_data;
279
330
        const dtype_t*  dtype;
332
383
                        /* Remove trailing spaces from old style VARCHAR
333
384
                        columns. */
334
385
 
335
 
                        /* Handle UCS2 strings differently. */
 
386
                        /* Handle Unicode strings differently. */
336
387
                        ulint   mbminlen        = dtype_get_mbminlen(dtype);
337
388
 
338
389
                        ptr = mysql_data;
339
390
 
340
 
                        if (mbminlen == 2) {
 
391
                        switch (mbminlen) {
 
392
                        default:
 
393
                                ut_error;
 
394
                        case 4:
 
395
                                /* space=0x00000020 */
 
396
                                /* Trim "half-chars", just in case. */
 
397
                                col_len &= ~3;
 
398
 
 
399
                                while (col_len >= 4
 
400
                                       && ptr[col_len - 4] == 0x00
 
401
                                       && ptr[col_len - 3] == 0x00
 
402
                                       && ptr[col_len - 2] == 0x00
 
403
                                       && ptr[col_len - 1] == 0x20) {
 
404
                                        col_len -= 4;
 
405
                                }
 
406
                                break;
 
407
                        case 2:
341
408
                                /* space=0x0020 */
342
409
                                /* Trim "half-chars", just in case. */
343
410
                                col_len &= ~1;
346
413
                                       && ptr[col_len - 1] == 0x20) {
347
414
                                        col_len -= 2;
348
415
                                }
349
 
                        } else {
350
 
                                ut_a(mbminlen == 1);
 
416
                                break;
 
417
                        case 1:
351
418
                                /* space=0x20 */
352
419
                                while (col_len > 0
353
420
                                       && ptr[col_len - 1] == 0x20) {
361
428
                /* In some cases we strip trailing spaces from UTF-8 and other
362
429
                multibyte charsets, from FIXED-length CHAR columns, to save
363
430
                space. UTF-8 would otherwise normally use 3 * the string length
364
 
                bytes to store a latin1 string! */
 
431
                bytes to store an ASCII string! */
365
432
 
366
433
                /* We assume that this CHAR field is encoded in a
367
434
                variable-length character set where spaces have
401
468
        return(buf);
402
469
}
403
470
 
404
 
/******************************************************************
 
471
/**************************************************************//**
405
472
Convert a row in the MySQL format to a row in the Innobase format. Note that
406
473
the function to convert a MySQL format key value to an InnoDB dtuple is
407
474
row_sel_convert_mysql_key_to_innobase() in row0sel.c. */
409
476
void
410
477
row_mysql_convert_row_to_innobase(
411
478
/*==============================*/
412
 
        dtuple_t*       row,            /* in/out: Innobase row where the
 
479
        dtuple_t*       row,            /*!< in/out: Innobase row where the
413
480
                                        field type information is already
414
481
                                        copied there! */
415
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct where template
 
482
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct where template
416
483
                                        must be of type ROW_MYSQL_WHOLE_ROW */
417
 
        byte*           mysql_rec)      /* in: row in the MySQL format;
 
484
        byte*           mysql_rec)      /*!< in: row in the MySQL format;
418
485
                                        NOTE: do not discard as long as
419
486
                                        row is used, as row may contain
420
487
                                        pointers to this record! */
421
488
{
422
 
        mysql_row_templ_t*      templ;
 
489
        const mysql_row_templ_t*templ;
423
490
        dfield_t*               dfield;
424
491
        ulint                   i;
425
492
 
457
524
        }
458
525
}
459
526
 
460
 
/********************************************************************
461
 
Handles user errors and lock waits detected by the database engine. */
 
527
/****************************************************************//**
 
528
Handles user errors and lock waits detected by the database engine.
 
529
@return TRUE if it was a lock wait and we should continue running the
 
530
query thread and in that case the thr is ALREADY in the running state. */
462
531
UNIV_INTERN
463
532
ibool
464
533
row_mysql_handle_errors(
465
534
/*====================*/
466
 
                                /* out: TRUE if it was a lock wait and
467
 
                                we should continue running the query thread */
468
 
        ulint*          new_err,/* out: possible new error encountered in
 
535
        ulint*          new_err,/*!< out: possible new error encountered in
469
536
                                lock wait, or if no new error, the value
470
537
                                of trx->error_state at the entry of this
471
538
                                function */
472
 
        trx_t*          trx,    /* in: transaction */
473
 
        que_thr_t*      thr,    /* in: query thread */
474
 
        trx_savept_t*   savept) /* in: savepoint or NULL */
 
539
        trx_t*          trx,    /*!< in: transaction */
 
540
        que_thr_t*      thr,    /*!< in: query thread */
 
541
        trx_savept_t*   savept) /*!< in: savepoint or NULL */
475
542
{
476
 
#ifndef UNIV_HOTBACKUP
477
543
        ulint   err;
478
544
 
479
545
handle_new_error:
486
552
        switch (err) {
487
553
        case DB_LOCK_WAIT_TIMEOUT:
488
554
                if (row_rollback_on_timeout) {
489
 
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
555
                        trx_general_rollback_for_mysql(trx, NULL);
490
556
                        break;
491
557
                }
492
558
                /* fall through */
498
564
        case DB_CANNOT_ADD_CONSTRAINT:
499
565
        case DB_TOO_MANY_CONCURRENT_TRXS:
500
566
        case DB_OUT_OF_FILE_SPACE:
 
567
        case DB_INTERRUPTED:
501
568
                if (savept) {
502
569
                        /* Roll back the latest, possibly incomplete
503
570
                        insertion or update */
504
571
 
505
 
                        trx_general_rollback_for_mysql(trx, TRUE, savept);
 
572
                        trx_general_rollback_for_mysql(trx, savept);
506
573
                }
507
574
                /* MySQL will roll back the latest SQL statement */
508
575
                break;
524
591
                /* Roll back the whole transaction; this resolution was added
525
592
                to version 3.23.43 */
526
593
 
527
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
594
                trx_general_rollback_for_mysql(trx, NULL);
528
595
                break;
529
596
 
530
597
        case DB_MUST_GET_MORE_FILE_SPACE:
548
615
                      "InnoDB: If the mysqld server crashes"
549
616
                      " after the startup or when\n"
550
617
                      "InnoDB: you dump the tables, look at\n"
551
 
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
552
 
                      "forcing-recovery.html"
 
618
                      "InnoDB: " REFMAN "forcing-recovery.html"
553
619
                      " for help.\n", stderr);
554
620
                break;
 
621
        case DB_FOREIGN_EXCEED_MAX_CASCADE:
 
622
                fprintf(stderr, "InnoDB: Cannot delete/update rows with"
 
623
                        " cascading foreign key constraints that exceed max"
 
624
                        " depth of %lu\n"
 
625
                        "Please drop excessive foreign constraints"
 
626
                        " and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
 
627
                break;
555
628
        default:
556
629
                fprintf(stderr, "InnoDB: unknown error code %lu\n",
557
630
                        (ulong) err);
567
640
        trx->error_state = DB_SUCCESS;
568
641
 
569
642
        return(FALSE);
570
 
#else /* UNIV_HOTBACKUP */
571
 
        /* This function depends on MySQL code that is not included in
572
 
        InnoDB Hot Backup builds.  Besides, this function should never
573
 
        be called in InnoDB Hot Backup. */
574
 
        ut_error;
575
 
        return(FALSE);
576
 
#endif /* UNIV_HOTBACKUP */
577
643
}
578
644
 
579
 
/************************************************************************
580
 
Create a prebuilt struct for a MySQL table handle. */
 
645
/********************************************************************//**
 
646
Create a prebuilt struct for a MySQL table handle.
 
647
@return own: a prebuilt struct */
581
648
UNIV_INTERN
582
649
row_prebuilt_t*
583
650
row_create_prebuilt(
584
651
/*================*/
585
 
                                /* out, own: a prebuilt struct */
586
 
        dict_table_t*   table)  /* in: Innobase table handle */
 
652
        dict_table_t*   table)  /*!< in: Innobase table handle */
587
653
{
588
654
        row_prebuilt_t* prebuilt;
589
655
        mem_heap_t*     heap;
593
659
 
594
660
        heap = mem_heap_create(sizeof *prebuilt + 128);
595
661
 
596
 
        prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt);
 
662
        prebuilt = static_cast<row_prebuilt_t *>(mem_heap_zalloc(heap, sizeof *prebuilt));
597
663
 
598
664
        prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
599
665
        prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
608
674
 
609
675
        prebuilt->select_lock_type = LOCK_NONE;
610
676
        prebuilt->stored_select_lock_type = 99999999;
 
677
        UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
 
678
                         sizeof prebuilt->stored_select_lock_type);
611
679
 
612
680
        prebuilt->search_tuple = dtuple_create(
613
681
                heap, 2 * dict_table_get_n_cols(table));
637
705
        return(prebuilt);
638
706
}
639
707
 
640
 
/************************************************************************
 
708
/********************************************************************//**
641
709
Free a prebuilt struct for a MySQL table handle. */
642
710
UNIV_INTERN
643
711
void
644
712
row_prebuilt_free(
645
713
/*==============*/
646
 
        row_prebuilt_t* prebuilt,       /* in, own: prebuilt struct */
647
 
        ibool           dict_locked)    /* in: TRUE=data dictionary locked */
 
714
        row_prebuilt_t* prebuilt,       /*!< in, own: prebuilt struct */
 
715
        ibool           dict_locked)    /*!< in: TRUE=data dictionary locked */
648
716
{
649
717
        ulint   i;
650
718
 
722
790
        mem_heap_free(prebuilt->heap);
723
791
}
724
792
 
725
 
/*************************************************************************
 
793
/*********************************************************************//**
726
794
Updates the transaction pointers in query graphs stored in the prebuilt
727
795
struct. */
728
796
UNIV_INTERN
729
797
void
730
798
row_update_prebuilt_trx(
731
799
/*====================*/
732
 
                                        /* out: prebuilt dtuple */
733
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL
734
 
                                        handle */
735
 
        trx_t*          trx)            /* in: transaction handle */
 
800
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct
 
801
                                        in MySQL handle */
 
802
        trx_t*          trx)            /*!< in: transaction handle */
736
803
{
737
804
        if (trx->magic_n != TRX_MAGIC_N) {
738
805
                fprintf(stderr,
773
840
        }
774
841
}
775
842
 
776
 
/*************************************************************************
 
843
dtuple_t* row_get_prebuilt_insert_row(row_prebuilt_t*   prebuilt);
 
844
 
 
845
/*********************************************************************//**
777
846
Gets pointer to a prebuilt dtuple used in insertions. If the insert graph
778
847
has not yet been built in the prebuilt struct, then this function first
779
 
builds it. */
780
 
static
 
848
builds it.
 
849
@return prebuilt dtuple; the column type information is also set in it */
781
850
dtuple_t*
782
851
row_get_prebuilt_insert_row(
783
852
/*========================*/
784
 
                                        /* out: prebuilt dtuple; the column
785
 
                                        type information is also set in it */
786
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
853
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
787
854
                                        handle */
788
855
{
789
856
        ins_node_t*     node;
802
869
                prebuilt->ins_node = node;
803
870
 
804
871
                if (prebuilt->ins_upd_rec_buff == NULL) {
805
 
                        prebuilt->ins_upd_rec_buff = mem_heap_alloc(
806
 
                                prebuilt->heap, prebuilt->mysql_row_len);
 
872
                        prebuilt->ins_upd_rec_buff = static_cast<byte *>(mem_heap_alloc(
 
873
                                prebuilt->heap, prebuilt->mysql_row_len));
807
874
                }
808
875
 
809
876
                row = dtuple_create(prebuilt->heap,
813
880
 
814
881
                ins_node_set_new_row(node, row);
815
882
 
816
 
                prebuilt->ins_graph = que_node_get_parent(
 
883
                prebuilt->ins_graph = static_cast<que_fork_t *>(que_node_get_parent(
817
884
                        pars_complete_graph_for_exec(node,
818
885
                                                     prebuilt->trx,
819
 
                                                     prebuilt->heap));
 
886
                                                     prebuilt->heap)));
820
887
                prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
821
888
        }
822
889
 
823
890
        return(prebuilt->ins_node->row);
824
891
}
825
892
 
826
 
/*************************************************************************
 
893
/*********************************************************************//**
827
894
Updates the table modification counter and calculates new estimates
828
895
for table and index statistics if necessary. */
829
896
UNIV_INLINE
830
897
void
831
898
row_update_statistics_if_needed(
832
899
/*============================*/
833
 
        dict_table_t*   table)  /* in: table */
 
900
        dict_table_t*   table)  /*!< in: table */
834
901
{
835
902
        ulint   counter;
836
903
 
847
914
        if (counter > 2000000000
848
915
            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
849
916
 
850
 
                dict_update_statistics(table);
 
917
                dict_update_statistics(table, FALSE /* update even if stats
 
918
                                                    are initialized */);
851
919
        }
852
920
}
853
921
 
854
 
/*************************************************************************
855
 
Unlocks AUTO_INC type locks that were possibly reserved by a trx. */
 
922
/*********************************************************************//**
 
923
Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
 
924
function should be called at the the end of an SQL statement, by the
 
925
connection thread that owns the transaction (trx->mysql_thd). */
856
926
UNIV_INTERN
857
927
void
858
928
row_unlock_table_autoinc_for_mysql(
859
929
/*===============================*/
860
 
        trx_t*  trx)    /* in/out: transaction */
 
930
        trx_t*  trx)    /*!< in/out: transaction */
861
931
{
862
 
        mutex_enter(&kernel_mutex);
863
 
 
864
 
        lock_release_autoinc_locks(trx);
865
 
 
866
 
        mutex_exit(&kernel_mutex);
 
932
        if (lock_trx_holds_autoinc_locks(trx)) {
 
933
                mutex_enter(&kernel_mutex);
 
934
 
 
935
                lock_release_autoinc_locks(trx);
 
936
 
 
937
                mutex_exit(&kernel_mutex);
 
938
        }
867
939
}
868
940
 
869
 
/*************************************************************************
 
941
/*********************************************************************//**
870
942
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
871
943
AUTO_INC lock gives exclusive access to the auto-inc counter of the
872
944
table. The lock is reserved only for the duration of an SQL statement.
873
945
It is not compatible with another AUTO_INC or exclusive lock on the
874
 
table. */
 
946
table.
 
947
@return error code or DB_SUCCESS */
875
948
UNIV_INTERN
876
949
int
877
950
row_lock_table_autoinc_for_mysql(
878
951
/*=============================*/
879
 
                                        /* out: error code or DB_SUCCESS */
880
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in the MySQL
 
952
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in the MySQL
881
953
                                        table handle */
882
954
{
883
955
        trx_t*                  trx     = prebuilt->trx;
946
1018
        return((int) err);
947
1019
}
948
1020
 
949
 
/*************************************************************************
950
 
Sets a table lock on the table mentioned in prebuilt. */
 
1021
/*********************************************************************//**
 
1022
Sets a table lock on the table mentioned in prebuilt.
 
1023
@return error code or DB_SUCCESS */
951
1024
UNIV_INTERN
952
1025
int
953
1026
row_lock_table_for_mysql(
954
1027
/*=====================*/
955
 
                                        /* out: error code or DB_SUCCESS */
956
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in the MySQL
 
1028
        row_prebuilt_t* prebuilt,       /*!< in: prebuilt struct in the MySQL
957
1029
                                        table handle */
958
 
        dict_table_t*   table,          /* in: table to lock, or NULL
 
1030
        dict_table_t*   table,          /*!< in: table to lock, or NULL
959
1031
                                        if prebuilt->table should be
960
1032
                                        locked as
961
1033
                                        prebuilt->select_lock_type */
962
 
        ulint           mode)           /* in: lock mode of table
 
1034
        ulint           mode)           /*!< in: lock mode of table
963
1035
                                        (ignored if table==NULL) */
964
1036
{
965
1037
        trx_t*          trx             = prebuilt->trx;
994
1066
        trx_start_if_not_started(trx);
995
1067
 
996
1068
        if (table) {
997
 
                err = lock_table(0, table, mode, thr);
 
1069
                err = lock_table(0, table, static_cast<lock_mode>(mode), thr);
998
1070
        } else {
999
1071
                err = lock_table(0, prebuilt->table,
1000
 
                                 prebuilt->select_lock_type, thr);
 
1072
                                 static_cast<lock_mode>(prebuilt->select_lock_type), thr);
1001
1073
        }
1002
1074
 
1003
1075
        trx->error_state = err;
1023
1095
        return((int) err);
1024
1096
}
1025
1097
 
1026
 
/*************************************************************************
1027
 
Does an insert for MySQL. */
 
1098
/*********************************************************************//**
 
1099
Does an insert for MySQL.
 
1100
@return error code or DB_SUCCESS */
1028
1101
UNIV_INTERN
1029
1102
int
1030
1103
row_insert_for_mysql(
1031
1104
/*=================*/
1032
 
                                        /* out: error code or DB_SUCCESS */
1033
 
        byte*           mysql_rec,      /* in: row in the MySQL format */
1034
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1105
        byte*           mysql_rec,      /*!< in: row in the MySQL format */
 
1106
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1035
1107
                                        handle */
1036
1108
{
1037
1109
        trx_savept_t    savept;
1055
1127
                        "InnoDB: the MySQL datadir, or have you"
1056
1128
                        " used DISCARD TABLESPACE?\n"
1057
1129
                        "InnoDB: Look from\n"
1058
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1059
 
                        "innodb-troubleshooting.html\n"
 
1130
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1060
1131
                        "InnoDB: how you can resolve the problem.\n",
1061
1132
                        prebuilt->table->name);
1062
1133
                return(DB_ERROR);
1156
1227
        return((int) err);
1157
1228
}
1158
1229
 
1159
 
/*************************************************************************
 
1230
/*********************************************************************//**
1160
1231
Builds a dummy query graph used in selects. */
1161
1232
UNIV_INTERN
1162
1233
void
1163
1234
row_prebuild_sel_graph(
1164
1235
/*===================*/
1165
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1236
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1166
1237
                                        handle */
1167
1238
{
1168
1239
        sel_node_t*     node;
1173
1244
 
1174
1245
                node = sel_node_create(prebuilt->heap);
1175
1246
 
1176
 
                prebuilt->sel_graph = que_node_get_parent(
 
1247
                prebuilt->sel_graph = static_cast<que_fork_t *>(que_node_get_parent(
1177
1248
                        pars_complete_graph_for_exec(node,
1178
1249
                                                     prebuilt->trx,
1179
 
                                                     prebuilt->heap));
 
1250
                                                     prebuilt->heap)));
1180
1251
 
1181
1252
                prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1182
1253
        }
1183
1254
}
1184
1255
 
1185
 
/*************************************************************************
 
1256
/*********************************************************************//**
1186
1257
Creates an query graph node of 'update' type to be used in the MySQL
1187
 
interface. */
 
1258
interface.
 
1259
@return own: update node */
1188
1260
UNIV_INTERN
1189
1261
upd_node_t*
1190
1262
row_create_update_node_for_mysql(
1191
1263
/*=============================*/
1192
 
                                /* out, own: update node */
1193
 
        dict_table_t*   table,  /* in: table to update */
1194
 
        mem_heap_t*     heap)   /* in: mem heap from which allocated */
 
1264
        dict_table_t*   table,  /*!< in: table to update */
 
1265
        mem_heap_t*     heap)   /*!< in: mem heap from which allocated */
1195
1266
{
1196
1267
        upd_node_t*     node;
1197
1268
 
1200
1271
        node->in_mysql_interface = TRUE;
1201
1272
        node->is_delete = FALSE;
1202
1273
        node->searched_update = FALSE;
1203
 
        node->select_will_do_update = FALSE;
1204
1274
        node->select = NULL;
1205
1275
        node->pcur = btr_pcur_create_for_mysql();
1206
1276
        node->table = table;
1219
1289
        return(node);
1220
1290
}
1221
1291
 
1222
 
/*************************************************************************
 
1292
/*********************************************************************//**
1223
1293
Gets pointer to a prebuilt update vector used in updates. If the update
1224
1294
graph has not yet been built in the prebuilt struct, then this function
1225
 
first builds it. */
 
1295
first builds it.
 
1296
@return prebuilt update vector */
1226
1297
UNIV_INTERN
1227
1298
upd_t*
1228
1299
row_get_prebuilt_update_vector(
1229
1300
/*===========================*/
1230
 
                                        /* out: prebuilt update vector */
1231
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1301
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1232
1302
                                        handle */
1233
1303
{
1234
1304
        dict_table_t*   table   = prebuilt->table;
1245
1315
 
1246
1316
                prebuilt->upd_node = node;
1247
1317
 
1248
 
                prebuilt->upd_graph = que_node_get_parent(
 
1318
                prebuilt->upd_graph = static_cast<que_fork_t *>(que_node_get_parent(
1249
1319
                        pars_complete_graph_for_exec(node,
1250
1320
                                                     prebuilt->trx,
1251
 
                                                     prebuilt->heap));
 
1321
                                                     prebuilt->heap)));
1252
1322
                prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1253
1323
        }
1254
1324
 
1255
1325
        return(prebuilt->upd_node->update);
1256
1326
}
1257
1327
 
1258
 
/*************************************************************************
1259
 
Does an update or delete of a row for MySQL. */
 
1328
/*********************************************************************//**
 
1329
Does an update or delete of a row for MySQL.
 
1330
@return error code or DB_SUCCESS */
1260
1331
UNIV_INTERN
1261
1332
int
1262
1333
row_update_for_mysql(
1263
1334
/*=================*/
1264
 
                                        /* out: error code or DB_SUCCESS */
1265
 
        byte*           mysql_rec,      /* in: the row to be updated, in
 
1335
        byte*           mysql_rec,      /*!< in: the row to be updated, in
1266
1336
                                        the MySQL format */
1267
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
 
1337
        row_prebuilt_t* prebuilt)       /*!< in: prebuilt struct in MySQL
1268
1338
                                        handle */
1269
1339
{
1270
1340
        trx_savept_t    savept;
1292
1362
                        "InnoDB: the MySQL datadir, or have you"
1293
1363
                        " used DISCARD TABLESPACE?\n"
1294
1364
                        "InnoDB: Look from\n"
1295
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
1296
 
                        "innodb-troubleshooting.html\n"
 
1365
                        "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
1297
1366
                        "InnoDB: how you can resolve the problem.\n",
1298
1367
                        prebuilt->table->name);
1299
1368
                return(DB_ERROR);
1363
1432
run_again:
1364
1433
        thr->run_node = node;
1365
1434
        thr->prev_node = node;
 
1435
        thr->fk_cascade_depth = 0;
1366
1436
 
1367
1437
        row_upd_step(thr);
1368
1438
 
 
1439
        /* The recursive call for cascading update/delete happens
 
1440
        in above row_upd_step(), reset the counter once we come
 
1441
        out of the recursive call, so it does not accumulate for
 
1442
        different row deletes */
 
1443
        thr->fk_cascade_depth = 0;
 
1444
 
1369
1445
        err = trx->error_state;
1370
1446
 
 
1447
        /* Reset fk_cascade_depth back to 0 */
 
1448
        thr->fk_cascade_depth = 0;
 
1449
 
1371
1450
        if (err != DB_SUCCESS) {
1372
1451
                que_thr_stop_for_mysql(thr);
1373
1452
 
1404
1483
                srv_n_rows_updated++;
1405
1484
        }
1406
1485
 
1407
 
        row_update_statistics_if_needed(prebuilt->table);
 
1486
        /* We update table statistics only if it is a DELETE or UPDATE
 
1487
        that changes indexed columns, UPDATEs that change only non-indexed
 
1488
        columns would not affect statistics. */
 
1489
        if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
 
1490
                row_update_statistics_if_needed(prebuilt->table);
 
1491
        }
1408
1492
 
1409
1493
        trx->op_info = "";
1410
1494
 
1411
1495
        return((int) err);
1412
1496
}
1413
1497
 
1414
 
/*************************************************************************
1415
 
This can only be used when srv_locks_unsafe_for_binlog is TRUE or
1416
 
this session is using a READ COMMITTED isolation level. Before
1417
 
calling this function we must use trx_reset_new_rec_lock_info() and
1418
 
trx_register_new_rec_lock() to store the information which new record locks
1419
 
really were set. This function removes a newly set lock under prebuilt->pcur,
1420
 
and also under prebuilt->clust_pcur. Currently, this is only used and tested
1421
 
in the case of an UPDATE or a DELETE statement, where the row lock is of the
1422
 
LOCK_X type.
1423
 
Thus, this implements a 'mini-rollback' that releases the latest record
1424
 
locks we set. */
 
1498
/*********************************************************************//**
 
1499
This can only be used when srv_locks_unsafe_for_binlog is TRUE or this
 
1500
session is using a READ COMMITTED or READ UNCOMMITTED isolation level.
 
1501
Before calling this function row_search_for_mysql() must have
 
1502
initialized prebuilt->new_rec_locks to store the information which new
 
1503
record locks really were set. This function removes a newly set
 
1504
clustered index record lock under prebuilt->pcur or
 
1505
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
 
1506
releases the latest clustered index record lock we set.
 
1507
@return error code or DB_SUCCESS */
1425
1508
UNIV_INTERN
1426
1509
int
1427
1510
row_unlock_for_mysql(
1428
1511
/*=================*/
1429
 
                                        /* out: error code or DB_SUCCESS */
1430
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL
 
1512
        row_prebuilt_t* prebuilt,       /*!< in/out: prebuilt struct in MySQL
1431
1513
                                        handle */
1432
 
        ibool           has_latches_on_recs)/* TRUE if called so that we have
1433
 
                                        the latches on the records under pcur
1434
 
                                        and clust_pcur, and we do not need to
1435
 
                                        reposition the cursors. */
 
1514
        ibool           has_latches_on_recs)/*!< in: TRUE if called so
 
1515
                                        that we have the latches on
 
1516
                                        the records under pcur and
 
1517
                                        clust_pcur, and we do not need
 
1518
                                        to reposition the cursors. */
1436
1519
{
1437
 
        dict_index_t*   index;
1438
1520
        btr_pcur_t*     pcur            = prebuilt->pcur;
1439
1521
        btr_pcur_t*     clust_pcur      = prebuilt->clust_pcur;
1440
1522
        trx_t*          trx             = prebuilt->trx;
1441
 
        rec_t*          rec;
1442
 
        mtr_t           mtr;
1443
1523
 
1444
1524
        ut_ad(prebuilt && trx);
1445
1525
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1446
1526
 
1447
 
        if (!(srv_locks_unsafe_for_binlog
1448
 
              || trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
 
1527
        if (UNIV_UNLIKELY
 
1528
            (!srv_locks_unsafe_for_binlog
 
1529
             && trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
1449
1530
 
1450
1531
                fprintf(stderr,
1451
1532
                        "InnoDB: Error: calling row_unlock_for_mysql though\n"
1452
 
                        "InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n"
 
1533
                        "InnoDB: innodb_locks_unsafe_for_binlog is FALSE and\n"
1453
1534
                        "InnoDB: this session is not using"
1454
1535
                        " READ COMMITTED isolation level.\n");
1455
1536
 
1458
1539
 
1459
1540
        trx->op_info = "unlock_row";
1460
1541
 
1461
 
        index = btr_pcur_get_btr_cur(pcur)->index;
 
1542
        if (prebuilt->new_rec_locks >= 1) {
1462
1543
 
1463
 
        if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
 
1544
                const rec_t*    rec;
 
1545
                dict_index_t*   index;
 
1546
                trx_id_t        rec_trx_id;
 
1547
                mtr_t           mtr;
1464
1548
 
1465
1549
                mtr_start(&mtr);
1466
1550
 
1471
1555
                }
1472
1556
 
1473
1557
                rec = btr_pcur_get_rec(pcur);
1474
 
 
1475
 
                lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1476
 
                                rec, prebuilt->select_lock_type);
1477
 
 
1478
 
                mtr_commit(&mtr);
1479
 
 
1480
 
                /* If the search was done through the clustered index, then
1481
 
                we have not used clust_pcur at all, and we must NOT try to
1482
 
                reset locks on clust_pcur. The values in clust_pcur may be
1483
 
                garbage! */
1484
 
 
1485
 
                if (dict_index_is_clust(index)) {
1486
 
 
1487
 
                        goto func_exit;
1488
 
                }
1489
 
        }
1490
 
 
1491
 
        index = btr_pcur_get_btr_cur(clust_pcur)->index;
1492
 
 
1493
 
        if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
1494
 
 
1495
 
                mtr_start(&mtr);
1496
 
 
1497
 
                /* Restore the cursor position and find the record */
1498
 
 
1499
 
                if (!has_latches_on_recs) {
1500
 
                        btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
1501
 
                                                  &mtr);
1502
 
                }
1503
 
 
1504
 
                rec = btr_pcur_get_rec(clust_pcur);
1505
 
 
1506
 
                lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
1507
 
                                rec, prebuilt->select_lock_type);
1508
 
 
1509
 
                mtr_commit(&mtr);
1510
 
        }
1511
 
 
1512
 
func_exit:
 
1558
                index = btr_pcur_get_btr_cur(pcur)->index;
 
1559
 
 
1560
                if (prebuilt->new_rec_locks >= 2) {
 
1561
                        /* Restore the cursor position and find the record
 
1562
                        in the clustered index. */
 
1563
 
 
1564
                        if (!has_latches_on_recs) {
 
1565
                                btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
1566
                                                          clust_pcur, &mtr);
 
1567
                        }
 
1568
 
 
1569
                        rec = btr_pcur_get_rec(clust_pcur);
 
1570
                        index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
1571
                }
 
1572
 
 
1573
                if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
 
1574
                        /* This is not a clustered index record.  We
 
1575
                        do not know how to unlock the record. */
 
1576
                        goto no_unlock;
 
1577
                }
 
1578
 
 
1579
                /* If the record has been modified by this
 
1580
                transaction, do not unlock it. */
 
1581
 
 
1582
                if (index->trx_id_offset) {
 
1583
                        rec_trx_id = trx_read_trx_id(rec
 
1584
                                                     + index->trx_id_offset);
 
1585
                } else {
 
1586
                        mem_heap_t*     heap                    = NULL;
 
1587
                        ulint   offsets_[REC_OFFS_NORMAL_SIZE];
 
1588
                        ulint*  offsets                         = offsets_;
 
1589
 
 
1590
                        rec_offs_init(offsets_);
 
1591
                        offsets = rec_get_offsets(rec, index, offsets,
 
1592
                                                  ULINT_UNDEFINED, &heap);
 
1593
 
 
1594
                        rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
 
1595
 
 
1596
                        if (UNIV_LIKELY_NULL(heap)) {
 
1597
                                mem_heap_free(heap);
 
1598
                        }
 
1599
                }
 
1600
 
 
1601
                if (rec_trx_id != trx->id) {
 
1602
                        /* We did not update the record: unlock it */
 
1603
 
 
1604
                        rec = btr_pcur_get_rec(pcur);
 
1605
                        index = btr_pcur_get_btr_cur(pcur)->index;
 
1606
 
 
1607
                        lock_rec_unlock(trx, btr_pcur_get_block(pcur),
 
1608
                                        rec, static_cast<lock_mode>(prebuilt->select_lock_type));
 
1609
 
 
1610
                        if (prebuilt->new_rec_locks >= 2) {
 
1611
                                rec = btr_pcur_get_rec(clust_pcur);
 
1612
                                index = btr_pcur_get_btr_cur(clust_pcur)->index;
 
1613
 
 
1614
                                lock_rec_unlock(trx,
 
1615
                                                btr_pcur_get_block(clust_pcur),
 
1616
                                                rec,
 
1617
                                                static_cast<lock_mode>(prebuilt->select_lock_type));
 
1618
                        }
 
1619
                }
 
1620
no_unlock:
 
1621
                mtr_commit(&mtr);
 
1622
        }
 
1623
 
1513
1624
        trx->op_info = "";
1514
1625
 
1515
1626
        return(DB_SUCCESS);
1516
1627
}
1517
1628
 
1518
 
/**************************************************************************
1519
 
Does a cascaded delete or set null in a foreign key operation. */
 
1629
/**********************************************************************//**
 
1630
Does a cascaded delete or set null in a foreign key operation.
 
1631
@return error code or DB_SUCCESS */
1520
1632
UNIV_INTERN
1521
1633
ulint
1522
1634
row_update_cascade_for_mysql(
1523
1635
/*=========================*/
1524
 
                                /* out: error code or DB_SUCCESS */
1525
 
        que_thr_t*      thr,    /* in: query thread */
1526
 
        upd_node_t*     node,   /* in: update node used in the cascade
 
1636
        que_thr_t*      thr,    /*!< in: query thread */
 
1637
        upd_node_t*     node,   /*!< in: update node used in the cascade
1527
1638
                                or set null operation */
1528
 
        dict_table_t*   table)  /* in: table where we do the operation */
 
1639
        dict_table_t*   table)  /*!< in: table where we do the operation */
1529
1640
{
1530
1641
        ulint   err;
1531
1642
        trx_t*  trx;
1532
1643
 
1533
1644
        trx = thr_get_trx(thr);
 
1645
 
 
1646
        /* Increment fk_cascade_depth to record the recursive call depth on
 
1647
        a single update/delete that affects multiple tables chained
 
1648
        together with foreign key relations. */
 
1649
        thr->fk_cascade_depth++;
 
1650
 
 
1651
        if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
 
1652
                return (DB_FOREIGN_EXCEED_MAX_CASCADE);
 
1653
        }
1534
1654
run_again:
1535
1655
        thr->run_node = node;
1536
1656
        thr->prev_node = node;
1537
1657
 
1538
1658
        row_upd_step(thr);
1539
1659
 
 
1660
        /* The recursive call for cascading update/delete happens
 
1661
        in above row_upd_step(), reset the counter once we come
 
1662
        out of the recursive call, so it does not accumulate for
 
1663
        different row deletes */
 
1664
        thr->fk_cascade_depth = 0;
 
1665
 
1540
1666
        err = trx->error_state;
1541
1667
 
1542
1668
        /* Note that the cascade node is a subnode of another InnoDB
1584
1710
        return(err);
1585
1711
}
1586
1712
 
1587
 
/*************************************************************************
 
1713
/*********************************************************************//**
1588
1714
Checks if a table is such that we automatically created a clustered
1589
 
index on it (on row id). */
 
1715
index on it (on row id).
 
1716
@return TRUE if the clustered index was generated automatically */
1590
1717
UNIV_INTERN
1591
1718
ibool
1592
1719
row_table_got_default_clust_index(
1593
1720
/*==============================*/
1594
 
        const dict_table_t*     table)
 
1721
        const dict_table_t*     table)  /*!< in: table */
1595
1722
{
1596
1723
        const dict_index_t*     clust_index;
1597
1724
 
1600
1727
        return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
1601
1728
}
1602
1729
 
1603
 
/*************************************************************************
1604
 
Calculates the key number used inside MySQL for an Innobase index. We have
1605
 
to take into account if we generated a default clustered index for the table */
1606
 
UNIV_INTERN
1607
 
ulint
1608
 
row_get_mysql_key_number_for_index(
1609
 
/*===============================*/
1610
 
        const dict_index_t*     index)
1611
 
{
1612
 
        const dict_index_t*     ind;
1613
 
        ulint                   i;
1614
 
 
1615
 
        ut_a(index);
1616
 
 
1617
 
        i = 0;
1618
 
        ind = dict_table_get_first_index(index->table);
1619
 
 
1620
 
        while (index != ind) {
1621
 
                ind = dict_table_get_next_index(ind);
1622
 
                i++;
1623
 
        }
1624
 
 
1625
 
        if (row_table_got_default_clust_index(index->table)) {
1626
 
                ut_a(i > 0);
1627
 
                i--;
1628
 
        }
1629
 
 
1630
 
        return(i);
1631
 
}
1632
 
 
1633
 
/*************************************************************************
 
1730
/*********************************************************************//**
1634
1731
Locks the data dictionary in shared mode from modifications, for performing
1635
1732
foreign key check, rollback, or other operation invisible to MySQL. */
1636
1733
UNIV_INTERN
1637
1734
void
1638
 
row_mysql_freeze_data_dictionary(
1639
 
/*=============================*/
1640
 
        trx_t*  trx)    /* in: transaction */
 
1735
row_mysql_freeze_data_dictionary_func(
 
1736
/*==================================*/
 
1737
        trx_t*          trx,    /*!< in/out: transaction */
 
1738
        const char*     file,   /*!< in: file name */
 
1739
        ulint           line)   /*!< in: line number */
1641
1740
{
1642
1741
        ut_a(trx->dict_operation_lock_mode == 0);
1643
1742
 
1644
 
        rw_lock_s_lock(&dict_operation_lock);
 
1743
        rw_lock_s_lock_func(&dict_operation_lock, 0, file, line);
1645
1744
 
1646
1745
        trx->dict_operation_lock_mode = RW_S_LATCH;
1647
1746
}
1648
1747
 
1649
 
/*************************************************************************
 
1748
/*********************************************************************//**
1650
1749
Unlocks the data dictionary shared lock. */
1651
1750
UNIV_INTERN
1652
1751
void
1653
1752
row_mysql_unfreeze_data_dictionary(
1654
1753
/*===============================*/
1655
 
        trx_t*  trx)    /* in: transaction */
 
1754
        trx_t*  trx)    /*!< in/out: transaction */
1656
1755
{
1657
1756
        ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
1658
1757
 
1661
1760
        trx->dict_operation_lock_mode = 0;
1662
1761
}
1663
1762
 
1664
 
/*************************************************************************
 
1763
/*********************************************************************//**
1665
1764
Locks the data dictionary exclusively for performing a table create or other
1666
1765
data dictionary modification operation. */
1667
1766
UNIV_INTERN
1668
1767
void
1669
 
row_mysql_lock_data_dictionary(
1670
 
/*===========================*/
1671
 
        trx_t*  trx)    /* in: transaction */
 
1768
row_mysql_lock_data_dictionary_func(
 
1769
/*================================*/
 
1770
        trx_t*          trx,    /*!< in/out: transaction */
 
1771
        const char*     file,   /*!< in: file name */
 
1772
        ulint           line)   /*!< in: line number */
1672
1773
{
1673
1774
        ut_a(trx->dict_operation_lock_mode == 0
1674
1775
             || trx->dict_operation_lock_mode == RW_X_LATCH);
1676
1777
        /* Serialize data dictionary operations with dictionary mutex:
1677
1778
        no deadlocks or lock waits can occur then in these operations */
1678
1779
 
1679
 
        rw_lock_x_lock(&dict_operation_lock);
 
1780
        rw_lock_x_lock_func(&dict_operation_lock, 0, file, line);
1680
1781
        trx->dict_operation_lock_mode = RW_X_LATCH;
1681
1782
 
1682
1783
        mutex_enter(&(dict_sys->mutex));
1683
1784
}
1684
1785
 
1685
 
/*************************************************************************
 
1786
/*********************************************************************//**
1686
1787
Unlocks the data dictionary exclusive lock. */
1687
1788
UNIV_INTERN
1688
1789
void
1689
1790
row_mysql_unlock_data_dictionary(
1690
1791
/*=============================*/
1691
 
        trx_t*  trx)    /* in: transaction */
 
1792
        trx_t*  trx)    /*!< in/out: transaction */
1692
1793
{
1693
1794
        ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
1694
1795
 
1701
1802
        trx->dict_operation_lock_mode = 0;
1702
1803
}
1703
1804
 
1704
 
#ifndef UNIV_HOTBACKUP
1705
 
/*************************************************************************
 
1805
/*********************************************************************//**
1706
1806
Creates a table for MySQL. If the name of the table ends in
1707
1807
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
1708
1808
"innodb_table_monitor", then this will also start the printing of monitor
1709
1809
output by the master thread. If the table name ends in "innodb_mem_validate",
1710
 
InnoDB will try to invoke mem_validate(). */
 
1810
InnoDB will try to invoke mem_validate().
 
1811
@return error code or DB_SUCCESS */
1711
1812
UNIV_INTERN
1712
1813
int
1713
1814
row_create_table_for_mysql(
1714
1815
/*=======================*/
1715
 
                                /* out: error code or DB_SUCCESS */
1716
 
        dict_table_t*   table,  /* in, own: table definition
 
1816
        dict_table_t*   table,  /*!< in, own: table definition
1717
1817
                                (will be freed) */
1718
 
        trx_t*          trx)    /* in: transaction handle */
 
1818
        trx_t*          trx)    /*!< in: transaction handle */
1719
1819
{
1720
1820
        tab_node_t*     node;
1721
1821
        mem_heap_t*     heap;
1723
1823
        const char*     table_name;
1724
1824
        ulint           table_name_len;
1725
1825
        ulint           err;
1726
 
        ulint           i;
1727
1826
 
1728
1827
        ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1729
1828
#ifdef UNIV_SYNC_DEBUG
1738
1837
                      " by the user.\n"
1739
1838
                      "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
1740
1839
                      " is replaced with raw.\n", stderr);
1741
 
err_exit:
1742
1840
                dict_mem_table_free(table);
1743
1841
                trx_commit_for_mysql(trx);
1744
1842
 
1747
1845
 
1748
1846
        trx->op_info = "creating table";
1749
1847
 
1750
 
        if (row_mysql_is_system_table(table->name)) {
1751
 
 
1752
 
                fprintf(stderr,
1753
 
                        "InnoDB: Error: trying to create a MySQL system"
1754
 
                        " table %s of type InnoDB.\n"
1755
 
                        "InnoDB: MySQL system tables must be"
1756
 
                        " of the MyISAM type!\n",
1757
 
                        table->name);
1758
 
                goto err_exit;
1759
 
        }
1760
 
 
1761
 
        /* Check that no reserved column names are used. */
1762
 
        for (i = 0; i < dict_table_get_n_user_cols(table); i++) {
1763
 
                if (dict_col_name_is_reserved(
1764
 
                            dict_table_get_col_name(table, i))) {
1765
 
 
1766
 
                        goto err_exit;
1767
 
                }
1768
 
        }
1769
 
 
1770
1848
        trx_start_if_not_started(trx);
1771
1849
 
1772
1850
        /* The table name is prefixed with the database name and a '/'.
1834
1912
 
1835
1913
        thr = pars_complete_graph_for_exec(node, trx, heap);
1836
1914
 
1837
 
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
 
1915
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
1838
1916
        que_run_threads(thr);
1839
1917
 
1840
1918
        err = trx->error_state;
1841
1919
 
1842
 
        if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1843
 
                trx->error_state = DB_SUCCESS;
1844
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
1845
 
        }
1846
 
 
1847
1920
        switch (err) {
 
1921
        case DB_SUCCESS:
 
1922
                break;
1848
1923
        case DB_OUT_OF_FILE_SPACE:
 
1924
                trx->error_state = DB_SUCCESS;
 
1925
                trx_general_rollback_for_mysql(trx, NULL);
 
1926
 
1849
1927
                ut_print_timestamp(stderr);
1850
1928
                fputs("  InnoDB: Warning: cannot create table ",
1851
1929
                      stderr);
1860
1938
                break;
1861
1939
 
1862
1940
        case DB_DUPLICATE_KEY:
1863
 
                ut_print_timestamp(stderr);
1864
 
                fputs("  InnoDB: Error: table ", stderr);
1865
 
                ut_print_name(stderr, trx, TRUE, table->name);
1866
 
                fputs(" already exists in InnoDB internal\n"
1867
 
                      "InnoDB: data dictionary. Have you deleted"
1868
 
                      " the .frm file\n"
1869
 
                      "InnoDB: and not used DROP TABLE?"
1870
 
                      " Have you used DROP DATABASE\n"
1871
 
                      "InnoDB: for InnoDB tables in"
1872
 
                      " MySQL version <= 3.23.43?\n"
1873
 
                      "InnoDB: See the Restrictions section"
1874
 
                      " of the InnoDB manual.\n"
1875
 
                      "InnoDB: You can drop the orphaned table"
1876
 
                      " inside InnoDB by\n"
1877
 
                      "InnoDB: creating an InnoDB table with"
1878
 
                      " the same name in another\n"
1879
 
                      "InnoDB: database and copying the .frm file"
1880
 
                      " to the current database.\n"
1881
 
                      "InnoDB: Then MySQL thinks the table exists,"
1882
 
                      " and DROP TABLE will\n"
1883
 
                      "InnoDB: succeed.\n"
1884
 
                      "InnoDB: You can look for further help from\n"
1885
 
                      "InnoDB: "
1886
 
                      "http://dev.mysql.com/doc/refman/5.1/en/"
1887
 
                      "innodb-troubleshooting.html\n", stderr);
1888
 
 
 
1941
        default:
1889
1942
                /* We may also get err == DB_ERROR if the .ibd file for the
1890
1943
                table already exists */
1891
1944
 
 
1945
                trx->error_state = DB_SUCCESS;
 
1946
                trx_general_rollback_for_mysql(trx, NULL);
 
1947
                dict_mem_table_free(table);
1892
1948
                break;
1893
1949
        }
1894
1950
 
1899
1955
        return((int) err);
1900
1956
}
1901
1957
 
1902
 
/*************************************************************************
 
1958
/*********************************************************************//**
1903
1959
Does an index creation operation for MySQL. TODO: currently failure
1904
1960
to create an index results in dropping the whole table! This is no problem
1905
 
currently as all indexes must be created at the same time as the table. */
 
1961
currently as all indexes must be created at the same time as the table.
 
1962
@return error number or DB_SUCCESS */
1906
1963
UNIV_INTERN
1907
1964
int
1908
1965
row_create_index_for_mysql(
1909
1966
/*=======================*/
1910
 
                                        /* out: error number or DB_SUCCESS */
1911
 
        dict_index_t*   index,          /* in, own: index definition
 
1967
        dict_index_t*   index,          /*!< in, own: index definition
1912
1968
                                        (will be freed) */
1913
 
        trx_t*          trx,            /* in: transaction handle */
1914
 
        const ulint*    field_lengths)  /* in: if not NULL, must contain
 
1969
        trx_t*          trx,            /*!< in: transaction handle */
 
1970
        const ulint*    field_lengths)  /*!< in: if not NULL, must contain
1915
1971
                                        dict_index_get_n_fields(index)
1916
1972
                                        actual field lengths for the
1917
1973
                                        index columns, which are
1997
2053
 
1998
2054
        thr = pars_complete_graph_for_exec(node, trx, heap);
1999
2055
 
2000
 
        ut_a(thr == que_fork_start_command(que_node_get_parent(thr)));
 
2056
        ut_a(thr == que_fork_start_command(static_cast<que_fork_t *>(que_node_get_parent(thr))));
2001
2057
        que_run_threads(thr);
2002
2058
 
2003
2059
        err = trx->error_state;
2010
2066
 
2011
2067
                trx->error_state = DB_SUCCESS;
2012
2068
 
2013
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
2069
                trx_general_rollback_for_mysql(trx, NULL);
2014
2070
 
2015
2071
                row_drop_table_for_mysql(table_name, trx, FALSE);
2016
2072
 
2026
2082
        return((int) err);
2027
2083
}
2028
2084
 
2029
 
/*************************************************************************
 
2085
/*********************************************************************//**
2030
2086
Scans a table create SQL string and adds to the data dictionary
2031
2087
the foreign key constraints declared in the string. This function
2032
2088
should be called after the indexes for a table have been created.
2033
2089
Each foreign key constraint must be accompanied with indexes in
2034
 
bot participating tables. The indexes are allowed to contain more
 
2090
both participating tables. The indexes are allowed to contain more
2035
2091
fields than mentioned in the constraint. Check also that foreign key
2036
 
constraints which reference this table are ok. */
 
2092
constraints which reference this table are ok.
 
2093
@return error code or DB_SUCCESS */
2037
2094
UNIV_INTERN
2038
2095
int
2039
2096
row_table_add_foreign_constraints(
2040
2097
/*==============================*/
2041
 
                                        /* out: error code or DB_SUCCESS */
2042
 
        trx_t*          trx,            /* in: transaction */
2043
 
        const char*     sql_string,     /* in: table create statement where
 
2098
        trx_t*          trx,            /*!< in: transaction */
 
2099
        const char*     sql_string,     /*!< in: table create statement where
2044
2100
                                        foreign keys are declared like:
2045
2101
                                FOREIGN KEY (a, b) REFERENCES table2(c, d),
2046
2102
                                        table2 can be written also with the
2047
2103
                                        database name before it: test.table2 */
2048
 
        const char*     name,           /* in: table full name in the
 
2104
        size_t          sql_length,     /*!< in: length of sql_string */
 
2105
        const char*     name,           /*!< in: table full name in the
2049
2106
                                        normalized form
2050
2107
                                        database_name/table_name */
2051
 
        ibool           reject_fks)     /* in: if TRUE, fail with error
 
2108
        ibool           reject_fks)     /*!< in: if TRUE, fail with error
2052
2109
                                        code DB_CANNOT_ADD_CONSTRAINT if
2053
2110
                                        any foreign keys are found. */
2054
2111
{
2066
2123
 
2067
2124
        trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2068
2125
 
2069
 
        err = dict_create_foreign_constraints(trx, sql_string, name,
2070
 
                                              reject_fks);
2071
 
#ifndef UNIV_HOTBACKUP
 
2126
        err = dict_create_foreign_constraints(trx, sql_string, sql_length,
 
2127
                                              name, reject_fks);
2072
2128
        if (err == DB_SUCCESS) {
2073
2129
                /* Check that also referencing constraints are ok */
2074
 
                err = dict_load_foreigns(name, TRUE);
 
2130
                err = dict_load_foreigns(name, FALSE, TRUE);
2075
2131
        }
2076
 
#endif /* !UNIV_HOTBACKUP */
 
2132
 
2077
2133
        if (err != DB_SUCCESS) {
2078
2134
                /* We have special error handling here */
2079
2135
 
2080
2136
                trx->error_state = DB_SUCCESS;
2081
2137
 
2082
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
2138
                trx_general_rollback_for_mysql(trx, NULL);
2083
2139
 
2084
2140
                row_drop_table_for_mysql(name, trx, FALSE);
2085
2141
 
2091
2147
        return((int) err);
2092
2148
}
2093
2149
 
2094
 
/*************************************************************************
 
2150
/*********************************************************************//**
2095
2151
Drops a table for MySQL as a background operation. MySQL relies on Unix
2096
2152
in ALTER TABLE to the fact that the table handler does not remove the
2097
2153
table before all handles to it has been removed. Furhermore, the MySQL's
2098
2154
call to drop table must be non-blocking. Therefore we do the drop table
2099
2155
as a background operation, which is taken care of by the master thread
2100
 
in srv0srv.c. */
 
2156
in srv0srv.c.
 
2157
@return error code or DB_SUCCESS */
2101
2158
static
2102
2159
int
2103
2160
row_drop_table_for_mysql_in_background(
2104
2161
/*===================================*/
2105
 
                                /* out: error code or DB_SUCCESS */
2106
 
        const char*     name)   /* in: table name */
 
2162
        const char*     name)   /*!< in: table name */
2107
2163
{
2108
2164
        ulint   error;
2109
2165
        trx_t*  trx;
2137
2193
        return((int) error);
2138
2194
}
2139
2195
 
2140
 
/*************************************************************************
 
2196
/*********************************************************************//**
2141
2197
The master thread in srv0srv.c calls this regularly to drop tables which
2142
2198
we must drop in background after queries to them have ended. Such lazy
2143
 
dropping of tables is needed in ALTER TABLE on Unix. */
 
2199
dropping of tables is needed in ALTER TABLE on Unix.
 
2200
@return how many tables dropped + remaining tables in list */
2144
2201
UNIV_INTERN
2145
2202
ulint
2146
2203
row_drop_tables_for_mysql_in_background(void)
2147
2204
/*=========================================*/
2148
 
                                        /* out: how many tables dropped
2149
 
                                        + remaining tables in list */
2150
2205
{
2151
2206
        row_mysql_drop_t*       drop;
2152
2207
        dict_table_t*           table;
2213
2268
        goto loop;
2214
2269
}
2215
2270
 
2216
 
/*************************************************************************
 
2271
/*********************************************************************//**
2217
2272
Get the background drop list length. NOTE: the caller must own the kernel
2218
 
mutex! */
 
2273
mutex!
 
2274
@return how many tables in list */
2219
2275
UNIV_INTERN
2220
2276
ulint
2221
2277
row_get_background_drop_list_len_low(void)
2222
2278
/*======================================*/
2223
 
                                        /* out: how many tables in list */
2224
2279
{
2225
2280
        ut_ad(mutex_own(&kernel_mutex));
2226
2281
 
2233
2288
        return(UT_LIST_GET_LEN(row_mysql_drop_list));
2234
2289
}
2235
2290
 
2236
 
/*************************************************************************
 
2291
/*********************************************************************//**
2237
2292
If a table is not yet in the drop list, adds the table to the list of tables
2238
2293
which the master thread drops in background. We need this on Unix because in
2239
2294
ALTER TABLE MySQL may call drop table even if the table has running queries on
2240
2295
it. Also, if there are running foreign key checks on the table, we drop the
2241
 
table lazily. */
 
2296
table lazily.
 
2297
@return TRUE if the table was not yet in the drop list, and was added there */
2242
2298
static
2243
2299
ibool
2244
2300
row_add_table_to_background_drop_list(
2245
2301
/*==================================*/
2246
 
                                /* out: TRUE if the table was not yet in the
2247
 
                                drop list, and was added there */
2248
 
        const char*     name)   /* in: table name */
 
2302
        const char*     name)   /*!< in: table name */
2249
2303
{
2250
2304
        row_mysql_drop_t*       drop;
2251
2305
 
2272
2326
                drop = UT_LIST_GET_NEXT(row_mysql_drop_list, drop);
2273
2327
        }
2274
2328
 
2275
 
        drop = mem_alloc(sizeof(row_mysql_drop_t));
 
2329
        drop = static_cast<row_mysql_drop_t *>(mem_alloc(sizeof(row_mysql_drop_t)));
2276
2330
 
2277
2331
        drop->table_name = mem_strdup(name);
2278
2332
 
2287
2341
        return(TRUE);
2288
2342
}
2289
2343
 
2290
 
/*************************************************************************
 
2344
/*********************************************************************//**
2291
2345
Discards the tablespace of a table which stored in an .ibd file. Discarding
2292
2346
means that this function deletes the .ibd file and assigns a new table id for
2293
 
the table. Also the flag table->ibd_file_missing is set TRUE. */
 
2347
the table. Also the flag table->ibd_file_missing is set TRUE.
 
2348
@return error code or DB_SUCCESS */
2294
2349
UNIV_INTERN
2295
2350
int
2296
2351
row_discard_tablespace_for_mysql(
2297
2352
/*=============================*/
2298
 
                                /* out: error code or DB_SUCCESS */
2299
 
        const char*     name,   /* in: table name */
2300
 
        trx_t*          trx)    /* in: transaction handle */
 
2353
        const char*     name,   /*!< in: table name */
 
2354
        trx_t*          trx)    /*!< in: transaction handle */
2301
2355
{
2302
2356
        dict_foreign_t* foreign;
2303
 
        dulint          new_id;
 
2357
        table_id_t      new_id;
2304
2358
        dict_table_t*   table;
2305
2359
        ibool           success;
2306
2360
        ulint           err;
2414
2468
                goto funct_exit;
2415
2469
        }
2416
2470
 
2417
 
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
 
2471
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2418
2472
 
2419
2473
        /* Remove all locks except the table-level S and X locks. */
2420
2474
        lock_remove_all_on_table(table, FALSE);
2422
2476
        info = pars_info_create();
2423
2477
 
2424
2478
        pars_info_add_str_literal(info, "table_name", name);
2425
 
        pars_info_add_dulint_literal(info, "new_id", new_id);
 
2479
        pars_info_add_ull_literal(info, "new_id", new_id);
2426
2480
 
2427
2481
        err = que_eval_sql(info,
2428
2482
                           "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n"
2448
2502
 
2449
2503
        if (err != DB_SUCCESS) {
2450
2504
                trx->error_state = DB_SUCCESS;
2451
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
2505
                trx_general_rollback_for_mysql(trx, NULL);
2452
2506
                trx->error_state = DB_SUCCESS;
2453
2507
        } else {
2454
2508
                dict_table_change_id_in_cache(table, new_id);
2457
2511
 
2458
2512
                if (!success) {
2459
2513
                        trx->error_state = DB_SUCCESS;
2460
 
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
2514
                        trx_general_rollback_for_mysql(trx, NULL);
2461
2515
                        trx->error_state = DB_SUCCESS;
2462
2516
 
2463
2517
                        err = DB_ERROR;
2479
2533
        return((int) err);
2480
2534
}
2481
2535
 
2482
 
/*********************************************************************
 
2536
/*****************************************************************//**
2483
2537
Imports a tablespace. The space id in the .ibd file must match the space id
2484
 
of the table in the data dictionary. */
 
2538
of the table in the data dictionary.
 
2539
@return error code or DB_SUCCESS */
2485
2540
UNIV_INTERN
2486
2541
int
2487
2542
row_import_tablespace_for_mysql(
2488
2543
/*============================*/
2489
 
                                /* out: error code or DB_SUCCESS */
2490
 
        const char*     name,   /* in: table name */
2491
 
        trx_t*          trx)    /* in: transaction handle */
 
2544
        const char*     name,   /*!< in: table name */
 
2545
        trx_t*          trx)    /*!< in: transaction handle */
2492
2546
{
2493
2547
        dict_table_t*   table;
2494
2548
        ibool           success;
2617
2671
        return((int) err);
2618
2672
}
2619
2673
 
2620
 
/*************************************************************************
2621
 
Truncates a table for MySQL. */
 
2674
/*********************************************************************//**
 
2675
Truncates a table for MySQL.
 
2676
@return error code or DB_SUCCESS */
2622
2677
UNIV_INTERN
2623
2678
int
2624
2679
row_truncate_table_for_mysql(
2625
2680
/*=========================*/
2626
 
                                /* out: error code or DB_SUCCESS */
2627
 
        dict_table_t*   table,  /* in: table handle */
2628
 
        trx_t*          trx)    /* in: transaction handle */
 
2681
        dict_table_t*   table,  /*!< in: table handle */
 
2682
        trx_t*          trx)    /*!< in: transaction handle */
2629
2683
{
2630
2684
        dict_foreign_t* foreign;
2631
2685
        ulint           err;
2636
2690
        dict_index_t*   sys_index;
2637
2691
        btr_pcur_t      pcur;
2638
2692
        mtr_t           mtr;
2639
 
        dulint          new_id;
 
2693
        table_id_t      new_id;
2640
2694
        ulint           recreate_space = 0;
2641
2695
        pars_info_t*    info = NULL;
2642
2696
 
2776
2830
 
2777
2831
                        dict_index_t*   index;
2778
2832
 
2779
 
                        space = 0;
2780
 
 
2781
 
                        if (fil_create_new_single_table_tablespace(
2782
 
                                    &space, table->name, FALSE, flags,
 
2833
                        dict_hdr_get_new_id(NULL, NULL, &space);
 
2834
 
 
2835
                        /* Lock all index trees for this table. We must
 
2836
                        do so after dict_hdr_get_new_id() to preserve
 
2837
                        the latch order */
 
2838
                        dict_table_x_lock_indexes(table);
 
2839
 
 
2840
                        if (space == ULINT_UNDEFINED
 
2841
                            || fil_create_new_single_table_tablespace(
 
2842
                                    space, table->name, FALSE, flags,
2783
2843
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
 
2844
                                dict_table_x_unlock_indexes(table);
2784
2845
                                ut_print_timestamp(stderr);
2785
2846
                                fprintf(stderr,
2786
2847
                                        "  InnoDB: TRUNCATE TABLE %s failed to"
2809
2870
                                        FIL_IBD_FILE_INITIAL_SIZE, &mtr);
2810
2871
                        mtr_commit(&mtr);
2811
2872
                }
 
2873
        } else {
 
2874
                /* Lock all index trees for this table, as we will
 
2875
                truncate the table/index and possibly change their metadata.
 
2876
                All DML/DDL are blocked by table level lock, with
 
2877
                a few exceptions such as queries into information schema
 
2878
                about the table, MySQL could try to access index stats
 
2879
                for this kind of query, we need to use index locks to
 
2880
                sync up */
 
2881
                dict_table_x_lock_indexes(table);
2812
2882
        }
2813
2883
 
2814
2884
        /* scan SYS_INDEXES for all indexes of the table */
2817
2887
        tuple = dtuple_create(heap, 1);
2818
2888
        dfield = dtuple_get_nth_field(tuple, 0);
2819
2889
 
2820
 
        buf = mem_heap_alloc(heap, 8);
 
2890
        buf = static_cast<byte *>(mem_heap_alloc(heap, 8));
2821
2891
        mach_write_to_8(buf, table->id);
2822
2892
 
2823
2893
        dfield_set_data(dfield, buf, 8);
2884
2954
 
2885
2955
        mem_heap_free(heap);
2886
2956
 
2887
 
        new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
 
2957
        /* Done with index truncation, release index tree locks,
 
2958
        subsequent work relates to table level metadata change */
 
2959
        dict_table_x_unlock_indexes(table);
 
2960
 
 
2961
        dict_hdr_get_new_id(&new_id, NULL, NULL);
2888
2962
 
2889
2963
        info = pars_info_create();
2890
2964
 
2891
2965
        pars_info_add_int4_literal(info, "space", (lint) table->space);
2892
 
        pars_info_add_dulint_literal(info, "old_id", table->id);
2893
 
        pars_info_add_dulint_literal(info, "new_id", new_id);
 
2966
        pars_info_add_ull_literal(info, "old_id", table->id);
 
2967
        pars_info_add_ull_literal(info, "new_id", new_id);
2894
2968
 
2895
2969
        err = que_eval_sql(info,
2896
2970
                           "PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2909
2983
 
2910
2984
        if (err != DB_SUCCESS) {
2911
2985
                trx->error_state = DB_SUCCESS;
2912
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
2986
                trx_general_rollback_for_mysql(trx, NULL);
2913
2987
                trx->error_state = DB_SUCCESS;
2914
2988
                ut_print_timestamp(stderr);
2915
2989
                fputs("  InnoDB: Unable to assign a new identifier to table ",
2923
2997
                dict_table_change_id_in_cache(table, new_id);
2924
2998
        }
2925
2999
 
2926
 
        /* MySQL calls ha_innobase::reset_auto_increment() which does
2927
 
        the same thing. */
 
3000
        /* 
 
3001
          MySQL calls ha_innobase::reset_auto_increment() which does
 
3002
          the same thing. 
 
3003
        */
2928
3004
        dict_table_autoinc_lock(table);
2929
3005
        dict_table_autoinc_initialize(table, 1);
2930
3006
        dict_table_autoinc_unlock(table);
2931
 
        dict_update_statistics(table);
 
3007
        dict_update_statistics(table, FALSE /* update even if stats are
 
3008
                                            initialized */);
2932
3009
 
2933
3010
        trx_commit_for_mysql(trx);
2934
3011
 
2943
3020
        return((int) err);
2944
3021
}
2945
3022
 
2946
 
/*************************************************************************
 
3023
/*********************************************************************//**
2947
3024
Drops a table for MySQL.  If the name of the dropped table ends in
2948
3025
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
2949
3026
"innodb_table_monitor", then this will also stop the printing of monitor
2950
3027
output by the master thread.  If the data dictionary was not already locked
2951
3028
by the transaction, the transaction will be committed.  Otherwise, the
2952
 
data dictionary will remain locked. */
 
3029
data dictionary will remain locked.
 
3030
@return error code or DB_SUCCESS */
2953
3031
UNIV_INTERN
2954
3032
int
2955
3033
row_drop_table_for_mysql(
2956
3034
/*=====================*/
2957
 
                                /* out: error code or DB_SUCCESS */
2958
 
        const char*     name,   /* in: table name */
2959
 
        trx_t*          trx,    /* in: transaction handle */
2960
 
        ibool           drop_db)/* in: TRUE=dropping whole database */
 
3035
        const char*     name,   /*!< in: table name */
 
3036
        trx_t*          trx,    /*!< in: transaction handle */
 
3037
        ibool           drop_db)/*!< in: TRUE=dropping whole database */
2961
3038
{
2962
3039
        dict_foreign_t* foreign;
2963
3040
        dict_table_t*   table;
3039
3116
        table = dict_table_get_low(name);
3040
3117
 
3041
3118
        if (!table) {
 
3119
#if defined(BUILD_DRIZZLE)
3042
3120
                err = ENOENT;
 
3121
#else
 
3122
                err = DB_TABLE_NOT_FOUND;
 
3123
                ut_print_timestamp(stderr);
 
3124
 
 
3125
                fputs("  InnoDB: Error: table ", stderr);
 
3126
                ut_print_name(stderr, trx, TRUE, name);
 
3127
                fputs(" does not exist in the InnoDB internal\n"
 
3128
                      "InnoDB: data dictionary though MySQL is"
 
3129
                      " trying to drop it.\n"
 
3130
                      "InnoDB: Have you copied the .frm file"
 
3131
                      " of the table to the\n"
 
3132
                      "InnoDB: MySQL database directory"
 
3133
                      " from another database?\n"
 
3134
                      "InnoDB: You can look for further help from\n"
 
3135
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
 
3136
                      stderr);
 
3137
#endif /* BUILD_DRIZZLE */
3043
3138
                goto funct_exit;
3044
3139
        }
3045
3140
 
3118
3213
 
3119
3214
        if (table->n_foreign_key_checks_running > 0) {
3120
3215
 
3121
 
                const char*     table_name = table->name;
 
3216
                const char*     i_table_name = table->name;
3122
3217
                ibool           added;
3123
3218
 
3124
 
                added = row_add_table_to_background_drop_list(table_name);
 
3219
                added = row_add_table_to_background_drop_list(i_table_name);
3125
3220
 
3126
3221
                if (added) {
3127
3222
                        ut_print_timestamp(stderr);
3128
3223
                        fputs("  InnoDB: You are trying to drop table ",
3129
3224
                              stderr);
3130
 
                        ut_print_name(stderr, trx, TRUE, table_name);
 
3225
                        ut_print_name(stderr, trx, TRUE, i_table_name);
3131
3226
                        fputs("\n"
3132
3227
                              "InnoDB: though there is a"
3133
3228
                              " foreign key check running on it.\n"
3230
3325
                           "END;\n"
3231
3326
                           , FALSE, trx);
3232
3327
 
3233
 
        if (err != DB_SUCCESS) {
3234
 
                ut_a(err == DB_OUT_OF_FILE_SPACE);
3235
 
 
3236
 
                err = DB_MUST_GET_MORE_FILE_SPACE;
3237
 
 
3238
 
                row_mysql_handle_errors(&err, trx, NULL, NULL);
3239
 
 
3240
 
                ut_error;
3241
 
        } else {
3242
 
                ibool           is_path;
 
3328
        switch (err) {
 
3329
                ibool           is_temp;
3243
3330
                const char*     name_or_path;
3244
3331
                mem_heap_t*     heap;
3245
3332
 
 
3333
        case DB_SUCCESS:
 
3334
 
3246
3335
                heap = mem_heap_create(200);
3247
3336
 
3248
3337
                /* Clone the name, in case it has been allocated
3252
3341
                space_id = table->space;
3253
3342
 
3254
3343
                if (table->dir_path_of_temp_table != NULL) {
3255
 
                        is_path = TRUE;
3256
3344
                        name_or_path = mem_heap_strdup(
3257
3345
                                heap, table->dir_path_of_temp_table);
 
3346
                        is_temp = TRUE;
3258
3347
                } else {
3259
 
                        is_path = FALSE;
3260
3348
                        name_or_path = name;
 
3349
                        is_temp = (table->flags >> DICT_TF2_SHIFT)
 
3350
                                & DICT_TF2_TEMPORARY;
3261
3351
                }
3262
3352
 
3263
3353
                dict_table_remove_from_cache(table);
3264
3354
 
3265
 
                if (dict_load_table(name) != NULL) {
 
3355
                if (dict_load_table(name, TRUE) != NULL) {
3266
3356
                        ut_print_timestamp(stderr);
3267
3357
                        fputs("  InnoDB: Error: not able to remove table ",
3268
3358
                              stderr);
3277
3367
                if (err == DB_SUCCESS && space_id > 0) {
3278
3368
                        if (!fil_space_for_table_exists_in_mem(space_id,
3279
3369
                                                               name_or_path,
3280
 
                                                               is_path,
3281
 
                                                               FALSE, TRUE)) {
 
3370
                                                               is_temp, FALSE,
 
3371
                                                               !is_temp)) {
3282
3372
                                err = DB_SUCCESS;
3283
3373
 
3284
3374
                                fprintf(stderr,
3307
3397
                }
3308
3398
 
3309
3399
                mem_heap_free(heap);
 
3400
                break;
 
3401
 
 
3402
        case DB_TOO_MANY_CONCURRENT_TRXS:
 
3403
                /* Cannot even find a free slot for the
 
3404
                the undo log. We can directly exit here
 
3405
                and return the DB_TOO_MANY_CONCURRENT_TRXS
 
3406
                error. */
 
3407
                break;
 
3408
 
 
3409
        case DB_OUT_OF_FILE_SPACE:
 
3410
                err = DB_MUST_GET_MORE_FILE_SPACE;
 
3411
 
 
3412
                row_mysql_handle_errors(&err, trx, NULL, NULL);
 
3413
 
 
3414
                /* Fall through to raise error */
 
3415
 
 
3416
        default:
 
3417
                /* No other possible error returns */
 
3418
                ut_error;
3310
3419
        }
 
3420
 
3311
3421
funct_exit:
3312
3422
 
3313
3423
        if (locked_dictionary) {
3318
3428
 
3319
3429
        trx->op_info = "";
3320
3430
 
3321
 
#ifndef UNIV_HOTBACKUP
3322
3431
        srv_wake_master_thread();
3323
 
#endif /* !UNIV_HOTBACKUP */
3324
3432
 
3325
3433
        return((int) err);
3326
3434
}
3327
3435
 
3328
 
/***********************************************************************
 
3436
/*********************************************************************//**
 
3437
Drop all temporary tables during crash recovery. */
 
3438
UNIV_INTERN
 
3439
void
 
3440
row_mysql_drop_temp_tables(void)
 
3441
/*============================*/
 
3442
{
 
3443
        trx_t*          trx;
 
3444
        btr_pcur_t      pcur;
 
3445
        mtr_t           mtr;
 
3446
        mem_heap_t*     heap;
 
3447
 
 
3448
        trx = trx_allocate_for_background();
 
3449
        trx->op_info = "dropping temporary tables";
 
3450
        row_mysql_lock_data_dictionary(trx);
 
3451
 
 
3452
        heap = mem_heap_create(200);
 
3453
 
 
3454
        mtr_start(&mtr);
 
3455
 
 
3456
        btr_pcur_open_at_index_side(
 
3457
                TRUE,
 
3458
                dict_table_get_first_index(dict_sys->sys_tables),
 
3459
                BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
 
3460
 
 
3461
        for (;;) {
 
3462
                const rec_t*    rec;
 
3463
                const byte*     field;
 
3464
                ulint           len;
 
3465
                const char*     table_name;
 
3466
                dict_table_t*   table;
 
3467
 
 
3468
                btr_pcur_move_to_next_user_rec(&pcur, &mtr);
 
3469
 
 
3470
                if (!btr_pcur_is_on_user_rec(&pcur)) {
 
3471
                        break;
 
3472
                }
 
3473
 
 
3474
                rec = btr_pcur_get_rec(&pcur);
 
3475
                field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
 
3476
                if (len != 4 || !(mach_read_from_4(field) & 0x80000000UL)) {
 
3477
                        continue;
 
3478
                }
 
3479
 
 
3480
                /* Because this is not a ROW_FORMAT=REDUNDANT table,
 
3481
                the is_temp flag is valid.  Examine it. */
 
3482
 
 
3483
                field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
 
3484
                if (len != 4
 
3485
                    || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
 
3486
                        continue;
 
3487
                }
 
3488
 
 
3489
                /* This is a temporary table. */
 
3490
                field = rec_get_nth_field_old(rec, 0/*NAME*/, &len);
 
3491
                if (len == UNIV_SQL_NULL || len == 0) {
 
3492
                        /* Corrupted SYS_TABLES.NAME */
 
3493
                        continue;
 
3494
                }
 
3495
 
 
3496
                table_name = mem_heap_strdupl(heap, (const char*) field, len);
 
3497
 
 
3498
                btr_pcur_store_position(&pcur, &mtr);
 
3499
                btr_pcur_commit_specify_mtr(&pcur, &mtr);
 
3500
 
 
3501
                table = dict_load_table(table_name, TRUE);
 
3502
 
 
3503
                if (table) {
 
3504
                        row_drop_table_for_mysql(table_name, trx, FALSE);
 
3505
                        trx_commit_for_mysql(trx);
 
3506
                }
 
3507
 
 
3508
                mtr_start(&mtr);
 
3509
                btr_pcur_restore_position(BTR_SEARCH_LEAF,
 
3510
                                          &pcur, &mtr);
 
3511
        }
 
3512
 
 
3513
        btr_pcur_close(&pcur);
 
3514
        mtr_commit(&mtr);
 
3515
        mem_heap_free(heap);
 
3516
        row_mysql_unlock_data_dictionary(trx);
 
3517
        trx_free_for_background(trx);
 
3518
}
 
3519
 
 
3520
/*******************************************************************//**
3329
3521
Drop all foreign keys in a database, see Bug#18942.
3330
 
Called at the end of row_drop_database_for_mysql(). */
 
3522
Called at the end of row_drop_database_for_mysql().
 
3523
@return error code or DB_SUCCESS */
3331
3524
static
3332
3525
ulint
3333
3526
drop_all_foreign_keys_in_db(
3334
3527
/*========================*/
3335
 
                                /* out: error code or DB_SUCCESS */
3336
 
        const char*     name,   /* in: database name which ends to '/' */
3337
 
        trx_t*          trx)    /* in: transaction handle */
 
3528
        const char*     name,   /*!< in: database name which ends to '/' */
 
3529
        trx_t*          trx)    /*!< in: transaction handle */
3338
3530
{
3339
3531
        pars_info_t*    pinfo;
3340
3532
        ulint           err;
3345
3537
 
3346
3538
        pars_info_add_str_literal(pinfo, "dbname", name);
3347
3539
 
3348
 
/* true if for_name is not prefixed with dbname */
 
3540
/** true if for_name is not prefixed with dbname */
3349
3541
#define TABLE_NOT_IN_THIS_DB \
3350
3542
"SUBSTR(for_name, 0, LENGTH(:dbname)) <> :dbname"
3351
3543
 
3385
3577
        return(err);
3386
3578
}
3387
3579
 
3388
 
/*************************************************************************
3389
 
Drops a database for MySQL. */
 
3580
/*********************************************************************//**
 
3581
Drops a database for MySQL.
 
3582
@return error code or DB_SUCCESS */
3390
3583
UNIV_INTERN
3391
3584
int
3392
3585
row_drop_database_for_mysql(
3393
3586
/*========================*/
3394
 
                                /* out: error code or DB_SUCCESS */
3395
 
        const char*     name,   /* in: database name which ends to '/' */
3396
 
        trx_t*          trx)    /* in: transaction handle */
 
3587
        const char*     name,   /*!< in: database name which ends to '/' */
 
3588
        trx_t*          trx)    /*!< in: transaction handle */
3397
3589
{
3398
3590
        dict_table_t* table;
3399
3591
        char*   table_name;
3413
3605
        while ((table_name = dict_get_first_table_name_in_db(name))) {
3414
3606
                ut_a(memcmp(table_name, name, namelen) == 0);
3415
3607
 
 
3608
                // For the time being I would like to see how often we see
 
3609
                // lost temporary tables. --Brian
 
3610
                fprintf(stderr, "Dropping lost temporary table %s\n", table_name);
 
3611
 
3416
3612
                table = dict_table_get_low(table_name);
3417
3613
 
3418
3614
                ut_a(table);
3479
3675
        return(err);
3480
3676
}
3481
3677
 
3482
 
/*************************************************************************
 
3678
/*********************************************************************//**
3483
3679
Checks if a table name contains the string "/#sql" which denotes temporary
3484
 
tables in MySQL. */
 
3680
tables in MySQL.
 
3681
@return TRUE if temporary table */
3485
3682
static
3486
3683
ibool
3487
3684
row_is_mysql_tmp_table_name(
3488
3685
/*========================*/
3489
 
                                /* out: TRUE if temporary table */
3490
 
        const char*     name)   /* in: table name in the form
 
3686
        const char*     name)   /*!< in: table name in the form
3491
3687
                                'database/tablename' */
3492
3688
{
3493
3689
        return(strstr(name, "/#sql") != NULL);
3494
3690
        /* return(strstr(name, "/@0023sql") != NULL); */
3495
3691
}
3496
3692
 
3497
 
/********************************************************************
3498
 
Delete a single constraint. */
 
3693
/****************************************************************//**
 
3694
Delete a single constraint.
 
3695
@return error code or DB_SUCCESS */
3499
3696
static
3500
3697
int
3501
3698
row_delete_constraint_low(
3502
3699
/*======================*/
3503
 
                                        /* out: error code or DB_SUCCESS */
3504
 
        const char*     id,             /* in: constraint id */
3505
 
        trx_t*          trx)            /* in: transaction handle */
 
3700
        const char*     id,             /*!< in: constraint id */
 
3701
        trx_t*          trx)            /*!< in: transaction handle */
3506
3702
{
3507
3703
        pars_info_t*    info = pars_info_create();
3508
3704
 
3517
3713
                            , FALSE, trx));
3518
3714
}
3519
3715
 
3520
 
/********************************************************************
3521
 
Delete a single constraint. */
 
3716
/****************************************************************//**
 
3717
Delete a single constraint.
 
3718
@return error code or DB_SUCCESS */
3522
3719
static
3523
3720
int
3524
3721
row_delete_constraint(
3525
3722
/*==================*/
3526
 
                                        /* out: error code or DB_SUCCESS */
3527
 
        const char*     id,             /* in: constraint id */
3528
 
        const char*     database_name,  /* in: database name, with the
 
3723
        const char*     id,             /*!< in: constraint id */
 
3724
        const char*     database_name,  /*!< in: database name, with the
3529
3725
                                        trailing '/' */
3530
 
        mem_heap_t*     heap,           /* in: memory heap */
3531
 
        trx_t*          trx)            /* in: transaction handle */
 
3726
        mem_heap_t*     heap,           /*!< in: memory heap */
 
3727
        trx_t*          trx)            /*!< in: transaction handle */
3532
3728
{
3533
3729
        ulint           err;
3534
3730
 
3550
3746
        return((int) err);
3551
3747
}
3552
3748
 
3553
 
/*************************************************************************
3554
 
Renames a table for MySQL. */
 
3749
/*********************************************************************//**
 
3750
Renames a table for MySQL.
 
3751
@return error code or DB_SUCCESS */
3555
3752
UNIV_INTERN
3556
3753
ulint
3557
3754
row_rename_table_for_mysql(
3558
3755
/*=======================*/
3559
 
                                        /* out: error code or DB_SUCCESS */
3560
 
        const char*     old_name,       /* in: old table name */
3561
 
        const char*     new_name,       /* in: new table name */
3562
 
        trx_t*          trx,            /* in: transaction handle */
3563
 
        ibool           commit)         /* in: if TRUE then commit trx */
 
3756
        const char*     old_name,       /*!< in: old table name */
 
3757
        const char*     new_name,       /*!< in: new table name */
 
3758
        trx_t*          trx,            /*!< in: transaction handle */
 
3759
        ibool           commit)         /*!< in: if TRUE then commit trx */
3564
3760
{
3565
3761
        dict_table_t*   table;
3566
3762
        ulint           err                     = DB_ERROR;
3584
3780
                      stderr);
3585
3781
 
3586
3782
                goto funct_exit;
3587
 
        } else if (row_mysql_is_system_table(new_name)) {
3588
 
 
3589
 
                fprintf(stderr,
3590
 
                        "InnoDB: Error: trying to create a MySQL"
3591
 
                        " system table %s of type InnoDB.\n"
3592
 
                        "InnoDB: MySQL system tables must be"
3593
 
                        " of the MyISAM type!\n",
3594
 
                        new_name);
3595
 
 
3596
 
                goto funct_exit;
3597
3783
        }
3598
3784
 
3599
3785
        trx->op_info = "renaming table";
3605
3791
        table = dict_table_get_low(old_name);
3606
3792
 
3607
3793
        if (!table) {
 
3794
#if defined(BUILD_DRIZZLE)
 
3795
                err = ENOENT;
 
3796
#else
3608
3797
                err = DB_TABLE_NOT_FOUND;
3609
3798
                ut_print_timestamp(stderr);
3610
3799
 
3618
3807
                      "InnoDB: MySQL database directory"
3619
3808
                      " from another database?\n"
3620
3809
                      "InnoDB: You can look for further help from\n"
3621
 
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3622
 
                      "innodb-troubleshooting.html\n",
 
3810
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3623
3811
                      stderr);
 
3812
#endif /* BUILD_DRIZZLE */
3624
3813
                goto funct_exit;
3625
3814
        } else if (table->ibd_file_missing) {
3626
3815
                err = DB_TABLE_NOT_FOUND;
3631
3820
                fputs(" does not have an .ibd file"
3632
3821
                      " in the database directory.\n"
3633
3822
                      "InnoDB: You can look for further help from\n"
3634
 
                      "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3635
 
                      "innodb-troubleshooting.html\n",
 
3823
                      "InnoDB: " REFMAN "innodb-troubleshooting.html\n",
3636
3824
                      stderr);
3637
3825
                goto funct_exit;
3638
3826
        } else if (new_is_tmp) {
3784
3972
                              "InnoDB: Have you deleted the .frm file"
3785
3973
                              " and not used DROP TABLE?\n"
3786
3974
                              "InnoDB: You can look for further help from\n"
3787
 
                              "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
3788
 
                              "innodb-troubleshooting.html\n"
 
3975
                              "InnoDB: " REFMAN "innodb-troubleshooting.html\n"
3789
3976
                              "InnoDB: If table ", stderr);
3790
3977
                        ut_print_name(stderr, trx, TRUE, new_name);
3791
3978
                        fputs(" is a temporary table #sql..., then"
3805
3992
                              "InnoDB: succeed.\n", stderr);
3806
3993
                }
3807
3994
                trx->error_state = DB_SUCCESS;
3808
 
                trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
3995
                trx_general_rollback_for_mysql(trx, NULL);
3809
3996
                trx->error_state = DB_SUCCESS;
3810
3997
        } else {
3811
3998
                /* The following call will also rename the .ibd data file if
3814
4001
                if (!dict_table_rename_in_cache(table, new_name,
3815
4002
                                                !new_is_tmp)) {
3816
4003
                        trx->error_state = DB_SUCCESS;
3817
 
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
4004
                        trx_general_rollback_for_mysql(trx, NULL);
3818
4005
                        trx->error_state = DB_SUCCESS;
3819
4006
                        goto funct_exit;
3820
4007
                }
3823
4010
                an ALTER, not in a RENAME. */
3824
4011
 
3825
4012
                err = dict_load_foreigns(
3826
 
                        new_name, !old_is_tmp || trx->check_foreigns);
 
4013
                        new_name, FALSE, !old_is_tmp || trx->check_foreigns);
3827
4014
 
3828
4015
                if (err != DB_SUCCESS) {
3829
4016
                        ut_print_timestamp(stderr);
3854
4041
                        ut_a(dict_table_rename_in_cache(table,
3855
4042
                                                        old_name, FALSE));
3856
4043
                        trx->error_state = DB_SUCCESS;
3857
 
                        trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
4044
                        trx_general_rollback_for_mysql(trx, NULL);
3858
4045
                        trx->error_state = DB_SUCCESS;
3859
4046
                }
3860
4047
        }
3874
4061
        return(err);
3875
4062
}
3876
4063
 
3877
 
/*************************************************************************
 
4064
/*********************************************************************//**
3878
4065
Checks that the index contains entries in an ascending order, unique
3879
4066
constraint is not broken, and calculates the number of index entries
3880
 
in the read view of the current transaction. */
3881
 
static
 
4067
in the read view of the current transaction.
 
4068
@return TRUE if ok */
 
4069
UNIV_INTERN
3882
4070
ibool
3883
 
row_scan_and_check_index(
3884
 
/*=====================*/
3885
 
                                        /* out: TRUE if ok */
3886
 
        row_prebuilt_t* prebuilt,       /* in: prebuilt struct in MySQL */
3887
 
        dict_index_t*   index,          /* in: index */
3888
 
        ulint*          n_rows)         /* out: number of entries seen in the
3889
 
                                        current consistent read */
 
4071
row_check_index_for_mysql(
 
4072
/*======================*/
 
4073
        row_prebuilt_t*         prebuilt,       /*!< in: prebuilt struct
 
4074
                                                in MySQL handle */
 
4075
        const dict_index_t*     index,          /*!< in: index */
 
4076
        ulint*                  n_rows)         /*!< out: number of entries
 
4077
                                                seen in the consistent read */
3890
4078
{
3891
4079
        dtuple_t*       prev_entry      = NULL;
3892
4080
        ulint           matched_fields;
3907
4095
 
3908
4096
        *n_rows = 0;
3909
4097
 
3910
 
        buf = mem_alloc(UNIV_PAGE_SIZE);
 
4098
        buf = static_cast<byte *>(mem_alloc(UNIV_PAGE_SIZE));
3911
4099
        heap = mem_heap_create(100);
3912
4100
 
3913
 
        /* Make a dummy template in prebuilt, which we will use
3914
 
        in scanning the index entries */
3915
 
 
3916
 
        prebuilt->index = index;
3917
 
        prebuilt->sql_stat_start = TRUE;
3918
 
        prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
3919
 
        prebuilt->n_template = 0;
3920
 
        prebuilt->need_to_access_clustered = FALSE;
3921
 
 
3922
 
        dtuple_set_n_fields(prebuilt->search_tuple, 0);
3923
 
 
3924
 
        prebuilt->select_lock_type = LOCK_NONE;
3925
4101
        cnt = 1000;
3926
4102
 
3927
4103
        ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
3933
4109
                }
3934
4110
                cnt = 1000;
3935
4111
        }
3936
 
        if (ret != DB_SUCCESS) {
 
4112
 
 
4113
        switch (ret) {
 
4114
        case DB_SUCCESS:
 
4115
                break;
 
4116
        default:
 
4117
                ut_print_timestamp(stderr);
 
4118
                fputs("  InnoDB: Warning: CHECK TABLE on ", stderr);
 
4119
                dict_index_name_print(stderr, prebuilt->trx, index);
 
4120
                fprintf(stderr, " returned %lu\n", ret);
 
4121
                /* fall through (this error is ignored by CHECK TABLE) */
 
4122
        case DB_END_OF_INDEX:
3937
4123
func_exit:
3938
4124
                mem_free(buf);
3939
4125
                mem_heap_free(heap);
4010
4196
                                * sizeof *offsets;
4011
4197
 
4012
4198
                        tmp_heap = mem_heap_create(size);
4013
 
                        offsets = mem_heap_dup(tmp_heap, offsets, size);
 
4199
                        offsets = static_cast<ulint *>(mem_heap_dup(tmp_heap, offsets, size));
4014
4200
                }
4015
4201
 
4016
4202
                mem_heap_empty(heap);
4029
4215
        goto loop;
4030
4216
}
4031
4217
 
4032
 
/*************************************************************************
4033
 
Checks a table for corruption. */
4034
 
UNIV_INTERN
4035
 
ulint
4036
 
row_check_table_for_mysql(
4037
 
/*======================*/
4038
 
                                        /* out: DB_ERROR or DB_SUCCESS */
4039
 
        row_prebuilt_t* prebuilt)       /* in: prebuilt struct in MySQL
4040
 
                                        handle */
4041
 
{
4042
 
        dict_table_t*   table           = prebuilt->table;
4043
 
        dict_index_t*   index;
4044
 
        ulint           n_rows;
4045
 
        ulint           n_rows_in_table = ULINT_UNDEFINED;
4046
 
        ulint           ret             = DB_SUCCESS;
4047
 
        ulint           old_isolation_level;
4048
 
 
4049
 
        if (table->ibd_file_missing) {
4050
 
                ut_print_timestamp(stderr);
4051
 
                fprintf(stderr, "  InnoDB: Error:\n"
4052
 
                        "InnoDB: MySQL is trying to use a table handle"
4053
 
                        " but the .ibd file for\n"
4054
 
                        "InnoDB: table %s does not exist.\n"
4055
 
                        "InnoDB: Have you deleted the .ibd file"
4056
 
                        " from the database directory under\n"
4057
 
                        "InnoDB: the MySQL datadir, or have you"
4058
 
                        " used DISCARD TABLESPACE?\n"
4059
 
                        "InnoDB: Look from\n"
4060
 
                        "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
4061
 
                        "innodb-troubleshooting.html\n"
4062
 
                        "InnoDB: how you can resolve the problem.\n",
4063
 
                        table->name);
4064
 
                return(DB_ERROR);
4065
 
        }
4066
 
 
4067
 
        prebuilt->trx->op_info = "checking table";
4068
 
 
4069
 
        old_isolation_level = prebuilt->trx->isolation_level;
4070
 
 
4071
 
        /* We must run the index record counts at an isolation level
4072
 
        >= READ COMMITTED, because a dirty read can see a wrong number
4073
 
        of records in some index; to play safe, we use always
4074
 
        REPEATABLE READ here */
4075
 
 
4076
 
        prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
4077
 
 
4078
 
        /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
4079
 
        mutex_enter(&kernel_mutex);
4080
 
        srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
4081
 
        mutex_exit(&kernel_mutex);
4082
 
 
4083
 
        index = dict_table_get_first_index(table);
4084
 
 
4085
 
        while (index != NULL) {
4086
 
                /* fputs("Validating index ", stderr);
4087
 
                ut_print_name(stderr, trx, FALSE, index->name);
4088
 
                putc('\n', stderr); */
4089
 
 
4090
 
                if (!btr_validate_index(index, prebuilt->trx)) {
4091
 
                        ret = DB_ERROR;
4092
 
                } else {
4093
 
                        if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
4094
 
                                ret = DB_ERROR;
4095
 
                        }
4096
 
 
4097
 
                        if (trx_is_interrupted(prebuilt->trx)) {
4098
 
                                break;
4099
 
                        }
4100
 
 
4101
 
                        /* fprintf(stderr, "%lu entries in index %s\n", n_rows,
4102
 
                        index->name); */
4103
 
 
4104
 
                        if (index == dict_table_get_first_index(table)) {
4105
 
                                n_rows_in_table = n_rows;
4106
 
                        } else if (n_rows != n_rows_in_table) {
4107
 
 
4108
 
                                ret = DB_ERROR;
4109
 
 
4110
 
                                fputs("Error: ", stderr);
4111
 
                                dict_index_name_print(stderr,
4112
 
                                                      prebuilt->trx, index);
4113
 
                                fprintf(stderr,
4114
 
                                        " contains %lu entries,"
4115
 
                                        " should be %lu\n",
4116
 
                                        (ulong) n_rows,
4117
 
                                        (ulong) n_rows_in_table);
4118
 
                        }
4119
 
                }
4120
 
 
4121
 
                index = dict_table_get_next_index(index);
4122
 
        }
4123
 
 
4124
 
        /* Restore the original isolation level */
4125
 
        prebuilt->trx->isolation_level = old_isolation_level;
4126
 
 
4127
 
        /* We validate also the whole adaptive hash index for all tables
4128
 
        at every CHECK TABLE */
4129
 
 
4130
 
        if (!btr_search_validate()) {
4131
 
 
4132
 
                ret = DB_ERROR;
4133
 
        }
4134
 
 
4135
 
        /* Restore the fatal lock wait timeout after CHECK TABLE. */
4136
 
        mutex_enter(&kernel_mutex);
4137
 
        srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
4138
 
        mutex_exit(&kernel_mutex);
4139
 
 
4140
 
        prebuilt->trx->op_info = "";
4141
 
 
4142
 
        return(ret);
4143
 
}
4144
 
#endif /* !UNIV_HOTBACKUP */
4145
 
 
4146
 
/*************************************************************************
4147
 
Determines if a table is a magic monitor table. */
 
4218
/*********************************************************************//**
 
4219
Determines if a table is a magic monitor table.
 
4220
@return TRUE if monitor table */
4148
4221
UNIV_INTERN
4149
4222
ibool
4150
4223
row_is_magic_monitor_table(
4151
4224
/*=======================*/
4152
 
                                        /* out: TRUE if monitor table */
4153
 
        const char*     table_name)     /* in: name of the table, in the
 
4225
        const char*     table_name)     /*!< in: name of the table, in the
4154
4226
                                        form database/table_name */
4155
4227
{
4156
4228
        const char*     name; /* table_name without database/ */