1
/******************************************************
1
/*****************************************************************************
3
Copyright (C) 2000, 2010, Innobase Oy. All Rights Reserved.
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.
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.
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
17
*****************************************************************************/
19
/**************************************************//**
2
21
Interface between Innobase row operations and MySQL.
3
22
Contains also create table and other data dictionary operations.
7
24
Created 9/17/2000 Heikki Tuuri
8
25
*******************************************************/
34
52
#include "fil0fil.h"
35
53
#include "ibuf0ibuf.h"
37
/* Provide optional 4.x backwards compatibility for 5.0 and above */
57
/** Provide optional 4.x backwards compatibility for 5.0 and above */
38
58
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
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;
63
/** Chain node of the list of tables to drop in the background. */
44
64
struct row_mysql_drop_struct{
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 */
70
/** @brief List of tables we should drop in background.
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;
52
/* Magic table names for invoking various monitor threads */
79
/** Magic table names for invoking various monitor threads */
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";
59
/* Evaluates to true if str1 equals str2_onstack, used for comparing
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)
65
#ifndef UNIV_HOTBACKUP
66
/***********************************************************************
67
Determine if the given name is a name reserved for MySQL system tables. */
70
row_mysql_is_system_table(
71
/*======================*/
72
/* out: TRUE if name is a MySQL
76
if (strncmp(name, "mysql/", 6) != 0) {
81
return(0 == strcmp(name + 6, "host")
82
|| 0 == strcmp(name + 6, "user")
83
|| 0 == strcmp(name + 6, "db"));
85
#endif /* !UNIV_HOTBACKUP */
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
104
@return TRUE if the table was not yet in the drop list, and was added there */
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 */
101
/***********************************************************************
111
/*******************************************************************//**
102
112
Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
113
/***********************************************************************
123
/*******************************************************************//**
114
124
Frees the blob heap in prebuilt when no longer needed. */
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 */
122
132
mem_heap_free(prebuilt->blob_heap);
123
133
prebuilt->blob_heap = NULL;
126
/***********************************************************************
136
/*******************************************************************//**
127
137
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
139
@return pointer to the data, we skip the 1 or 2 bytes at the start
140
that are used to store the len */
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 */
139
149
if (lenlen == 2) {
140
150
ut_a(len < 256 * 256);
152
162
return(dest + 1);
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 */
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
170
179
if (lenlen == 2) {
180
189
return(field + 1);
183
/***********************************************************************
192
/*******************************************************************//**
184
193
Stores a reference to a BLOB in the MySQL format. */
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
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
217
226
memcpy(dest + col_len - 8, &data, sizeof data);
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 */
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
230
ulint col_len) /* in: BLOB reference length
239
ulint col_len) /*!< in: BLOB reference length
231
240
(not BLOB length) */
242
/******************************************************************
251
/**************************************************************//**
252
Pad a column with spaces. */
257
ulint mbminlen, /*!< in: minimum size of a character,
259
byte* pad, /*!< out: padded buffer */
260
ulint len) /*!< in: number of bytes to pad */
264
switch (UNIV_EXPECT(mbminlen, 1)) {
269
memset(pad, 0x20, len);
278
} while (pad < pad_end);
281
/* space=0x00000020 */
289
} while (pad < pad_end);
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
298
@return up to which byte we used buf in the conversion */
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
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 */
278
329
const byte* ptr = mysql_data;
279
330
const dtype_t* dtype;
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
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! */
422
mysql_row_templ_t* templ;
489
const mysql_row_templ_t*templ;
423
490
dfield_t* dfield;
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. */
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
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 */
476
#ifndef UNIV_HOTBACKUP
479
545
handle_new_error:
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);
621
case DB_FOREIGN_EXCEED_MAX_CASCADE:
622
fprintf(stderr, "InnoDB: Cannot delete/update rows with"
623
" cascading foreign key constraints that exceed max"
625
"Please drop excessive foreign constraints"
626
" and try again\n", (ulong) DICT_FK_MAX_RECURSIVE_LOAD);
556
629
fprintf(stderr, "InnoDB: unknown error code %lu\n",
567
640
trx->error_state = DB_SUCCESS;
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. */
576
#endif /* UNIV_HOTBACKUP */
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 */
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 */
588
654
row_prebuilt_t* prebuilt;
589
655
mem_heap_t* heap;
814
881
ins_node_set_new_row(node, row);
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,
820
887
prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
823
890
return(prebuilt->ins_node->row);
826
/*************************************************************************
893
/*********************************************************************//**
827
894
Updates the table modification counter and calculates new estimates
828
895
for table and index statistics if necessary. */
831
898
row_update_statistics_if_needed(
832
899
/*============================*/
833
dict_table_t* table) /* in: table */
900
dict_table_t* table) /*!< in: table */
847
914
if (counter > 2000000000
848
915
|| ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {
850
dict_update_statistics(table);
917
dict_update_statistics(table, FALSE /* update even if stats
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). */
858
928
row_unlock_table_autoinc_for_mysql(
859
929
/*===============================*/
860
trx_t* trx) /* in/out: transaction */
930
trx_t* trx) /*!< in/out: transaction */
862
mutex_enter(&kernel_mutex);
864
lock_release_autoinc_locks(trx);
866
mutex_exit(&kernel_mutex);
932
if (lock_trx_holds_autoinc_locks(trx)) {
933
mutex_enter(&kernel_mutex);
935
lock_release_autoinc_locks(trx);
937
mutex_exit(&kernel_mutex);
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
947
@return error code or DB_SUCCESS */
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
883
955
trx_t* trx = prebuilt->trx;
946
1018
return((int) err);
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 */
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
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
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) */
965
1037
trx_t* trx = prebuilt->trx;
1174
1245
node = sel_node_create(prebuilt->heap);
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,
1181
1252
prebuilt->sel_graph->state = QUE_FORK_ACTIVE;
1185
/*************************************************************************
1256
/*********************************************************************//**
1186
1257
Creates an query graph node of 'update' type to be used in the MySQL
1259
@return own: update node */
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 */
1196
1267
upd_node_t* node;
1246
1316
prebuilt->upd_node = node;
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,
1252
1322
prebuilt->upd_graph->state = QUE_FORK_ACTIVE;
1255
1325
return(prebuilt->upd_node->update);
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 */
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
1270
1340
trx_savept_t savept;
1404
1483
srv_n_rows_updated++;
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);
1409
1493
trx->op_info = "";
1411
1495
return((int) err);
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
1423
Thus, this implements a 'mini-rollback' that releases the latest record
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 */
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
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. */
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;
1444
1524
ut_ad(prebuilt && trx);
1445
1525
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
1447
if (!(srv_locks_unsafe_for_binlog
1448
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
1528
(!srv_locks_unsafe_for_binlog
1529
&& trx->isolation_level > TRX_ISO_READ_COMMITTED)) {
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");
1473
1557
rec = btr_pcur_get_rec(pcur);
1475
lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1476
rec, prebuilt->select_lock_type);
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
1485
if (dict_index_is_clust(index)) {
1491
index = btr_pcur_get_btr_cur(clust_pcur)->index;
1493
if (index != NULL && trx_new_rec_locks_contain(trx, index)) {
1497
/* Restore the cursor position and find the record */
1499
if (!has_latches_on_recs) {
1500
btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur,
1504
rec = btr_pcur_get_rec(clust_pcur);
1506
lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur),
1507
rec, prebuilt->select_lock_type);
1558
index = btr_pcur_get_btr_cur(pcur)->index;
1560
if (prebuilt->new_rec_locks >= 2) {
1561
/* Restore the cursor position and find the record
1562
in the clustered index. */
1564
if (!has_latches_on_recs) {
1565
btr_pcur_restore_position(BTR_SEARCH_LEAF,
1569
rec = btr_pcur_get_rec(clust_pcur);
1570
index = btr_pcur_get_btr_cur(clust_pcur)->index;
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. */
1579
/* If the record has been modified by this
1580
transaction, do not unlock it. */
1582
if (index->trx_id_offset) {
1583
rec_trx_id = trx_read_trx_id(rec
1584
+ index->trx_id_offset);
1586
mem_heap_t* heap = NULL;
1587
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1588
ulint* offsets = offsets_;
1590
rec_offs_init(offsets_);
1591
offsets = rec_get_offsets(rec, index, offsets,
1592
ULINT_UNDEFINED, &heap);
1594
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
1596
if (UNIV_LIKELY_NULL(heap)) {
1597
mem_heap_free(heap);
1601
if (rec_trx_id != trx->id) {
1602
/* We did not update the record: unlock it */
1604
rec = btr_pcur_get_rec(pcur);
1605
index = btr_pcur_get_btr_cur(pcur)->index;
1607
lock_rec_unlock(trx, btr_pcur_get_block(pcur),
1608
rec, static_cast<lock_mode>(prebuilt->select_lock_type));
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;
1614
lock_rec_unlock(trx,
1615
btr_pcur_get_block(clust_pcur),
1617
static_cast<lock_mode>(prebuilt->select_lock_type));
1513
1624
trx->op_info = "";
1515
1626
return(DB_SUCCESS);
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 */
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 */
1533
1644
trx = thr_get_trx(thr);
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++;
1651
if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) {
1652
return (DB_FOREIGN_EXCEED_MAX_CASCADE);
1535
1655
thr->run_node = node;
1536
1656
thr->prev_node = node;
1538
1658
row_upd_step(thr);
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;
1540
1666
err = trx->error_state;
1542
1668
/* Note that the cascade node is a subnode of another InnoDB
1600
1727
return(dict_index_get_nth_col(clust_index, 0)->mtype == DATA_SYS);
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 */
1608
row_get_mysql_key_number_for_index(
1609
/*===============================*/
1610
const dict_index_t* index)
1612
const dict_index_t* ind;
1618
ind = dict_table_get_first_index(index->table);
1620
while (index != ind) {
1621
ind = dict_table_get_next_index(ind);
1625
if (row_table_got_default_clust_index(index->table)) {
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. */
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 */
1642
1741
ut_a(trx->dict_operation_lock_mode == 0);
1644
rw_lock_s_lock(&dict_operation_lock);
1743
rw_lock_s_lock_func(&dict_operation_lock, 0, file, line);
1646
1745
trx->dict_operation_lock_mode = RW_S_LATCH;
1649
/*************************************************************************
1748
/*********************************************************************//**
1650
1749
Unlocks the data dictionary shared lock. */
1653
1752
row_mysql_unfreeze_data_dictionary(
1654
1753
/*===============================*/
1655
trx_t* trx) /* in: transaction */
1754
trx_t* trx) /*!< in/out: transaction */
1657
1756
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
1661
1760
trx->dict_operation_lock_mode = 0;
1664
/*************************************************************************
1763
/*********************************************************************//**
1665
1764
Locks the data dictionary exclusively for performing a table create or other
1666
1765
data dictionary modification operation. */
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 */
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 */
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;
1682
1783
mutex_enter(&(dict_sys->mutex));
1685
/*************************************************************************
1786
/*********************************************************************//**
1686
1787
Unlocks the data dictionary exclusive lock. */
1689
1790
row_mysql_unlock_data_dictionary(
1690
1791
/*=============================*/
1691
trx_t* trx) /* in: transaction */
1792
trx_t* trx) /*!< in/out: transaction */
1693
1794
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
1701
1802
trx->dict_operation_lock_mode = 0;
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 */
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 */
1720
1820
tab_node_t* node;
1721
1821
mem_heap_t* heap;
1835
1913
thr = pars_complete_graph_for_exec(node, trx, heap);
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);
1840
1918
err = trx->error_state;
1842
if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
1843
trx->error_state = DB_SUCCESS;
1844
trx_general_rollback_for_mysql(trx, FALSE, NULL);
1848
1923
case DB_OUT_OF_FILE_SPACE:
1924
trx->error_state = DB_SUCCESS;
1925
trx_general_rollback_for_mysql(trx, NULL);
1849
1927
ut_print_timestamp(stderr);
1850
1928
fputs(" InnoDB: Warning: cannot create table ",
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"
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"
1886
"http://dev.mysql.com/doc/refman/5.1/en/"
1887
"innodb-troubleshooting.html\n", stderr);
1889
1942
/* We may also get err == DB_ERROR if the .ibd file for the
1890
1943
table already exists */
1945
trx->error_state = DB_SUCCESS;
1946
trx_general_rollback_for_mysql(trx, NULL);
1947
dict_mem_table_free(table);
1899
1955
return((int) err);
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 */
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
2026
2082
return((int) err);
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 */
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. */
2067
2124
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
2069
err = dict_create_foreign_constraints(trx, sql_string, name,
2071
#ifndef UNIV_HOTBACKUP
2126
err = dict_create_foreign_constraints(trx, sql_string, sql_length,
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);
2076
#endif /* !UNIV_HOTBACKUP */
2077
2133
if (err != DB_SUCCESS) {
2078
2134
/* We have special error handling here */
2080
2136
trx->error_state = DB_SUCCESS;
2082
trx_general_rollback_for_mysql(trx, FALSE, NULL);
2138
trx_general_rollback_for_mysql(trx, NULL);
2084
2140
row_drop_table_for_mysql(name, trx, FALSE);
2091
2147
return((int) err);
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
2157
@return error code or DB_SUCCESS */
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 */
2233
2288
return(UT_LIST_GET_LEN(row_mysql_drop_list));
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
2297
@return TRUE if the table was not yet in the drop list, and was added there */
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 */
2250
2304
row_mysql_drop_t* drop;
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 */
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 */
2302
2356
dict_foreign_t* foreign;
2304
2358
dict_table_t* table;
2479
2533
return((int) err);
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 */
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 */
2493
2547
dict_table_t* table;
2777
2831
dict_index_t* index;
2781
if (fil_create_new_single_table_tablespace(
2782
&space, table->name, FALSE, flags,
2833
dict_hdr_get_new_id(NULL, NULL, &space);
2835
/* Lock all index trees for this table. We must
2836
do so after dict_hdr_get_new_id() to preserve
2838
dict_table_x_lock_indexes(table);
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"
2885
2955
mem_heap_free(heap);
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);
2961
dict_hdr_get_new_id(&new_id, NULL, NULL);
2889
2963
info = pars_info_create();
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);
2895
2969
err = que_eval_sql(info,
2896
2970
"PROCEDURE RENUMBER_TABLESPACE_PROC () IS\n"
2943
3020
return((int) err);
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 */
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 */
2962
3039
dict_foreign_t* foreign;
2963
3040
dict_table_t* table;
3039
3116
table = dict_table_get_low(name);
3119
#if defined(BUILD_DRIZZLE)
3122
err = DB_TABLE_NOT_FOUND;
3123
ut_print_timestamp(stderr);
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",
3137
#endif /* BUILD_DRIZZLE */
3043
3138
goto funct_exit;
3119
3214
if (table->n_foreign_key_checks_running > 0) {
3121
const char* table_name = table->name;
3216
const char* i_table_name = table->name;
3124
added = row_add_table_to_background_drop_list(table_name);
3219
added = row_add_table_to_background_drop_list(i_table_name);
3127
3222
ut_print_timestamp(stderr);
3128
3223
fputs(" InnoDB: You are trying to drop table ",
3130
ut_print_name(stderr, trx, TRUE, table_name);
3225
ut_print_name(stderr, trx, TRUE, i_table_name);
3132
3227
"InnoDB: though there is a"
3133
3228
" foreign key check running on it.\n"
3319
3429
trx->op_info = "";
3321
#ifndef UNIV_HOTBACKUP
3322
3431
srv_wake_master_thread();
3323
#endif /* !UNIV_HOTBACKUP */
3325
3433
return((int) err);
3328
/***********************************************************************
3436
/*********************************************************************//**
3437
Drop all temporary tables during crash recovery. */
3440
row_mysql_drop_temp_tables(void)
3441
/*============================*/
3448
trx = trx_allocate_for_background();
3449
trx->op_info = "dropping temporary tables";
3450
row_mysql_lock_data_dictionary(trx);
3452
heap = mem_heap_create(200);
3456
btr_pcur_open_at_index_side(
3458
dict_table_get_first_index(dict_sys->sys_tables),
3459
BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
3465
const char* table_name;
3466
dict_table_t* table;
3468
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
3470
if (!btr_pcur_is_on_user_rec(&pcur)) {
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)) {
3480
/* Because this is not a ROW_FORMAT=REDUNDANT table,
3481
the is_temp flag is valid. Examine it. */
3483
field = rec_get_nth_field_old(rec, 7/*MIX_LEN*/, &len);
3485
|| !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) {
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 */
3496
table_name = mem_heap_strdupl(heap, (const char*) field, len);
3498
btr_pcur_store_position(&pcur, &mtr);
3499
btr_pcur_commit_specify_mtr(&pcur, &mtr);
3501
table = dict_load_table(table_name, TRUE);
3504
row_drop_table_for_mysql(table_name, trx, FALSE);
3505
trx_commit_for_mysql(trx);
3509
btr_pcur_restore_position(BTR_SEARCH_LEAF,
3513
btr_pcur_close(&pcur);
3515
mem_heap_free(heap);
3516
row_mysql_unlock_data_dictionary(trx);
3517
trx_free_for_background(trx);
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 */
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 */
3339
3531
pars_info_t* pinfo;
3482
/*************************************************************************
3678
/*********************************************************************//**
3483
3679
Checks if a table name contains the string "/#sql" which denotes temporary
3681
@return TRUE if temporary table */
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' */
3493
3689
return(strstr(name, "/#sql") != NULL);
3494
3690
/* return(strstr(name, "/@0023sql") != NULL); */
3497
/********************************************************************
3498
Delete a single constraint. */
3693
/****************************************************************//**
3694
Delete a single constraint.
3695
@return error code or DB_SUCCESS */
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 */
3507
3703
pars_info_t* info = pars_info_create();
3517
3713
, FALSE, trx));
3520
/********************************************************************
3521
Delete a single constraint. */
3716
/****************************************************************//**
3717
Delete a single constraint.
3718
@return error code or DB_SUCCESS */
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 */
3550
3746
return((int) err);
3553
/*************************************************************************
3554
Renames a table for MySQL. */
3749
/*********************************************************************//**
3750
Renames a table for MySQL.
3751
@return error code or DB_SUCCESS */
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 */
3565
3761
dict_table_t* table;
3566
3762
ulint err = DB_ERROR;
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. */
4067
in the read view of the current transaction.
4068
@return TRUE if ok */
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
4075
const dict_index_t* index, /*!< in: index */
4076
ulint* n_rows) /*!< out: number of entries
4077
seen in the consistent read */
3891
4079
dtuple_t* prev_entry = NULL;
3892
4080
ulint matched_fields;
3910
buf = mem_alloc(UNIV_PAGE_SIZE);
4098
buf = static_cast<byte *>(mem_alloc(UNIV_PAGE_SIZE));
3911
4099
heap = mem_heap_create(100);
3913
/* Make a dummy template in prebuilt, which we will use
3914
in scanning the index entries */
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;
3922
dtuple_set_n_fields(prebuilt->search_tuple, 0);
3924
prebuilt->select_lock_type = LOCK_NONE;
3927
4103
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
4032
/*************************************************************************
4033
Checks a table for corruption. */
4036
row_check_table_for_mysql(
4037
/*======================*/
4038
/* out: DB_ERROR or DB_SUCCESS */
4039
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
4042
dict_table_t* table = prebuilt->table;
4043
dict_index_t* index;
4045
ulint n_rows_in_table = ULINT_UNDEFINED;
4046
ulint ret = DB_SUCCESS;
4047
ulint old_isolation_level;
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",
4067
prebuilt->trx->op_info = "checking table";
4069
old_isolation_level = prebuilt->trx->isolation_level;
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 */
4076
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
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);
4083
index = dict_table_get_first_index(table);
4085
while (index != NULL) {
4086
/* fputs("Validating index ", stderr);
4087
ut_print_name(stderr, trx, FALSE, index->name);
4088
putc('\n', stderr); */
4090
if (!btr_validate_index(index, prebuilt->trx)) {
4093
if (!row_scan_and_check_index(prebuilt,index, &n_rows)){
4097
if (trx_is_interrupted(prebuilt->trx)) {
4101
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
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) {
4110
fputs("Error: ", stderr);
4111
dict_index_name_print(stderr,
4112
prebuilt->trx, index);
4114
" contains %lu entries,"
4117
(ulong) n_rows_in_table);
4121
index = dict_table_get_next_index(index);
4124
/* Restore the original isolation level */
4125
prebuilt->trx->isolation_level = old_isolation_level;
4127
/* We validate also the whole adaptive hash index for all tables
4128
at every CHECK TABLE */
4130
if (!btr_search_validate()) {
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);
4140
prebuilt->trx->op_info = "";
4144
#endif /* !UNIV_HOTBACKUP */
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 */
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 */
4156
4228
const char* name; /* table_name without database/ */